mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a53f6e9d99 | ||
|
|
e7f4f655e5 | ||
|
|
000ac51ff0 | ||
|
|
23cee388de | ||
|
|
5c73fb318f | ||
|
|
066554393f | ||
|
|
303c0a98cc | ||
|
|
02c62d012f | ||
|
|
a4ec04a499 | ||
|
|
006e382b34 | ||
|
|
beb2593dd9 | ||
|
|
657cbf5c55 | ||
|
|
aff34fa5eb | ||
|
|
22cd8968cb | ||
|
|
ec7efa4d17 | ||
|
|
07fd8c2923 | ||
|
|
a7301e93d9 | ||
|
|
5912a958b3 | ||
|
|
9ca4ae4d8f | ||
|
|
6cd2cea30b | ||
|
|
ba16c8b377 | ||
|
|
d72c5d87be | ||
|
|
dea3a3a41e | ||
|
|
48296990e9 | ||
|
|
289150d415 | ||
|
|
69d49d9dd0 | ||
|
|
e8e813142b | ||
|
|
968705a589 | ||
|
|
1c097491d9 | ||
|
|
0b3ce66cad | ||
|
|
14c77c4926 | ||
|
|
8aadbe4706 | ||
|
|
19d18b96b3 | ||
|
|
59e64a73ff | ||
|
|
8b338dec2d | ||
|
|
bab02222a4 | ||
|
|
9359f523c1 | ||
|
|
e385d2fdec | ||
|
|
49c3d3ff55 | ||
|
|
7b249af944 | ||
|
|
197cec04f3 | ||
|
|
c75baa48f4 | ||
|
|
866aadc8c3 | ||
|
|
276f4a316a | ||
|
|
e65ff5a8dc | ||
|
|
85bfd21257 | ||
|
|
9ebbf957a2 | ||
|
|
00c0418017 | ||
|
|
33a2471338 | ||
|
|
d86fba6945 | ||
|
|
248fe3e4f7 | ||
|
|
9a6dc2b0a0 | ||
|
|
6b9cd2d317 | ||
|
|
f2c98cdb40 | ||
|
|
5635341d12 | ||
|
|
df739f525f | ||
|
|
c8b1c8ed3a | ||
|
|
b0428a1d8b | ||
|
|
c0a96f94fb | ||
|
|
1945b83562 | ||
|
|
dc550f3121 | ||
|
|
0460f2b77b | ||
|
|
b37ed51d07 | ||
|
|
f1183e531d | ||
|
|
16a66112fc | ||
|
|
8aa6ae089a | ||
|
|
728a83a82d | ||
|
|
c05328cd1e | ||
|
|
a9120ed65e | ||
|
|
9305abc784 | ||
|
|
0c637ed80d | ||
|
|
7ee3c5d251 | ||
|
|
a33c99347b | ||
|
|
97cae50bdd | ||
|
|
80360029ef | ||
|
|
af5dbcfcdc | ||
|
|
9dcebb4943 | ||
|
|
e2d9c4cda3 | ||
|
|
3e21887d27 | ||
|
|
d60720aab7 | ||
|
|
2292af6c07 | ||
|
|
ff128f56d2 | ||
|
|
3c01c644c9 | ||
|
|
ade4dc47cd | ||
|
|
cbbbe3a131 | ||
|
|
b385a42b63 | ||
|
|
ccae1d05e7 | ||
|
|
788d994ad7 | ||
|
|
7cf6974b6b | ||
|
|
cf0737ed90 | ||
|
|
75fa495c99 | ||
|
|
7945f0ce63 | ||
|
|
a053315675 | ||
|
|
de0e722f0c | ||
|
|
a42592daa9 | ||
|
|
7f9dc86b23 | ||
|
|
2f5c165aec | ||
|
|
29164ac75d | ||
|
|
185df1735a | ||
|
|
c81e6cccfa | ||
|
|
a2509554db | ||
|
|
b83f77c7c6 | ||
|
|
d8e2e0ac57 |
14
.github/workflows/gradle.yml
vendored
14
.github/workflows/gradle.yml
vendored
@@ -21,14 +21,14 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
- name: Set up JDK 25
|
- name: Set up JDK 27
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v6
|
||||||
with:
|
with:
|
||||||
java-version: '25'
|
java-version: '27'
|
||||||
distribution: 'liberica'
|
distribution: 'liberica'
|
||||||
java-package: 'jdk+fx'
|
java-package: 'jdk+fx'
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v6
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
run: ./gradlew clean build
|
||||||
with:
|
|
||||||
arguments: clean build
|
|
||||||
|
|||||||
29
.github/workflows/nightly.yml
vendored
29
.github/workflows/nightly.yml
vendored
@@ -13,35 +13,36 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Set up JDK 25
|
- name: Set up JDK 27
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v6
|
||||||
with:
|
with:
|
||||||
java-version: '25'
|
# Must match the JDK version downloaded in build.gradle (jdk_download_base) - jlink requires an exact version match
|
||||||
|
java-version: '27.0.0'
|
||||||
distribution: 'liberica'
|
distribution: 'liberica'
|
||||||
java-package: 'jdk+fx'
|
java-package: 'jdk+fx'
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v6
|
||||||
|
|
||||||
- name: Build Linux and Mac releases with Gradle
|
- name: Build Linux and Mac releases with Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
run: ./gradlew runtimeZipOthers -PprojectVersion=nightly
|
||||||
with:
|
|
||||||
arguments: runtimeZipOthers -PprojectVersion=nightly
|
|
||||||
|
|
||||||
- name: Build Windows release with Gradle
|
- name: Build Windows release with Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
run: ./gradlew runtimeZipWindows -PprojectVersion=nightly
|
||||||
with:
|
|
||||||
arguments: runtimeZipWindows -PprojectVersion=nightly
|
|
||||||
|
|
||||||
- name: Create Build Info file
|
- name: Create Build Info file
|
||||||
run: |
|
run: |
|
||||||
echo -e "ref: $GITHUB_REF \ncommit: $GITHUB_SHA\nbuild: $(date +"%Y-%m-%dT%H:%M:%SZ")" > build/image/build_info.txt
|
echo -e "ref: $GITHUB_REF \ncommit: $GITHUB_SHA\nbuild: $(date +"%Y-%m-%dT%H:%M:%SZ")" > build/image/build_info.txt
|
||||||
|
|
||||||
- name: Add build artifacts to nightly release
|
- name: Add build artifacts to nightly release
|
||||||
uses: pyTooling/Actions/releaser@main
|
uses: softprops/action-gh-release@v3
|
||||||
with:
|
with:
|
||||||
tag: nightly
|
tag_name: nightly
|
||||||
rm: false
|
prerelease: true
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
files: |
|
files: |
|
||||||
build/image/*.zip
|
build/image/*.zip
|
||||||
build/image/build_info.txt
|
build/image/build_info.txt
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
130
.github/workflows/release.yml
vendored
Normal file
130
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# Publishes a release when a version tag is pushed. The tag has to match
|
||||||
|
# projectVersion in gradle.properties with a leading 'v': v0.6.2 for a final
|
||||||
|
# release, or v0.6.2-beta-1 / v0.6.2-alpha-1 for a pre-release.
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v[0-9]+.[0-9]+.[0-9]+*']
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
previous_tag: ${{ steps.previous.outputs.tag }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
# Full history and tags, to find the previous release tag for the release notes
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- id: version
|
||||||
|
run: |
|
||||||
|
expected="v$(sed -n 's/^projectVersion=//p' gradle.properties | tr -d '[:space:]')"
|
||||||
|
if [ "$GITHUB_REF_NAME" != "$expected" ]; then
|
||||||
|
echo "::error::Tag $GITHUB_REF_NAME does not match projectVersion in gradle.properties ($expected)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Release notes list the PRs since the previous version tag (never 'nightly'). A final release
|
||||||
|
# starts from the previous final release, so it covers every alpha and beta in between.
|
||||||
|
- id: previous
|
||||||
|
run: |
|
||||||
|
exclude=(--exclude "$GITHUB_REF_NAME")
|
||||||
|
if [[ "$GITHUB_REF_NAME" != *-* ]]; then
|
||||||
|
exclude+=(--exclude '*-*')
|
||||||
|
fi
|
||||||
|
tag="$(git describe --tags --abbrev=0 --match 'v[0-9]*' "${exclude[@]}" HEAD 2>/dev/null || true)"
|
||||||
|
echo "Release notes start from: ${tag:-(GitHub default)}"
|
||||||
|
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Set up JDK 27
|
||||||
|
uses: actions/setup-java@v6
|
||||||
|
with:
|
||||||
|
# Must match the JDK version downloaded in build.gradle (jdk_download_base) - jlink requires an exact version match
|
||||||
|
java-version: '27.0.0'
|
||||||
|
distribution: 'liberica'
|
||||||
|
java-package: 'jdk+fx'
|
||||||
|
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v6
|
||||||
|
|
||||||
|
- name: Build and test
|
||||||
|
run: ./gradlew clean build --console=plain
|
||||||
|
|
||||||
|
# The runtime plugin can't build Windows and the other platforms in the same invocation.
|
||||||
|
- name: Build Linux and Mac releases
|
||||||
|
run: ./gradlew runtimeZipOthers --console=plain
|
||||||
|
|
||||||
|
- name: Build Windows release
|
||||||
|
run: ./gradlew runtimeZipWindows --console=plain
|
||||||
|
|
||||||
|
- name: Check release zips
|
||||||
|
env:
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
||||||
|
run: |
|
||||||
|
missing=0
|
||||||
|
for platform in linux-aarch64 linux-x86_64 osx-aarch64 osx-x86_64 windows-aarch64 windows-x86_64; do
|
||||||
|
zip="build/image/sdr-trunk-${platform}-v${VERSION}.zip"
|
||||||
|
if [ ! -f "$zip" ]; then
|
||||||
|
echo "::error::Missing $zip"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
ls -l build/image/*.zip
|
||||||
|
exit $missing
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: release-zips
|
||||||
|
path: build/image/*.zip
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v8
|
||||||
|
with:
|
||||||
|
name: release-zips
|
||||||
|
path: zips
|
||||||
|
|
||||||
|
# Publishing is split into steps that can all be repeated, so a failed
|
||||||
|
# upload or a re-run finishes the draft left behind rather than failing on
|
||||||
|
# it: gh retries uploads, and a retry of an upload that had in fact
|
||||||
|
# succeeded fails with "ReleaseAsset.name already exists" unless clobbering.
|
||||||
|
- name: Create release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
GH_REPO: ${{ github.repository }}
|
||||||
|
VERSION: ${{ needs.build.outputs.version }}
|
||||||
|
PREVIOUS_TAG: ${{ needs.build.outputs.previous_tag }}
|
||||||
|
run: |
|
||||||
|
(cd zips && sha256sum *.zip > SHA256SUMS)
|
||||||
|
prerelease=()
|
||||||
|
if [[ "$GITHUB_REF_NAME" == *-* ]]; then
|
||||||
|
prerelease=(--prerelease)
|
||||||
|
fi
|
||||||
|
notes_start=()
|
||||||
|
if [ -n "$PREVIOUS_TAG" ]; then
|
||||||
|
notes_start=(--notes-start-tag "$PREVIOUS_TAG")
|
||||||
|
fi
|
||||||
|
if gh release view "$GITHUB_REF_NAME" --json isDraft --jq .isDraft 2>/dev/null | grep -qx false; then
|
||||||
|
echo "::error::Release $GITHUB_REF_NAME is already published"
|
||||||
|
exit 1
|
||||||
|
elif gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
|
||||||
|
echo "Reusing the draft release $GITHUB_REF_NAME"
|
||||||
|
else
|
||||||
|
gh release create "$GITHUB_REF_NAME" --draft "${prerelease[@]}" \
|
||||||
|
--verify-tag --generate-notes "${notes_start[@]}" --title "Version $VERSION"
|
||||||
|
fi
|
||||||
|
gh release upload "$GITHUB_REF_NAME" zips/* --clobber
|
||||||
|
gh release edit "$GITHUB_REF_NAME" --draft=false
|
||||||
45
.idea/misc.xml
generated
45
.idea/misc.xml
generated
@@ -4,7 +4,50 @@
|
|||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25_PREVIEW" project-jdk-name="liberica-25" project-jdk-type="JavaSDK">
|
<component name="NullableNotNullManager">
|
||||||
|
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||||
|
<option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
|
||||||
|
<option name="myOrdered" value="true" />
|
||||||
|
<option name="myNullables">
|
||||||
|
<value>
|
||||||
|
<list size="13">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jspecify.annotations.Nullable" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
|
||||||
|
<item index="6" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||||
|
<item index="7" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||||
|
<item index="8" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||||
|
<item index="9" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
|
||||||
|
<item index="10" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
|
||||||
|
<item index="11" class="java.lang.String" itemvalue="org.springframework.lang.Nullable" />
|
||||||
|
<item index="12" class="java.lang.String" itemvalue="jakarta.annotation.Nullable" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="myNotNulls">
|
||||||
|
<value>
|
||||||
|
<list size="13">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.jspecify.annotations.NonNull" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
|
||||||
|
<item index="6" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||||
|
<item index="7" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||||
|
<item index="8" class="java.lang.String" itemvalue="lombok.NonNull" />
|
||||||
|
<item index="9" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
|
||||||
|
<item index="10" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
|
||||||
|
<item index="11" class="java.lang.String" itemvalue="org.springframework.lang.NonNull" />
|
||||||
|
<item index="12" class="java.lang.String" itemvalue="jakarta.annotation.Nonnull" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_27_PREVIEW" project-jdk-name="liberica-27" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
25
README.md
25
README.md
@@ -49,3 +49,28 @@ committed to the code base, so it's not really 'nightly' as much as it is 'curre
|
|||||||
* **Operating System:** Windows (~~32 or~~ 64-bit), Linux (~~32 or~~ 64-bit) or Mac (64-bit, 12.x or higher)
|
* **Operating System:** Windows (~~32 or~~ 64-bit), Linux (~~32 or~~ 64-bit) or Mac (64-bit, 12.x or higher)
|
||||||
* **CPU:** 4-core
|
* **CPU:** 4-core
|
||||||
* **RAM:** 8GB or more (preferred). Depending on usage, 4GB may be sufficient.
|
* **RAM:** 8GB or more (preferred). Depending on usage, 4GB may be sufficient.
|
||||||
|
|
||||||
|
## Creating a Release (Maintainers)
|
||||||
|
Releases are built and published automatically by the [Release](.github/workflows/release.yml) GitHub workflow
|
||||||
|
whenever a version tag is pushed to the repository.
|
||||||
|
|
||||||
|
1. Update `projectVersion` in `gradle.properties` to the new version, following the naming convention described in
|
||||||
|
that file (e.g. `0.6.2-alpha-1`, `0.6.2-beta-1` or `0.6.2`).
|
||||||
|
2. Commit and push the change to `master`.
|
||||||
|
3. Create and push a tag that matches the version with a leading `v`:
|
||||||
|
```
|
||||||
|
git tag v0.6.2-beta-1
|
||||||
|
git push origin v0.6.2-beta-1
|
||||||
|
```
|
||||||
|
|
||||||
|
The workflow then:
|
||||||
|
* Verifies that the tag matches `projectVersion` in `gradle.properties` and fails if it does not.
|
||||||
|
* Builds and tests the code, then creates the release zips for Linux, Mac and Windows (x86-64 and aarch64).
|
||||||
|
* Creates a GitHub release titled `Version <version>` with auto-generated release notes (a "What's Changed" list of
|
||||||
|
the PRs merged since the previous version tag), and attaches the six zip
|
||||||
|
files plus a `SHA256SUMS` checksum file.
|
||||||
|
* Marks tags containing a dash (alpha and beta versions) as pre-releases. Tags without a dash become full releases.
|
||||||
|
|
||||||
|
If the workflow fails part way through, fix the problem and re-run it from the Actions tab. It resumes from the
|
||||||
|
draft release left behind. It won't modify a release that has already been published. To rebuild a published
|
||||||
|
release, delete the release and the tag on GitHub, then push the tag again.
|
||||||
|
|||||||
@@ -1,229 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_H
|
|
||||||
#define SDRPLAY_API_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_dev.h"
|
|
||||||
#include "sdrplay_api_rx_channel.h"
|
|
||||||
#include "sdrplay_api_callback.h"
|
|
||||||
|
|
||||||
//#if defined(_M_X64) || defined(_M_IX86)
|
|
||||||
//#include "windows.h"
|
|
||||||
//#elif defined (__GNUC__)
|
|
||||||
typedef void *HANDLE;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#ifndef _SDRPLAY_DLL_QUALIFIER
|
|
||||||
//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86))
|
|
||||||
//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
|
||||||
//#elif defined(STATIC_LIB) || defined(__GNUC__)
|
|
||||||
//#define _SDRPLAY_DLL_QUALIFIER
|
|
||||||
//#endif
|
|
||||||
//#endif // _SDRPLAY_DLL_QUALIFIER
|
|
||||||
|
|
||||||
// Application code should check that it is compiled against the same API version
|
|
||||||
// sdrplay_api_ApiVersion() returns the API version
|
|
||||||
#define SDRPLAY_API_VERSION (float)(3.07)
|
|
||||||
|
|
||||||
// API Constants
|
|
||||||
#define SDRPLAY_MAX_DEVICES (16)
|
|
||||||
#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
|
|
||||||
|
|
||||||
#define SDRPLAY_MAX_SER_NO_LEN (64)
|
|
||||||
#define SDRPLAY_MAX_ROOT_NM_LEN (32)
|
|
||||||
|
|
||||||
#define SDRPLAY_RSP1_ID (1)
|
|
||||||
#define SDRPLAY_RSP1A_ID (255)
|
|
||||||
#define SDRPLAY_RSP2_ID (2)
|
|
||||||
#define SDRPLAY_RSPduo_ID (3)
|
|
||||||
#define SDRPLAY_RSPdx_ID (4)
|
|
||||||
|
|
||||||
// Enum types
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Success = 0,
|
|
||||||
sdrplay_api_Fail = 1,
|
|
||||||
sdrplay_api_InvalidParam = 2,
|
|
||||||
sdrplay_api_OutOfRange = 3,
|
|
||||||
sdrplay_api_GainUpdateError = 4,
|
|
||||||
sdrplay_api_RfUpdateError = 5,
|
|
||||||
sdrplay_api_FsUpdateError = 6,
|
|
||||||
sdrplay_api_HwError = 7,
|
|
||||||
sdrplay_api_AliasingError = 8,
|
|
||||||
sdrplay_api_AlreadyInitialised = 9,
|
|
||||||
sdrplay_api_NotInitialised = 10,
|
|
||||||
sdrplay_api_NotEnabled = 11,
|
|
||||||
sdrplay_api_HwVerError = 12,
|
|
||||||
sdrplay_api_OutOfMemError = 13,
|
|
||||||
sdrplay_api_ServiceNotResponding = 14,
|
|
||||||
sdrplay_api_StartPending = 15,
|
|
||||||
sdrplay_api_StopPending = 16,
|
|
||||||
sdrplay_api_InvalidMode = 17,
|
|
||||||
sdrplay_api_FailedVerification1 = 18,
|
|
||||||
sdrplay_api_FailedVerification2 = 19,
|
|
||||||
sdrplay_api_FailedVerification3 = 20,
|
|
||||||
sdrplay_api_FailedVerification4 = 21,
|
|
||||||
sdrplay_api_FailedVerification5 = 22,
|
|
||||||
sdrplay_api_FailedVerification6 = 23,
|
|
||||||
sdrplay_api_InvalidServiceVersion = 24
|
|
||||||
} sdrplay_api_ErrT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_Dev_Fs = 0x00000001,
|
|
||||||
sdrplay_api_Update_Dev_Ppm = 0x00000002,
|
|
||||||
sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
|
|
||||||
sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
|
|
||||||
sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
|
|
||||||
sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
|
|
||||||
sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
|
|
||||||
sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Master_Spare_1 = 0x00002000,
|
|
||||||
sdrplay_api_Update_Master_Spare_2 = 0x00004000,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
// Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
|
|
||||||
sdrplay_api_Update_Tuner_Gr = 0x00008000,
|
|
||||||
sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
|
|
||||||
sdrplay_api_Update_Tuner_Frf = 0x00020000,
|
|
||||||
sdrplay_api_Update_Tuner_BwType = 0x00040000,
|
|
||||||
sdrplay_api_Update_Tuner_IfType = 0x00080000,
|
|
||||||
sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
|
|
||||||
sdrplay_api_Update_Tuner_LoMode = 0x00200000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
|
|
||||||
sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
|
|
||||||
sdrplay_api_Update_Ctrl_Agc = 0x01000000,
|
|
||||||
sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
|
|
||||||
sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
|
|
||||||
sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
|
|
||||||
sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
|
|
||||||
} sdrplay_api_ReasonForUpdateT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_Ext1_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
|
|
||||||
sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
|
|
||||||
sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
|
|
||||||
sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
|
|
||||||
sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
} sdrplay_api_ReasonForUpdateExtension1T;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_DbgLvl_Disable = 0,
|
|
||||||
sdrplay_api_DbgLvl_Verbose = 1,
|
|
||||||
sdrplay_api_DbgLvl_Warning = 2,
|
|
||||||
sdrplay_api_DbgLvl_Error = 3,
|
|
||||||
sdrplay_api_DbgLvl_Message = 4,
|
|
||||||
} sdrplay_api_DbgLvl_t;
|
|
||||||
|
|
||||||
// Device structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char SerNo[SDRPLAY_MAX_SER_NO_LEN];
|
|
||||||
unsigned char hwVer;
|
|
||||||
sdrplay_api_TunerSelectT tuner;
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode;
|
|
||||||
double rspDuoSampleFreq;
|
|
||||||
HANDLE dev;
|
|
||||||
} sdrplay_api_DeviceT;
|
|
||||||
|
|
||||||
// Device parameter structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DevParamsT *devParams;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelA;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelB;
|
|
||||||
} sdrplay_api_DeviceParamsT;
|
|
||||||
|
|
||||||
// Extended error message structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char file[256];
|
|
||||||
char function[256];
|
|
||||||
int line;
|
|
||||||
char message[1024];
|
|
||||||
} sdrplay_api_ErrorInfoT;
|
|
||||||
|
|
||||||
// Comman API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
|
|
||||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
|
|
||||||
|
|
||||||
// Device API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
// API function definitions
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comman API function definitions
|
|
||||||
sdrplay_api_ErrT sdrplay_api_Open(void);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_Close(void);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
|
|
||||||
const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
|
|
||||||
sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
|
|
||||||
|
|
||||||
// Device API function definitions
|
|
||||||
sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate);
|
|
||||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_H
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CALLBACK_H
|
|
||||||
#define SDRPLAY_API_CALLBACK_H
|
|
||||||
|
|
||||||
// Event callback enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Overload_Detected = 0,
|
|
||||||
sdrplay_api_Overload_Corrected = 1,
|
|
||||||
} sdrplay_api_PowerOverloadCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_MasterInitialised = 0,
|
|
||||||
sdrplay_api_SlaveAttached = 1,
|
|
||||||
sdrplay_api_SlaveDetached = 2,
|
|
||||||
sdrplay_api_SlaveInitialised = 3,
|
|
||||||
sdrplay_api_SlaveUninitialised = 4,
|
|
||||||
sdrplay_api_MasterDllDisappeared = 5,
|
|
||||||
sdrplay_api_SlaveDllDisappeared = 6,
|
|
||||||
} sdrplay_api_RspDuoModeCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_GainChange = 0,
|
|
||||||
sdrplay_api_PowerOverloadChange = 1,
|
|
||||||
sdrplay_api_DeviceRemoved = 2,
|
|
||||||
sdrplay_api_RspDuoModeChange = 3,
|
|
||||||
} sdrplay_api_EventT;
|
|
||||||
|
|
||||||
// Event callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int gRdB;
|
|
||||||
unsigned int lnaGRdB;
|
|
||||||
double currGain;
|
|
||||||
} sdrplay_api_GainCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
|
|
||||||
} sdrplay_api_PowerOverloadCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
|
|
||||||
} sdrplay_api_RspDuoModeCbParamT;
|
|
||||||
|
|
||||||
// Event parameters overlay
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
sdrplay_api_GainCbParamT gainParams;
|
|
||||||
sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
|
|
||||||
sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
|
|
||||||
} sdrplay_api_EventParamsT;
|
|
||||||
|
|
||||||
// Stream callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int firstSampleNum;
|
|
||||||
int grChanged;
|
|
||||||
int rfChanged;
|
|
||||||
int fsChanged;
|
|
||||||
unsigned int numSamples;
|
|
||||||
} sdrplay_api_StreamCbParamsT;
|
|
||||||
|
|
||||||
// Callback function prototypes
|
|
||||||
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
|
|
||||||
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
|
|
||||||
|
|
||||||
// Callback function struct
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_StreamCallback_t StreamACbFn;
|
|
||||||
sdrplay_api_StreamCallback_t StreamBCbFn;
|
|
||||||
sdrplay_api_EventCallback_t EventCbFn;
|
|
||||||
} sdrplay_api_CallbackFnsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CALLBACK_H
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CONTROL_H
|
|
||||||
#define SDRPLAY_API_CONTROL_H
|
|
||||||
|
|
||||||
// Control parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_AGC_DISABLE = 0,
|
|
||||||
sdrplay_api_AGC_100HZ = 1,
|
|
||||||
sdrplay_api_AGC_50HZ = 2,
|
|
||||||
sdrplay_api_AGC_5HZ = 3,
|
|
||||||
sdrplay_api_AGC_CTRL_EN = 4
|
|
||||||
} sdrplay_api_AgcControlT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ADSB_DECIMATION = 0,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
|
|
||||||
} sdrplay_api_AdsbModeT;
|
|
||||||
|
|
||||||
// Control parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char DCenable; // default: 1
|
|
||||||
unsigned char IQenable; // default: 1
|
|
||||||
} sdrplay_api_DcOffsetT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char enable; // default: 0
|
|
||||||
unsigned char decimationFactor; // default: 1
|
|
||||||
unsigned char wideBandSignal; // default: 0
|
|
||||||
} sdrplay_api_DecimationT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
|
|
||||||
int setPoint_dBfs; // default: -60
|
|
||||||
unsigned short attack_ms; // default: 0
|
|
||||||
unsigned short decay_ms; // default: 0
|
|
||||||
unsigned short decay_delay_ms; // default: 0
|
|
||||||
unsigned short decay_threshold_dB; // default: 0
|
|
||||||
int syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_AgcT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DcOffsetT dcOffset;
|
|
||||||
sdrplay_api_DecimationT decimation;
|
|
||||||
sdrplay_api_AgcT agc;
|
|
||||||
sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
|
|
||||||
} sdrplay_api_ControlParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CONTROL_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_DEV_H
|
|
||||||
#define SDRPLAY_API_DEV_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
// Dev parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ISOCH = 0,
|
|
||||||
sdrplay_api_BULK = 1
|
|
||||||
} sdrplay_api_TransferModeT;
|
|
||||||
|
|
||||||
// Dev parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double fsHz; // default: 2000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
unsigned char reCal; // default: 0
|
|
||||||
} sdrplay_api_FsFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int sampleNum; // default: 0
|
|
||||||
unsigned int period; // default: 0
|
|
||||||
} sdrplay_api_SyncUpdateT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char resetGainUpdate; // default: 0
|
|
||||||
unsigned char resetRfUpdate; // default: 0
|
|
||||||
unsigned char resetFsUpdate; // default: 0
|
|
||||||
} sdrplay_api_ResetFlagsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double ppm; // default: 0.0
|
|
||||||
sdrplay_api_FsFreqT fsFreq;
|
|
||||||
sdrplay_api_SyncUpdateT syncUpdate;
|
|
||||||
sdrplay_api_ResetFlagsT resetFlags;
|
|
||||||
sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
|
|
||||||
unsigned int samplesPerPkt; // default: 0 (output param)
|
|
||||||
sdrplay_api_Rsp1aParamsT rsp1aParams;
|
|
||||||
sdrplay_api_Rsp2ParamsT rsp2Params;
|
|
||||||
sdrplay_api_RspDuoParamsT rspDuoParams;
|
|
||||||
sdrplay_api_RspDxParamsT rspDxParams;
|
|
||||||
} sdrplay_api_DevParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_DEV_H
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP1A_H
|
|
||||||
#define SDRPLAY_API_RSP1A_H
|
|
||||||
|
|
||||||
#define RSPIA_NUM_LNA_STATES 10
|
|
||||||
#define RSPIA_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPIA_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSP1A parameter enums
|
|
||||||
|
|
||||||
// RSP1A parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP1A_H
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP2_H
|
|
||||||
#define SDRPLAY_API_RSP2_H
|
|
||||||
|
|
||||||
#define RSPII_NUM_LNA_STATES 9
|
|
||||||
#define RSPII_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPII_NUM_LNA_STATES_420MHZ 6
|
|
||||||
|
|
||||||
// RSP2 parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_A = 5,
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_B = 6,
|
|
||||||
} sdrplay_api_Rsp2_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_Rsp2_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_Rsp2_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSP2 parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_Rsp2ParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
|
|
||||||
sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp2TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP2_H
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPduo_H
|
|
||||||
#define SDRPLAY_API_RSPduo_H
|
|
||||||
|
|
||||||
#define RSPDUO_NUM_LNA_STATES 10
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSPduo parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoMode_Unknown = 0,
|
|
||||||
sdrplay_api_RspDuoMode_Single_Tuner = 1,
|
|
||||||
sdrplay_api_RspDuoMode_Dual_Tuner = 2,
|
|
||||||
sdrplay_api_RspDuoMode_Master = 4,
|
|
||||||
sdrplay_api_RspDuoMode_Slave = 8,
|
|
||||||
} sdrplay_api_RspDuoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuo_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_RspDuo_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_RspDuo_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSPduo parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_RspDuoParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
|
|
||||||
unsigned char tuner1AmNotchEnable; // default: 0
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_RspDuoTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPduo_H
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPDX_H
|
|
||||||
#define SDRPLAY_API_RSPDX_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
|
|
||||||
#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_12_60 20 // Number of LNA states when using AM Port 2 between 12 and 60MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
|
|
||||||
#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_DX 26 // Number of LNA states in DX path
|
|
||||||
|
|
||||||
// RSPdx parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_ANTENNA_A = 0,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_B = 1,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_C = 2,
|
|
||||||
} sdrplay_api_RspDx_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
|
|
||||||
} sdrplay_api_RspDx_HdrModeBwT;
|
|
||||||
|
|
||||||
// RSPdx parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char hdrEnable; // default: 0
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_RspDxParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
|
|
||||||
} sdrplay_api_RspDxTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPDX_H
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
#define SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
#include "sdrplay_api_control.h"
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_TunerParamsT tunerParams;
|
|
||||||
sdrplay_api_ControlParamsT ctrlParams;
|
|
||||||
sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
|
|
||||||
sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
|
|
||||||
sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
|
|
||||||
sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
|
|
||||||
} sdrplay_api_RxChannelParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_TUNER_H
|
|
||||||
#define SDRPLAY_API_TUNER_H
|
|
||||||
|
|
||||||
#define MAX_BB_GR (59)
|
|
||||||
|
|
||||||
// Tuner parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_BW_Undefined = 0,
|
|
||||||
sdrplay_api_BW_0_200 = 200,
|
|
||||||
sdrplay_api_BW_0_300 = 300,
|
|
||||||
sdrplay_api_BW_0_600 = 600,
|
|
||||||
sdrplay_api_BW_1_536 = 1536,
|
|
||||||
sdrplay_api_BW_5_000 = 5000,
|
|
||||||
sdrplay_api_BW_6_000 = 6000,
|
|
||||||
sdrplay_api_BW_7_000 = 7000,
|
|
||||||
sdrplay_api_BW_8_000 = 8000
|
|
||||||
} sdrplay_api_Bw_MHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_IF_Undefined = -1,
|
|
||||||
sdrplay_api_IF_Zero = 0,
|
|
||||||
sdrplay_api_IF_0_450 = 450,
|
|
||||||
sdrplay_api_IF_1_620 = 1620,
|
|
||||||
sdrplay_api_IF_2_048 = 2048
|
|
||||||
} sdrplay_api_If_kHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_LO_Undefined = 0,
|
|
||||||
sdrplay_api_LO_Auto = 1,
|
|
||||||
sdrplay_api_LO_120MHz = 2,
|
|
||||||
sdrplay_api_LO_144MHz = 3,
|
|
||||||
sdrplay_api_LO_168MHz = 4
|
|
||||||
} sdrplay_api_LoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_EXTENDED_MIN_GR = 0,
|
|
||||||
sdrplay_api_NORMAL_MIN_GR = 20
|
|
||||||
} sdrplay_api_MinGainReductionT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Tuner_Neither = 0,
|
|
||||||
sdrplay_api_Tuner_A = 1,
|
|
||||||
sdrplay_api_Tuner_B = 2,
|
|
||||||
sdrplay_api_Tuner_Both = 3,
|
|
||||||
} sdrplay_api_TunerSelectT;
|
|
||||||
|
|
||||||
// Tuner parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float curr;
|
|
||||||
float max;
|
|
||||||
float min;
|
|
||||||
} sdrplay_api_GainValuesT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int gRdB; // default: 50
|
|
||||||
unsigned char LNAstate; // default: 0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
|
|
||||||
sdrplay_api_GainValuesT gainVals; // output parameter
|
|
||||||
} sdrplay_api_GainT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double rfHz; // default: 200000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_RfFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char dcCal; // default: 3 (Periodic mode)
|
|
||||||
unsigned char speedUp; // default: 0 (No speedup)
|
|
||||||
int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
|
|
||||||
int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
|
|
||||||
} sdrplay_api_DcOffsetTunerT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
|
|
||||||
sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
|
|
||||||
sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
|
|
||||||
sdrplay_api_GainT gain;
|
|
||||||
sdrplay_api_RfFreqT rfFreq;
|
|
||||||
sdrplay_api_DcOffsetTunerT dcOffsetTuner;
|
|
||||||
} sdrplay_api_TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_TUNER_H
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_H
|
|
||||||
#define SDRPLAY_API_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_dev.h"
|
|
||||||
#include "sdrplay_api_rx_channel.h"
|
|
||||||
#include "sdrplay_api_callback.h"
|
|
||||||
|
|
||||||
//#if defined(_M_X64) || defined(_M_IX86)
|
|
||||||
//#include "windows.h"
|
|
||||||
//#elif defined (__GNUC__)
|
|
||||||
typedef void *HANDLE;
|
|
||||||
//#endif
|
|
||||||
//
|
|
||||||
//#ifndef _SDRPLAY_DLL_QUALIFIER
|
|
||||||
//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86))
|
|
||||||
//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
|
||||||
//#elif defined(STATIC_LIB) || defined(__GNUC__)
|
|
||||||
//#define _SDRPLAY_DLL_QUALIFIER
|
|
||||||
//#endif
|
|
||||||
//#endif // _SDRPLAY_DLL_QUALIFIER
|
|
||||||
|
|
||||||
// Application code should check that it is compiled against the same API version
|
|
||||||
// sdrplay_api_ApiVersion() returns the API version
|
|
||||||
#define SDRPLAY_API_VERSION (float)(3.08)
|
|
||||||
|
|
||||||
// API Constants
|
|
||||||
#define SDRPLAY_MAX_DEVICES (16)
|
|
||||||
#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
|
|
||||||
|
|
||||||
#define SDRPLAY_MAX_SER_NO_LEN (64)
|
|
||||||
#define SDRPLAY_MAX_ROOT_NM_LEN (32)
|
|
||||||
|
|
||||||
#define SDRPLAY_RSP1_ID (1)
|
|
||||||
#define SDRPLAY_RSP1A_ID (255)
|
|
||||||
#define SDRPLAY_RSP2_ID (2)
|
|
||||||
#define SDRPLAY_RSPduo_ID (3)
|
|
||||||
#define SDRPLAY_RSPdx_ID (4)
|
|
||||||
|
|
||||||
// Enum types
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Success = 0,
|
|
||||||
sdrplay_api_Fail = 1,
|
|
||||||
sdrplay_api_InvalidParam = 2,
|
|
||||||
sdrplay_api_OutOfRange = 3,
|
|
||||||
sdrplay_api_GainUpdateError = 4,
|
|
||||||
sdrplay_api_RfUpdateError = 5,
|
|
||||||
sdrplay_api_FsUpdateError = 6,
|
|
||||||
sdrplay_api_HwError = 7,
|
|
||||||
sdrplay_api_AliasingError = 8,
|
|
||||||
sdrplay_api_AlreadyInitialised = 9,
|
|
||||||
sdrplay_api_NotInitialised = 10,
|
|
||||||
sdrplay_api_NotEnabled = 11,
|
|
||||||
sdrplay_api_HwVerError = 12,
|
|
||||||
sdrplay_api_OutOfMemError = 13,
|
|
||||||
sdrplay_api_ServiceNotResponding = 14,
|
|
||||||
sdrplay_api_StartPending = 15,
|
|
||||||
sdrplay_api_StopPending = 16,
|
|
||||||
sdrplay_api_InvalidMode = 17,
|
|
||||||
sdrplay_api_FailedVerification1 = 18,
|
|
||||||
sdrplay_api_FailedVerification2 = 19,
|
|
||||||
sdrplay_api_FailedVerification3 = 20,
|
|
||||||
sdrplay_api_FailedVerification4 = 21,
|
|
||||||
sdrplay_api_FailedVerification5 = 22,
|
|
||||||
sdrplay_api_FailedVerification6 = 23,
|
|
||||||
sdrplay_api_InvalidServiceVersion = 24
|
|
||||||
} sdrplay_api_ErrT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_Dev_Fs = 0x00000001,
|
|
||||||
sdrplay_api_Update_Dev_Ppm = 0x00000002,
|
|
||||||
sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
|
|
||||||
sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
|
|
||||||
sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
|
|
||||||
sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
|
|
||||||
sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
|
|
||||||
sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Master_Spare_1 = 0x00002000,
|
|
||||||
sdrplay_api_Update_Master_Spare_2 = 0x00004000,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
// Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
|
|
||||||
sdrplay_api_Update_Tuner_Gr = 0x00008000,
|
|
||||||
sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
|
|
||||||
sdrplay_api_Update_Tuner_Frf = 0x00020000,
|
|
||||||
sdrplay_api_Update_Tuner_BwType = 0x00040000,
|
|
||||||
sdrplay_api_Update_Tuner_IfType = 0x00080000,
|
|
||||||
sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
|
|
||||||
sdrplay_api_Update_Tuner_LoMode = 0x00200000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
|
|
||||||
sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
|
|
||||||
sdrplay_api_Update_Ctrl_Agc = 0x01000000,
|
|
||||||
sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
|
|
||||||
sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
|
|
||||||
sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
|
|
||||||
sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
|
|
||||||
} sdrplay_api_ReasonForUpdateT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_Ext1_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
|
|
||||||
sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
|
|
||||||
sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
|
|
||||||
sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
|
|
||||||
sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
} sdrplay_api_ReasonForUpdateExtension1T;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_DbgLvl_Disable = 0,
|
|
||||||
sdrplay_api_DbgLvl_Verbose = 1,
|
|
||||||
sdrplay_api_DbgLvl_Warning = 2,
|
|
||||||
sdrplay_api_DbgLvl_Error = 3,
|
|
||||||
sdrplay_api_DbgLvl_Message = 4,
|
|
||||||
} sdrplay_api_DbgLvl_t;
|
|
||||||
|
|
||||||
// Device structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char SerNo[SDRPLAY_MAX_SER_NO_LEN];
|
|
||||||
unsigned char hwVer;
|
|
||||||
sdrplay_api_TunerSelectT tuner;
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode;
|
|
||||||
unsigned char valid;
|
|
||||||
double rspDuoSampleFreq;
|
|
||||||
HANDLE dev;
|
|
||||||
} sdrplay_api_DeviceT;
|
|
||||||
|
|
||||||
// Device parameter structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DevParamsT *devParams;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelA;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelB;
|
|
||||||
} sdrplay_api_DeviceParamsT;
|
|
||||||
|
|
||||||
// Extended error message structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char file[256];
|
|
||||||
char function[256];
|
|
||||||
int line;
|
|
||||||
char message[1024];
|
|
||||||
} sdrplay_api_ErrorInfoT;
|
|
||||||
|
|
||||||
// Comman API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
|
|
||||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
|
|
||||||
|
|
||||||
// Device API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate, double newSampleRate);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
// API function definitions
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// // Comman API function definitions
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Open(void);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Close(void);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
|
|
||||||
//
|
|
||||||
// // Device API function definitions
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate, double newSampleRate);
|
|
||||||
// _SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
// sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
// sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_H
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CALLBACK_H
|
|
||||||
#define SDRPLAY_API_CALLBACK_H
|
|
||||||
|
|
||||||
// Event callback enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Overload_Detected = 0,
|
|
||||||
sdrplay_api_Overload_Corrected = 1,
|
|
||||||
} sdrplay_api_PowerOverloadCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_MasterInitialised = 0,
|
|
||||||
sdrplay_api_SlaveAttached = 1,
|
|
||||||
sdrplay_api_SlaveDetached = 2,
|
|
||||||
sdrplay_api_SlaveInitialised = 3,
|
|
||||||
sdrplay_api_SlaveUninitialised = 4,
|
|
||||||
sdrplay_api_MasterDllDisappeared = 5,
|
|
||||||
sdrplay_api_SlaveDllDisappeared = 6,
|
|
||||||
} sdrplay_api_RspDuoModeCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_GainChange = 0,
|
|
||||||
sdrplay_api_PowerOverloadChange = 1,
|
|
||||||
sdrplay_api_DeviceRemoved = 2,
|
|
||||||
sdrplay_api_RspDuoModeChange = 3,
|
|
||||||
} sdrplay_api_EventT;
|
|
||||||
|
|
||||||
// Event callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int gRdB;
|
|
||||||
unsigned int lnaGRdB;
|
|
||||||
double currGain;
|
|
||||||
} sdrplay_api_GainCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
|
|
||||||
} sdrplay_api_PowerOverloadCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
|
|
||||||
} sdrplay_api_RspDuoModeCbParamT;
|
|
||||||
|
|
||||||
// Event parameters overlay
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
sdrplay_api_GainCbParamT gainParams;
|
|
||||||
sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
|
|
||||||
sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
|
|
||||||
} sdrplay_api_EventParamsT;
|
|
||||||
|
|
||||||
// Stream callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int firstSampleNum;
|
|
||||||
int grChanged;
|
|
||||||
int rfChanged;
|
|
||||||
int fsChanged;
|
|
||||||
unsigned int numSamples;
|
|
||||||
} sdrplay_api_StreamCbParamsT;
|
|
||||||
|
|
||||||
// Callback function prototypes
|
|
||||||
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
|
|
||||||
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
|
|
||||||
|
|
||||||
// Callback function struct
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_StreamCallback_t StreamACbFn;
|
|
||||||
sdrplay_api_StreamCallback_t StreamBCbFn;
|
|
||||||
sdrplay_api_EventCallback_t EventCbFn;
|
|
||||||
} sdrplay_api_CallbackFnsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CALLBACK_H
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CONTROL_H
|
|
||||||
#define SDRPLAY_API_CONTROL_H
|
|
||||||
|
|
||||||
// Control parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_AGC_DISABLE = 0,
|
|
||||||
sdrplay_api_AGC_100HZ = 1,
|
|
||||||
sdrplay_api_AGC_50HZ = 2,
|
|
||||||
sdrplay_api_AGC_5HZ = 3,
|
|
||||||
sdrplay_api_AGC_CTRL_EN = 4
|
|
||||||
} sdrplay_api_AgcControlT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ADSB_DECIMATION = 0,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
|
|
||||||
} sdrplay_api_AdsbModeT;
|
|
||||||
|
|
||||||
// Control parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char DCenable; // default: 1
|
|
||||||
unsigned char IQenable; // default: 1
|
|
||||||
} sdrplay_api_DcOffsetT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char enable; // default: 0
|
|
||||||
unsigned char decimationFactor; // default: 1
|
|
||||||
unsigned char wideBandSignal; // default: 0
|
|
||||||
} sdrplay_api_DecimationT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
|
|
||||||
int setPoint_dBfs; // default: -60
|
|
||||||
unsigned short attack_ms; // default: 0
|
|
||||||
unsigned short decay_ms; // default: 0
|
|
||||||
unsigned short decay_delay_ms; // default: 0
|
|
||||||
unsigned short decay_threshold_dB; // default: 0
|
|
||||||
int syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_AgcT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DcOffsetT dcOffset;
|
|
||||||
sdrplay_api_DecimationT decimation;
|
|
||||||
sdrplay_api_AgcT agc;
|
|
||||||
sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
|
|
||||||
} sdrplay_api_ControlParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CONTROL_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_DEV_H
|
|
||||||
#define SDRPLAY_API_DEV_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
// Dev parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ISOCH = 0,
|
|
||||||
sdrplay_api_BULK = 1
|
|
||||||
} sdrplay_api_TransferModeT;
|
|
||||||
|
|
||||||
// Dev parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double fsHz; // default: 2000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
unsigned char reCal; // default: 0
|
|
||||||
} sdrplay_api_FsFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int sampleNum; // default: 0
|
|
||||||
unsigned int period; // default: 0
|
|
||||||
} sdrplay_api_SyncUpdateT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char resetGainUpdate; // default: 0
|
|
||||||
unsigned char resetRfUpdate; // default: 0
|
|
||||||
unsigned char resetFsUpdate; // default: 0
|
|
||||||
} sdrplay_api_ResetFlagsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double ppm; // default: 0.0
|
|
||||||
sdrplay_api_FsFreqT fsFreq;
|
|
||||||
sdrplay_api_SyncUpdateT syncUpdate;
|
|
||||||
sdrplay_api_ResetFlagsT resetFlags;
|
|
||||||
sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
|
|
||||||
unsigned int samplesPerPkt; // default: 0 (output param)
|
|
||||||
sdrplay_api_Rsp1aParamsT rsp1aParams;
|
|
||||||
sdrplay_api_Rsp2ParamsT rsp2Params;
|
|
||||||
sdrplay_api_RspDuoParamsT rspDuoParams;
|
|
||||||
sdrplay_api_RspDxParamsT rspDxParams;
|
|
||||||
} sdrplay_api_DevParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_DEV_H
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP1A_H
|
|
||||||
#define SDRPLAY_API_RSP1A_H
|
|
||||||
|
|
||||||
#define RSPIA_NUM_LNA_STATES 10
|
|
||||||
#define RSPIA_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPIA_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSP1A parameter enums
|
|
||||||
|
|
||||||
// RSP1A parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP1A_H
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP2_H
|
|
||||||
#define SDRPLAY_API_RSP2_H
|
|
||||||
|
|
||||||
#define RSPII_NUM_LNA_STATES 9
|
|
||||||
#define RSPII_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPII_NUM_LNA_STATES_420MHZ 6
|
|
||||||
|
|
||||||
// RSP2 parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_A = 5,
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_B = 6,
|
|
||||||
} sdrplay_api_Rsp2_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_Rsp2_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_Rsp2_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSP2 parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_Rsp2ParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
|
|
||||||
sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp2TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP2_H
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPduo_H
|
|
||||||
#define SDRPLAY_API_RSPduo_H
|
|
||||||
|
|
||||||
#define RSPDUO_NUM_LNA_STATES 10
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSPduo parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoMode_Unknown = 0,
|
|
||||||
sdrplay_api_RspDuoMode_Single_Tuner = 1,
|
|
||||||
sdrplay_api_RspDuoMode_Dual_Tuner = 2,
|
|
||||||
sdrplay_api_RspDuoMode_Master = 4,
|
|
||||||
sdrplay_api_RspDuoMode_Slave = 8,
|
|
||||||
} sdrplay_api_RspDuoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuo_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_RspDuo_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_RspDuo_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSPduo parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_RspDuoParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
|
|
||||||
unsigned char tuner1AmNotchEnable; // default: 0
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_RspDuoTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPduo_H
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPDX_H
|
|
||||||
#define SDRPLAY_API_RSPDX_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
|
|
||||||
#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_12_60 20 // Number of LNA states when using AM Port 2 between 12 and 60MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
|
|
||||||
#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_DX 26 // Number of LNA states in DX path
|
|
||||||
|
|
||||||
// RSPdx parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_ANTENNA_A = 0,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_B = 1,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_C = 2,
|
|
||||||
} sdrplay_api_RspDx_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
|
|
||||||
} sdrplay_api_RspDx_HdrModeBwT;
|
|
||||||
|
|
||||||
// RSPdx parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char hdrEnable; // default: 0
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_RspDxParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
|
|
||||||
} sdrplay_api_RspDxTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPDX_H
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
#define SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
#include "sdrplay_api_control.h"
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_TunerParamsT tunerParams;
|
|
||||||
sdrplay_api_ControlParamsT ctrlParams;
|
|
||||||
sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
|
|
||||||
sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
|
|
||||||
sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
|
|
||||||
sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
|
|
||||||
} sdrplay_api_RxChannelParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_TUNER_H
|
|
||||||
#define SDRPLAY_API_TUNER_H
|
|
||||||
|
|
||||||
#define MAX_BB_GR (59)
|
|
||||||
|
|
||||||
// Tuner parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_BW_Undefined = 0,
|
|
||||||
sdrplay_api_BW_0_200 = 200,
|
|
||||||
sdrplay_api_BW_0_300 = 300,
|
|
||||||
sdrplay_api_BW_0_600 = 600,
|
|
||||||
sdrplay_api_BW_1_536 = 1536,
|
|
||||||
sdrplay_api_BW_5_000 = 5000,
|
|
||||||
sdrplay_api_BW_6_000 = 6000,
|
|
||||||
sdrplay_api_BW_7_000 = 7000,
|
|
||||||
sdrplay_api_BW_8_000 = 8000
|
|
||||||
} sdrplay_api_Bw_MHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_IF_Undefined = -1,
|
|
||||||
sdrplay_api_IF_Zero = 0,
|
|
||||||
sdrplay_api_IF_0_450 = 450,
|
|
||||||
sdrplay_api_IF_1_620 = 1620,
|
|
||||||
sdrplay_api_IF_2_048 = 2048
|
|
||||||
} sdrplay_api_If_kHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_LO_Undefined = 0,
|
|
||||||
sdrplay_api_LO_Auto = 1,
|
|
||||||
sdrplay_api_LO_120MHz = 2,
|
|
||||||
sdrplay_api_LO_144MHz = 3,
|
|
||||||
sdrplay_api_LO_168MHz = 4
|
|
||||||
} sdrplay_api_LoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_EXTENDED_MIN_GR = 0,
|
|
||||||
sdrplay_api_NORMAL_MIN_GR = 20
|
|
||||||
} sdrplay_api_MinGainReductionT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Tuner_Neither = 0,
|
|
||||||
sdrplay_api_Tuner_A = 1,
|
|
||||||
sdrplay_api_Tuner_B = 2,
|
|
||||||
sdrplay_api_Tuner_Both = 3,
|
|
||||||
} sdrplay_api_TunerSelectT;
|
|
||||||
|
|
||||||
// Tuner parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float curr;
|
|
||||||
float max;
|
|
||||||
float min;
|
|
||||||
} sdrplay_api_GainValuesT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int gRdB; // default: 50
|
|
||||||
unsigned char LNAstate; // default: 0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
|
|
||||||
sdrplay_api_GainValuesT gainVals; // output parameter
|
|
||||||
} sdrplay_api_GainT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double rfHz; // default: 200000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_RfFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char dcCal; // default: 3 (Periodic mode)
|
|
||||||
unsigned char speedUp; // default: 0 (No speedup)
|
|
||||||
int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
|
|
||||||
int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
|
|
||||||
} sdrplay_api_DcOffsetTunerT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
|
|
||||||
sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
|
|
||||||
sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
|
|
||||||
sdrplay_api_GainT gain;
|
|
||||||
sdrplay_api_RfFreqT rfFreq;
|
|
||||||
sdrplay_api_DcOffsetTunerT dcOffsetTuner;
|
|
||||||
} sdrplay_api_TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_TUNER_H
|
|
||||||
@@ -1,235 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_H
|
|
||||||
#define SDRPLAY_API_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_dev.h"
|
|
||||||
#include "sdrplay_api_rx_channel.h"
|
|
||||||
#include "sdrplay_api_callback.h"
|
|
||||||
|
|
||||||
#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64)
|
|
||||||
#include "windows.h"
|
|
||||||
#elif defined (__GNUC__)
|
|
||||||
typedef void *HANDLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _SDRPLAY_DLL_QUALIFIER
|
|
||||||
#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64))
|
|
||||||
#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
|
||||||
#elif defined(STATIC_LIB) || defined(__GNUC__)
|
|
||||||
#define _SDRPLAY_DLL_QUALIFIER
|
|
||||||
#endif
|
|
||||||
#endif // _SDRPLAY_DLL_QUALIFIER
|
|
||||||
|
|
||||||
// Application code should check that it is compiled against the same API version
|
|
||||||
// sdrplay_api_ApiVersion() returns the API version
|
|
||||||
#define SDRPLAY_API_VERSION (float)(3.15)
|
|
||||||
|
|
||||||
// API Constants
|
|
||||||
#define SDRPLAY_MAX_DEVICES (16)
|
|
||||||
#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
|
|
||||||
|
|
||||||
#define SDRPLAY_MAX_SER_NO_LEN (64)
|
|
||||||
#define SDRPLAY_MAX_ROOT_NM_LEN (32)
|
|
||||||
|
|
||||||
#define SDRPLAY_RSP1_ID (1)
|
|
||||||
#define SDRPLAY_RSP1A_ID (255)
|
|
||||||
#define SDRPLAY_RSP2_ID (2)
|
|
||||||
#define SDRPLAY_RSPduo_ID (3)
|
|
||||||
#define SDRPLAY_RSPdx_ID (4)
|
|
||||||
#define SDRPLAY_RSP1B_ID (6)
|
|
||||||
#define SDRPLAY_RSPdxR2_ID (7)
|
|
||||||
|
|
||||||
// Enum types
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Success = 0,
|
|
||||||
sdrplay_api_Fail = 1,
|
|
||||||
sdrplay_api_InvalidParam = 2,
|
|
||||||
sdrplay_api_OutOfRange = 3,
|
|
||||||
sdrplay_api_GainUpdateError = 4,
|
|
||||||
sdrplay_api_RfUpdateError = 5,
|
|
||||||
sdrplay_api_FsUpdateError = 6,
|
|
||||||
sdrplay_api_HwError = 7,
|
|
||||||
sdrplay_api_AliasingError = 8,
|
|
||||||
sdrplay_api_AlreadyInitialised = 9,
|
|
||||||
sdrplay_api_NotInitialised = 10,
|
|
||||||
sdrplay_api_NotEnabled = 11,
|
|
||||||
sdrplay_api_HwVerError = 12,
|
|
||||||
sdrplay_api_OutOfMemError = 13,
|
|
||||||
sdrplay_api_ServiceNotResponding = 14,
|
|
||||||
sdrplay_api_StartPending = 15,
|
|
||||||
sdrplay_api_StopPending = 16,
|
|
||||||
sdrplay_api_InvalidMode = 17,
|
|
||||||
sdrplay_api_FailedVerification1 = 18,
|
|
||||||
sdrplay_api_FailedVerification2 = 19,
|
|
||||||
sdrplay_api_FailedVerification3 = 20,
|
|
||||||
sdrplay_api_FailedVerification4 = 21,
|
|
||||||
sdrplay_api_FailedVerification5 = 22,
|
|
||||||
sdrplay_api_FailedVerification6 = 23,
|
|
||||||
sdrplay_api_InvalidServiceVersion = 24
|
|
||||||
} sdrplay_api_ErrT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_Dev_Fs = 0x00000001,
|
|
||||||
sdrplay_api_Update_Dev_Ppm = 0x00000002,
|
|
||||||
sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
|
|
||||||
sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
|
|
||||||
sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
|
|
||||||
sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
|
|
||||||
sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
|
|
||||||
sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
|
|
||||||
sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Master_Spare_1 = 0x00002000,
|
|
||||||
sdrplay_api_Update_Master_Spare_2 = 0x00004000,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
// Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
|
|
||||||
sdrplay_api_Update_Tuner_Gr = 0x00008000,
|
|
||||||
sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
|
|
||||||
sdrplay_api_Update_Tuner_Frf = 0x00020000,
|
|
||||||
sdrplay_api_Update_Tuner_BwType = 0x00040000,
|
|
||||||
sdrplay_api_Update_Tuner_IfType = 0x00080000,
|
|
||||||
sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
|
|
||||||
sdrplay_api_Update_Tuner_LoMode = 0x00200000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
|
|
||||||
sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
|
|
||||||
sdrplay_api_Update_Ctrl_Agc = 0x01000000,
|
|
||||||
sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
|
|
||||||
sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
|
|
||||||
|
|
||||||
sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
|
|
||||||
sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
|
|
||||||
sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
|
|
||||||
sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
|
|
||||||
} sdrplay_api_ReasonForUpdateT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Update_Ext1_None = 0x00000000,
|
|
||||||
|
|
||||||
// Reasons for master only mode
|
|
||||||
sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
|
|
||||||
sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
|
|
||||||
sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
|
|
||||||
sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
|
|
||||||
sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
|
|
||||||
sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
|
|
||||||
sdrplay_api_Update_RspDuo_ResetSlaveFlags = 0x00000040,
|
|
||||||
|
|
||||||
// Reasons for master and slave mode
|
|
||||||
} sdrplay_api_ReasonForUpdateExtension1T;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_DbgLvl_Disable = 0,
|
|
||||||
sdrplay_api_DbgLvl_Verbose = 1,
|
|
||||||
sdrplay_api_DbgLvl_Warning = 2,
|
|
||||||
sdrplay_api_DbgLvl_Error = 3,
|
|
||||||
sdrplay_api_DbgLvl_Message = 4,
|
|
||||||
} sdrplay_api_DbgLvl_t;
|
|
||||||
|
|
||||||
// Device structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char SerNo[SDRPLAY_MAX_SER_NO_LEN];
|
|
||||||
unsigned char hwVer;
|
|
||||||
sdrplay_api_TunerSelectT tuner;
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode;
|
|
||||||
unsigned char valid;
|
|
||||||
double rspDuoSampleFreq;
|
|
||||||
HANDLE dev;
|
|
||||||
} sdrplay_api_DeviceT;
|
|
||||||
|
|
||||||
// Device parameter structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DevParamsT *devParams;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelA;
|
|
||||||
sdrplay_api_RxChannelParamsT *rxChannelB;
|
|
||||||
} sdrplay_api_DeviceParamsT;
|
|
||||||
|
|
||||||
// Extended error message structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char file[256];
|
|
||||||
char function[256];
|
|
||||||
int line;
|
|
||||||
char message[1024];
|
|
||||||
} sdrplay_api_ErrorInfoT;
|
|
||||||
|
|
||||||
// Comman API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
|
|
||||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
|
|
||||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastErrorByType_t)(sdrplay_api_DeviceT *device, int type, unsigned long long *time);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
|
|
||||||
|
|
||||||
// Device API function types
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate, double newSampleRate);
|
|
||||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
// API function definitions
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Comman API function definitions
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Open(void);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Close(void);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrorInfoT* sdrplay_api_GetLastErrorByType(sdrplay_api_DeviceT *device, int type, unsigned long long *time);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
|
|
||||||
|
|
||||||
// Device API function definitions
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate, double newSampleRate);
|
|
||||||
_SDRPLAY_DLL_QUALIFIER sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
|
||||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
|
||||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_H
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CALLBACK_H
|
|
||||||
#define SDRPLAY_API_CALLBACK_H
|
|
||||||
|
|
||||||
// Event callback enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Overload_Detected = 0,
|
|
||||||
sdrplay_api_Overload_Corrected = 1,
|
|
||||||
} sdrplay_api_PowerOverloadCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_MasterInitialised = 0,
|
|
||||||
sdrplay_api_SlaveAttached = 1,
|
|
||||||
sdrplay_api_SlaveDetached = 2,
|
|
||||||
sdrplay_api_SlaveInitialised = 3,
|
|
||||||
sdrplay_api_SlaveUninitialised = 4,
|
|
||||||
sdrplay_api_MasterDllDisappeared = 5,
|
|
||||||
sdrplay_api_SlaveDllDisappeared = 6,
|
|
||||||
} sdrplay_api_RspDuoModeCbEventIdT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_GainChange = 0,
|
|
||||||
sdrplay_api_PowerOverloadChange = 1,
|
|
||||||
sdrplay_api_DeviceRemoved = 2,
|
|
||||||
sdrplay_api_RspDuoModeChange = 3,
|
|
||||||
sdrplay_api_DeviceFailure = 4,
|
|
||||||
} sdrplay_api_EventT;
|
|
||||||
|
|
||||||
// Event callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int gRdB;
|
|
||||||
unsigned int lnaGRdB;
|
|
||||||
double currGain;
|
|
||||||
} sdrplay_api_GainCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
|
|
||||||
} sdrplay_api_PowerOverloadCbParamT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
|
|
||||||
} sdrplay_api_RspDuoModeCbParamT;
|
|
||||||
|
|
||||||
// Event parameters overlay
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
sdrplay_api_GainCbParamT gainParams;
|
|
||||||
sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
|
|
||||||
sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
|
|
||||||
} sdrplay_api_EventParamsT;
|
|
||||||
|
|
||||||
// Stream callback parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int firstSampleNum;
|
|
||||||
int grChanged;
|
|
||||||
int rfChanged;
|
|
||||||
int fsChanged;
|
|
||||||
unsigned int numSamples;
|
|
||||||
} sdrplay_api_StreamCbParamsT;
|
|
||||||
|
|
||||||
// Callback function prototypes
|
|
||||||
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
|
|
||||||
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
|
|
||||||
|
|
||||||
// Callback function struct
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_StreamCallback_t StreamACbFn;
|
|
||||||
sdrplay_api_StreamCallback_t StreamBCbFn;
|
|
||||||
sdrplay_api_EventCallback_t EventCbFn;
|
|
||||||
} sdrplay_api_CallbackFnsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CALLBACK_H
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_CONTROL_H
|
|
||||||
#define SDRPLAY_API_CONTROL_H
|
|
||||||
|
|
||||||
// Control parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_AGC_DISABLE = 0,
|
|
||||||
sdrplay_api_AGC_100HZ = 1,
|
|
||||||
sdrplay_api_AGC_50HZ = 2,
|
|
||||||
sdrplay_api_AGC_5HZ = 3,
|
|
||||||
sdrplay_api_AGC_CTRL_EN = 4
|
|
||||||
} sdrplay_api_AgcControlT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ADSB_DECIMATION = 0,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
|
|
||||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
|
|
||||||
} sdrplay_api_AdsbModeT;
|
|
||||||
|
|
||||||
// Control parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char DCenable; // default: 1
|
|
||||||
unsigned char IQenable; // default: 1
|
|
||||||
} sdrplay_api_DcOffsetT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char enable; // default: 0
|
|
||||||
unsigned char decimationFactor; // default: 1
|
|
||||||
unsigned char wideBandSignal; // default: 0
|
|
||||||
} sdrplay_api_DecimationT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
|
|
||||||
int setPoint_dBfs; // default: -60
|
|
||||||
unsigned short attack_ms; // default: 0
|
|
||||||
unsigned short decay_ms; // default: 0
|
|
||||||
unsigned short decay_delay_ms; // default: 0
|
|
||||||
unsigned short decay_threshold_dB; // default: 0
|
|
||||||
int syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_AgcT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_DcOffsetT dcOffset;
|
|
||||||
sdrplay_api_DecimationT decimation;
|
|
||||||
sdrplay_api_AgcT agc;
|
|
||||||
sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
|
|
||||||
} sdrplay_api_ControlParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_CONTROL_H
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_DEV_H
|
|
||||||
#define SDRPLAY_API_DEV_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
// Dev parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_ISOCH = 0,
|
|
||||||
sdrplay_api_BULK = 1
|
|
||||||
} sdrplay_api_TransferModeT;
|
|
||||||
|
|
||||||
// Dev parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double fsHz; // default: 2000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
unsigned char reCal; // default: 0
|
|
||||||
} sdrplay_api_FsFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int sampleNum; // default: 0
|
|
||||||
unsigned int period; // default: 0
|
|
||||||
} sdrplay_api_SyncUpdateT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char resetGainUpdate; // default: 0
|
|
||||||
unsigned char resetRfUpdate; // default: 0
|
|
||||||
unsigned char resetFsUpdate; // default: 0
|
|
||||||
} sdrplay_api_ResetFlagsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double ppm; // default: 0.0
|
|
||||||
sdrplay_api_FsFreqT fsFreq;
|
|
||||||
sdrplay_api_SyncUpdateT syncUpdate;
|
|
||||||
sdrplay_api_ResetFlagsT resetFlags;
|
|
||||||
sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
|
|
||||||
unsigned int samplesPerPkt; // default: 0 (output param)
|
|
||||||
sdrplay_api_Rsp1aParamsT rsp1aParams;
|
|
||||||
sdrplay_api_Rsp2ParamsT rsp2Params;
|
|
||||||
sdrplay_api_RspDuoParamsT rspDuoParams;
|
|
||||||
sdrplay_api_RspDxParamsT rspDxParams;
|
|
||||||
} sdrplay_api_DevParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_DEV_H
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP1A_H
|
|
||||||
#define SDRPLAY_API_RSP1A_H
|
|
||||||
|
|
||||||
#define RSPIA_NUM_LNA_STATES 10
|
|
||||||
#define RSPIA_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPIA_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSP1A parameter enums
|
|
||||||
|
|
||||||
// RSP1A parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp1aTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP1A_H
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSP2_H
|
|
||||||
#define SDRPLAY_API_RSP2_H
|
|
||||||
|
|
||||||
#define RSPII_NUM_LNA_STATES 9
|
|
||||||
#define RSPII_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPII_NUM_LNA_STATES_420MHZ 6
|
|
||||||
|
|
||||||
// RSP2 parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_A = 5,
|
|
||||||
sdrplay_api_Rsp2_ANTENNA_B = 6,
|
|
||||||
} sdrplay_api_Rsp2_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Rsp2_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_Rsp2_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_Rsp2_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSP2 parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_Rsp2ParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
|
|
||||||
sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_Rsp2TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSP2_H
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPduo_H
|
|
||||||
#define SDRPLAY_API_RSPduo_H
|
|
||||||
|
|
||||||
#define RSPDUO_NUM_LNA_STATES 10
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AMPORT 5
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_AM 7
|
|
||||||
#define RSPDUO_NUM_LNA_STATES_LBAND 9
|
|
||||||
|
|
||||||
// RSPduo parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuoMode_Unknown = 0,
|
|
||||||
sdrplay_api_RspDuoMode_Single_Tuner = 1,
|
|
||||||
sdrplay_api_RspDuoMode_Dual_Tuner = 2,
|
|
||||||
sdrplay_api_RspDuoMode_Master = 4,
|
|
||||||
sdrplay_api_RspDuoMode_Slave = 8,
|
|
||||||
} sdrplay_api_RspDuoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDuo_AMPORT_1 = 1,
|
|
||||||
sdrplay_api_RspDuo_AMPORT_2 = 0,
|
|
||||||
} sdrplay_api_RspDuo_AmPortSelectT;
|
|
||||||
|
|
||||||
// RSPduo parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int extRefOutputEn; // default: 0
|
|
||||||
} sdrplay_api_RspDuoParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char resetGainUpdate; // default: 0
|
|
||||||
unsigned char resetRfUpdate; // default: 0
|
|
||||||
} sdrplay_api_RspDuo_ResetSlaveFlagsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
|
|
||||||
unsigned char tuner1AmNotchEnable; // default: 0
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
sdrplay_api_RspDuo_ResetSlaveFlagsT resetSlaveFlags;
|
|
||||||
} sdrplay_api_RspDuoTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPduo_H
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RSPDX_H
|
|
||||||
#define SDRPLAY_API_RSPDX_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
|
|
||||||
#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_12_50 20 // Number of LNA states when using AM Port 2 between 12 and 50MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_50_60 25 // Number of LNA states when using AM Port 2 between 50 and 60MHz
|
|
||||||
#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
|
|
||||||
#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
|
|
||||||
#define RSPDX_NUM_LNA_STATES_DX 22 // Number of LNA states in DX path
|
|
||||||
|
|
||||||
// RSPdx parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_ANTENNA_A = 0,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_B = 1,
|
|
||||||
sdrplay_api_RspDx_ANTENNA_C = 2,
|
|
||||||
} sdrplay_api_RspDx_AntennaSelectT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
|
|
||||||
sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
|
|
||||||
} sdrplay_api_RspDx_HdrModeBwT;
|
|
||||||
|
|
||||||
// RSPdx parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char hdrEnable; // default: 0
|
|
||||||
unsigned char biasTEnable; // default: 0
|
|
||||||
sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
|
|
||||||
unsigned char rfNotchEnable; // default: 0
|
|
||||||
unsigned char rfDabNotchEnable; // default: 0
|
|
||||||
} sdrplay_api_RspDxParamsT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
|
|
||||||
} sdrplay_api_RspDxTunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RSPDX_H
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
#define SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
|
|
||||||
#include "sdrplay_api_tuner.h"
|
|
||||||
#include "sdrplay_api_control.h"
|
|
||||||
#include "sdrplay_api_rsp1a.h"
|
|
||||||
#include "sdrplay_api_rsp2.h"
|
|
||||||
#include "sdrplay_api_rspDuo.h"
|
|
||||||
#include "sdrplay_api_rspDx.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_TunerParamsT tunerParams;
|
|
||||||
sdrplay_api_ControlParamsT ctrlParams;
|
|
||||||
sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
|
|
||||||
sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
|
|
||||||
sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
|
|
||||||
sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
|
|
||||||
} sdrplay_api_RxChannelParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_RX_CHANNEL_H
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#ifndef SDRPLAY_API_TUNER_H
|
|
||||||
#define SDRPLAY_API_TUNER_H
|
|
||||||
|
|
||||||
#define MAX_BB_GR (59)
|
|
||||||
|
|
||||||
// Tuner parameter enums
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_BW_Undefined = 0,
|
|
||||||
sdrplay_api_BW_0_200 = 200,
|
|
||||||
sdrplay_api_BW_0_300 = 300,
|
|
||||||
sdrplay_api_BW_0_600 = 600,
|
|
||||||
sdrplay_api_BW_1_536 = 1536,
|
|
||||||
sdrplay_api_BW_5_000 = 5000,
|
|
||||||
sdrplay_api_BW_6_000 = 6000,
|
|
||||||
sdrplay_api_BW_7_000 = 7000,
|
|
||||||
sdrplay_api_BW_8_000 = 8000
|
|
||||||
} sdrplay_api_Bw_MHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_IF_Undefined = -1,
|
|
||||||
sdrplay_api_IF_Zero = 0,
|
|
||||||
sdrplay_api_IF_0_450 = 450,
|
|
||||||
sdrplay_api_IF_1_620 = 1620,
|
|
||||||
sdrplay_api_IF_2_048 = 2048
|
|
||||||
} sdrplay_api_If_kHzT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_LO_Undefined = 0,
|
|
||||||
sdrplay_api_LO_Auto = 1,
|
|
||||||
sdrplay_api_LO_120MHz = 2,
|
|
||||||
sdrplay_api_LO_144MHz = 3,
|
|
||||||
sdrplay_api_LO_168MHz = 4
|
|
||||||
} sdrplay_api_LoModeT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_EXTENDED_MIN_GR = 0,
|
|
||||||
sdrplay_api_NORMAL_MIN_GR = 20
|
|
||||||
} sdrplay_api_MinGainReductionT;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
sdrplay_api_Tuner_Neither = 0,
|
|
||||||
sdrplay_api_Tuner_A = 1,
|
|
||||||
sdrplay_api_Tuner_B = 2,
|
|
||||||
sdrplay_api_Tuner_Both = 3,
|
|
||||||
} sdrplay_api_TunerSelectT;
|
|
||||||
|
|
||||||
// Tuner parameter structs
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float curr;
|
|
||||||
float max;
|
|
||||||
float min;
|
|
||||||
} sdrplay_api_GainValuesT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int gRdB; // default: 50
|
|
||||||
unsigned char LNAstate; // default: 0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
|
|
||||||
sdrplay_api_GainValuesT gainVals; // output parameter
|
|
||||||
} sdrplay_api_GainT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double rfHz; // default: 200000000.0
|
|
||||||
unsigned char syncUpdate; // default: 0
|
|
||||||
} sdrplay_api_RfFreqT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned char dcCal; // default: 3 (Periodic mode)
|
|
||||||
unsigned char speedUp; // default: 0 (No speedup)
|
|
||||||
int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
|
|
||||||
int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
|
|
||||||
} sdrplay_api_DcOffsetTunerT;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
|
|
||||||
sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
|
|
||||||
sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
|
|
||||||
sdrplay_api_GainT gain;
|
|
||||||
sdrplay_api_RfFreqT rfFreq;
|
|
||||||
sdrplay_api_DcOffsetTunerT dcOffsetTuner;
|
|
||||||
} sdrplay_api_TunerParamsT;
|
|
||||||
|
|
||||||
#endif //SDRPLAY_API_TUNER_H
|
|
||||||
321
build.gradle
321
build.gradle
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,16 +17,18 @@
|
|||||||
* ****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.beryx.runtime.RuntimeZipTask
|
||||||
|
import org.gradle.internal.jvm.Jvm
|
||||||
|
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructions for building/compiling the sdrtrunk application.
|
* Instructions for building/compiling the sdrtrunk application.
|
||||||
*
|
*
|
||||||
* Prerequisites:
|
* Prerequisites:
|
||||||
* Install and configure an OpenJDK version 22+ that includes the JavaFX modules (e.g. Bellsoft Liberica JDK)
|
* Install and configure an OpenJDK version 27+ that includes the JavaFX modules (e.g. Bellsoft Liberica JDK)
|
||||||
* - Optional: install and configure Gradle 8.10+
|
* - Optional: install and configure Gradle 9.8+
|
||||||
*
|
*
|
||||||
* Scenario 1: run the application via gradle command line from the source code root directory:
|
* Scenario 1: run the application via gradle command line from the source code root directory:
|
||||||
* command: ./gradlew run
|
* command: ./gradlew run
|
||||||
@@ -50,24 +52,40 @@ plugins {
|
|||||||
id 'org.beryx.runtime' version '2.0.1'
|
id 'org.beryx.runtime' version '2.0.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url = "https://jitpack.io" }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Version is defined in gradle.properties so that we can CLI override it for nightly builds.
|
//Version is defined in gradle.properties so that we can CLI override it for nightly builds.
|
||||||
version = project.findProperty('projectVersion')
|
version = project.findProperty('projectVersion')
|
||||||
|
|
||||||
//Java 24 is required for this version of the Project Panama preview/incubator feature
|
//Java 27 is required for this version of the Project Panama preview/incubator feature
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(25)
|
languageVersion = JavaLanguageVersion.of(27)
|
||||||
|
vendor = JvmVendorSpec.BELLSOFT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
/**
|
||||||
main.java.srcDirs 'src/main'
|
* Verifies that the selected toolchain JDK includes the JavaFX modules (e.g. Bellsoft Liberica 'Full JDK').
|
||||||
test.java.srcDirs 'src/test'
|
*
|
||||||
|
* Gradle's toolchain spec can only select by language version, vendor and implementation, so it can't distinguish
|
||||||
|
* between the Liberica JDK packages that do and don't bundle JavaFX. This task fails the build with a clear message
|
||||||
|
* instead of allowing compilation to fail with missing javafx packages.
|
||||||
|
*/
|
||||||
|
tasks.register('verifyToolchainJavaFx') {
|
||||||
|
def jdkHome = javaToolchains.launcherFor(java.toolchain).map { it.metadata.installationPath.asFile }
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
def release = new File(jdkHome.get(), 'release')
|
||||||
|
|
||||||
|
if(!release.exists() || !release.text.contains('javafx.base')) {
|
||||||
|
throw new GradleException("The JDK at [${jdkHome.get()}] does not include the JavaFX modules. Install " +
|
||||||
|
"the Bellsoft Liberica JDK 27 'Full' package (includes LibericaFX), or use " +
|
||||||
|
"-Porg.gradle.java.installations.paths=<jdk path> to specify the JDK that Gradle should use.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('compileJava') {
|
||||||
|
dependsOn 'verifyToolchainJavaFx'
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@@ -77,58 +95,61 @@ test {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
// JUnit Tests
|
// JUnit Tests
|
||||||
testImplementation(platform("org.junit:junit-bom:6.0.1"))
|
testImplementation(platform("org.junit:junit-bom:6.1.3"))
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:6.0.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api'
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:6.0.1")
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.1")
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
//Jitpack imports
|
//Jitpack imports
|
||||||
implementation 'com.github.dnault:libresample4j:master'
|
implementation 'com.github.dnault:libresample4j:master'
|
||||||
implementation 'com.github.DSheirer.jmbe:jmbe-api:1.0.0'
|
implementation 'com.github.DSheirer.jmbe:api:v2.1.1'
|
||||||
implementation 'com.github.nwaldispuehl:java-lame:v3.98.4'
|
implementation 'com.github.nwaldispuehl:java-lame:v3.98.4'
|
||||||
|
|
||||||
//mavenCentral/jcenter imports
|
//mavenCentral/jcenter imports
|
||||||
implementation 'ch.qos.logback:logback-classic:1.5.21'
|
implementation 'ch.qos.logback:logback-classic:1.6.6'
|
||||||
implementation 'ch.qos.logback:logback-core:1.5.21'
|
implementation 'ch.qos.logback:logback-core:1.6.6'
|
||||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.20.1'
|
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.23.0'
|
||||||
implementation 'com.fazecast:jSerialComm:2.11.4'
|
implementation 'com.formdev:flatlaf:3.8'
|
||||||
|
implementation 'com.formdev:flatlaf-intellij-themes:3.8' //Not imported - Theme.java loads these themes by class name
|
||||||
implementation 'com.github.jiconfont:jiconfont-font_awesome:4.7.0.1'
|
implementation 'com.github.jiconfont:jiconfont-font_awesome:4.7.0.1'
|
||||||
implementation 'com.github.jiconfont:jiconfont-javafx:1.0.0'
|
implementation 'com.github.jiconfont:jiconfont-javafx:1.0.0'
|
||||||
implementation 'com.github.jiconfont:jiconfont-swing:1.0.1'
|
implementation 'com.github.jiconfont:jiconfont-swing:1.0.1'
|
||||||
implementation 'com.github.wendykierp:JTransforms:3.1'
|
implementation('com.github.wendykierp:JTransforms:3.2') {
|
||||||
implementation 'com.google.code.gson:gson:2.13.2'
|
exclude group: 'junit' //JLargeArrays 1.7 declares junit as a compile dependency
|
||||||
implementation 'com.google.guava:guava:33.5.0-jre'
|
}
|
||||||
|
implementation 'com.google.code.gson:gson:2.15.0'
|
||||||
|
implementation 'com.google.guava:guava:33.8.0-jre'
|
||||||
implementation 'com.jidesoft:jide-oss:3.6.18'
|
implementation 'com.jidesoft:jide-oss:3.6.18'
|
||||||
implementation 'com.miglayout:miglayout-swing:11.4.2'
|
implementation 'com.miglayout:miglayout-swing:11.5.2'
|
||||||
implementation 'com.mpatric:mp3agic:0.9.1'
|
implementation 'com.mpatric:mp3agic:0.9.1'
|
||||||
implementation 'commons-io:commons-io:2.21.0'
|
implementation 'commons-io:commons-io:2.22.0'
|
||||||
implementation 'eu.hansolo:charts:1.0.5'
|
implementation 'io.github.dsheirer:jairspy:1.0.12.1' //Airspy tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jairspyhf:1.8.1.1' //Airspy HF+ tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jbladerf:2.6.0.1' //bladeRF tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jhackrf:2026.01.3.1' //HackRF tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jlibusb:1.0.30.1' //libusb and USB hotplug for the tuner libraries - GitHub release; not pulled in transitively
|
||||||
|
implementation 'io.github.dsheirer:jhydrasdr:1.1.4.1' //HydraSDR tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jlimesdr:25.1.0.2' //LimeSDR tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jrtl:1.4.0.3' //RTL-SDR tuners - GitHub release, see settings.gradle
|
||||||
|
implementation 'io.github.dsheirer:jsdrplay:3.15.3' //SDRplay RSP tuners - GitHub release, see settings.gradle
|
||||||
implementation 'io.github.dsheirer:radio-reference-api:18.0.0'
|
implementation 'io.github.dsheirer:radio-reference-api:18.0.0'
|
||||||
implementation 'io.github.dsheirer:usb4java-native-libraries:1.3.3' //OSX & Windows aarch64 native libs
|
implementation 'org.apache.commons:commons-compress:1.28.0' //Not used directly - overrides the vulnerable 1.21 version from jarchivelib
|
||||||
implementation 'io.github.dsheirer:usb4java:1.3.5' //Fork with Loader support for OSX Multi-Version
|
implementation 'org.apache.commons:commons-lang3:3.21.0'
|
||||||
implementation 'javax.usb:usb-api:1.0.2'
|
|
||||||
implementation 'net.coderazzi:tablefilter-swing:5.5.4'
|
|
||||||
implementation 'org.apache.commons:commons-compress:1.28.0'
|
|
||||||
implementation 'org.apache.commons:commons-lang3:3.19.0'
|
|
||||||
implementation 'org.apache.commons:commons-math3:3.6.1'
|
implementation 'org.apache.commons:commons-math3:3.6.1'
|
||||||
implementation 'org.apache.commons:commons-csv:1.14.1'
|
implementation 'org.apache.commons:commons-csv:1.14.1'
|
||||||
implementation 'org.apache.mina:mina-core:2.2.4'
|
implementation 'org.apache.mina:mina-core:2.2.10'
|
||||||
implementation 'org.apache.mina:mina-http:2.2.4'
|
implementation 'org.apache.mina:mina-http:2.2.10'
|
||||||
implementation 'org.controlsfx:controlsfx:11.2.2'
|
implementation 'org.controlsfx:controlsfx:11.2.6'
|
||||||
implementation 'org.rauschig:jarchivelib:1.2.0'
|
implementation 'org.rauschig:jarchivelib:1.2.0'
|
||||||
implementation 'org.slf4j:slf4j-api:2.0.17'
|
implementation 'org.slf4j:slf4j-api:2.0.20'
|
||||||
implementation 'org.usb4java:libusb4java:1.3.0'
|
|
||||||
implementation 'org.usb4java:usb4java-javax:1.3.0'
|
|
||||||
implementation 'pl.edu.icm:JLargeArrays:1.6'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem
|
def os = DefaultNativePlatform.currentOperatingSystem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is needed for the JDK23 vector API ... until it moves out of incubation or preview
|
* This is needed for the JDK23+ vector API ... until it moves out of incubation or preview
|
||||||
*/
|
*/
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
options.compilerArgs.add("--enable-preview") //Project Panama Vector API is still in incubator
|
options.compilerArgs.add("--enable-preview") //Project Panama Vector API is still in incubator
|
||||||
options.compilerArgs.add("--add-modules=jdk.incubator.vector") //Project Panama Vector API is still in incubator
|
options.compilerArgs.add("--add-modules=jdk.incubator.vector") //Project Panama Vector API is still in incubator
|
||||||
}
|
}
|
||||||
@@ -139,25 +160,22 @@ tasks.withType(JavaCompile) {
|
|||||||
def jvmArgsWindows =
|
def jvmArgsWindows =
|
||||||
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
||||||
'--add-exports=java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED', //windows users for JIDE
|
'--add-exports=java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED', //windows users for JIDE
|
||||||
'--add-modules=jdk.incubator.vector', //Project Panama Vector API is still in incubator
|
'--add-modules=jdk.incubator.vector', //Project Panama vector API is still in incubator
|
||||||
'--enable-preview', //Project Panama Vector API is still in incubator
|
'--enable-preview', //Project Panama Vector API is still in incubator
|
||||||
'--enable-native-access=ALL-UNNAMED', //Suppress unsafe warnings for FFM API Foreign Memory calls
|
'--enable-native-access=ALL-UNNAMED', //Suppress unsafe warnings for FFM API Foreign Memory calls
|
||||||
'--enable-native-access=javafx.graphics', //JDK24 - suppress restricted java.lang.System calls
|
'--enable-native-access=javafx.graphics', //JDK24 - suppress restricted java.lang.System calls
|
||||||
'--sun-misc-unsafe-memory-access=allow', //JDK24 - suppress sun.misc.Unsafe::allocateMemory warning
|
'--sun-misc-unsafe-memory-access=allow'] //JDK24 - suppress sun.misc.Unsafe::allocateMemory warning
|
||||||
'-XX:+UseCompactObjectHeaders', //JDK25 - use compact object headers
|
|
||||||
'-Djava.library.path=c:\\Program Files\\SDRplay\\API\\x64'] //SDRPlay API library path
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JVM Arguments for running the application on Linux.
|
* JVM Arguments for running the application on Linux.
|
||||||
*/
|
*/
|
||||||
def jvmArgsLinux =
|
def jvmArgsLinux =
|
||||||
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
||||||
'--add-modules=jdk.incubator.vector', //Needed while Project Panama API is still in incubator
|
'--add-modules=jdk.incubator.vector', //Project Panama vector API is still in incubator
|
||||||
'--enable-preview', //Project Panama Vector & Foreign Function APIs remain in incubator
|
'--enable-preview', //Project Panama Vector & Foreign Function APIs remain in incubator
|
||||||
'--sun-misc-unsafe-memory-access=allow', //JDK24 - suppress sun.misc.Unsafe::allocateMemory warning
|
'--sun-misc-unsafe-memory-access=allow', //JDK24 - suppress sun.misc.Unsafe::allocateMemory warning
|
||||||
'-XX:+UseCompactObjectHeaders', //JDK25 - use compact object headers
|
|
||||||
'--enable-native-access=javafx.graphics', //JDK24 - suppress restricted java.lang.System calls
|
'--enable-native-access=javafx.graphics', //JDK24 - suppress restricted java.lang.System calls
|
||||||
'--enable-native-access=ALL-UNNAMED'] //SDRPlay API library path
|
'--enable-native-access=ALL-UNNAMED'] //Suppress warnings for FFM API native calls (tuner libraries)
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass = "io.github.dsheirer.gui.SDRTrunk"
|
mainClass = "io.github.dsheirer.gui.SDRTrunk"
|
||||||
@@ -214,22 +232,10 @@ String targetOsxX86_64 = 'osx-x86_64-v' + version
|
|||||||
String targetWindowsX86_64 = 'windows-x86_64-v' + version
|
String targetWindowsX86_64 = 'windows-x86_64-v' + version
|
||||||
String targetWindowsAarch64 = 'windows-aarch64-v' + version
|
String targetWindowsAarch64 = 'windows-aarch64-v' + version
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional pre-downloaded Java Development Kit (JDK) for each target OS and CPU. These locations are hard-coded to the
|
|
||||||
* author's development environment, but can be changed to your environment if you want to use this build pattern.
|
|
||||||
*/
|
|
||||||
String jdk_base = '/home/denny/java_jdks/'
|
|
||||||
String jdk_linux_aarch64 = jdk_base + 'linux-arm64/jdk-25.0.1-full'
|
|
||||||
String jdk_linux_x86_64 = jdk_base + 'linux-x64/jdk-25.0.1-full'
|
|
||||||
String jdk_osx_x86_64 = jdk_base + 'osx-x64/jdk-25.0.1-full.jdk'
|
|
||||||
String jdk_osx_aarch64 = jdk_base + 'osx-arm64/jdk-25.0.1-full.jdk'
|
|
||||||
String jdk_windows_x86_64 = jdk_base + 'windows-x64/jdk-25.0.1-full'
|
|
||||||
String jdk_windows_aarch64 = jdk_base + 'windows-arm64/jdk-25.0.1-full'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download URLs to download the JDK as part of the gradle build packaging process
|
* Download URLs to download the JDK as part of the gradle build packaging process
|
||||||
*/
|
*/
|
||||||
def jdk_download_base = "https://download.bell-sw.com/java/25.0.1+11/bellsoft-jdk25.0.1+11-"
|
def jdk_download_base = "https://download.bell-sw.com/java/27+36/bellsoft-jdk27+36-"
|
||||||
def jdk_download_suffix = "-full.tar.gz"
|
def jdk_download_suffix = "-full.tar.gz"
|
||||||
def jdk_download_linux_aarch64 = jdk_download_base + "linux-aarch64" + jdk_download_suffix
|
def jdk_download_linux_aarch64 = jdk_download_base + "linux-aarch64" + jdk_download_suffix
|
||||||
def jdk_download_linux_x86_64 = jdk_download_base + "linux-amd64" + jdk_download_suffix
|
def jdk_download_linux_x86_64 = jdk_download_base + "linux-amd64" + jdk_download_suffix
|
||||||
@@ -244,25 +250,146 @@ def jdk_download_windows_aarch64 = jdk_download_base + "windows-aarch64-full.zip
|
|||||||
* @param jvmArgs to use (windows or linux)
|
* @param jvmArgs to use (windows or linux)
|
||||||
* @return configured task.
|
* @return configured task.
|
||||||
*/
|
*/
|
||||||
def configure(org.beryx.runtime.RuntimeZipTask rt, List<String> jvmArgs) {
|
def configure(RuntimeZipTask rt, List<String> jvmArgs) {
|
||||||
//Use the correct set of JVM arguments
|
//Use the correct set of JVM arguments
|
||||||
rt.extension.launcherData.get().jvmArgs = jvmArgs
|
rt.extension.launcherData.get().jvmArgs = jvmArgs
|
||||||
|
|
||||||
//Additional modules to include with auto-detected modules.
|
//Additional modules to include with auto-detected modules.
|
||||||
|
//jdk.charsets - NXDN BIG5 encoding support
|
||||||
//jdk.crypto.ec - needed for HTTPS connections (broadcastify calls & map tile server)
|
//jdk.crypto.ec - needed for HTTPS connections (broadcastify calls & map tile server)
|
||||||
//jdk.incubator.vector - needed for Project Panama foreign function and vector apis
|
//jdk.incubator.vector - needed for Project Panama foreign function and vector apis
|
||||||
//jdk.accessibility is used with assistive technologies like screen readers
|
//jdk.accessibility is used with assistive technologies like screen readers
|
||||||
//java.management for JVM resource monitoring
|
//java.management for JVM resource monitoring
|
||||||
rt.extension.addModules('jdk.crypto.ec', 'jdk.incubator.vector', 'jdk.accessibility', 'java.management')
|
//java.base, java.logging, java.net.http, java.prefs, javafx.controls, javafx.swing - required by sdrtrunk (jdeps)
|
||||||
|
rt.extension.addModules('jdk.charsets', 'jdk.crypto.ec', 'jdk.incubator.vector', 'jdk.accessibility', 'java.management',
|
||||||
|
'java.base', 'java.logging', 'java.net.http', 'java.prefs', 'javafx.controls', 'javafx.swing')
|
||||||
|
|
||||||
//Use auto-detected modules and 'add' any specified modules.
|
//Use only the modules listed above. The runtime plugin's module auto-detection uses a bundled ASM library that
|
||||||
rt.extension.additive.set(true)
|
//can't read Java 27 class files and logs a 'Failed to scan' error for each sdrtrunk class. The jdeps module check
|
||||||
|
//on the runtime task verifies that this list is complete.
|
||||||
|
rt.extension.additive.set(false)
|
||||||
|
|
||||||
//Recommended options for reducing/shrinking runtime target image size
|
//Recommended options for reducing/shrinking runtime target image size
|
||||||
rt.extension.addOptions('--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages')
|
rt.extension.addOptions('--strip-debug', '--compress', 'zip-6', '--no-header-files', '--no-man-pages')
|
||||||
|
|
||||||
//Runtime images have auto appended version in image zip name. Override to include version in single target image.
|
//Runtime images have auto appended version in image zip name. Override to include version in single target image.
|
||||||
rt.extension.imageZip.set(file("$buildDir/image/sdr-trunk.zip"))
|
// rt.extension.imageDir=layout.buildDirectory.dir('image')
|
||||||
|
rt.extension.imageZip.set(file(layout.buildDirectory.dir('image').get().file('sdr-trunk.zip')))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrites the jar file without the native library folders for other operating systems and architectures. Fails the
|
||||||
|
* build if a jar that contains native libraries doesn't contain the folder for the target.
|
||||||
|
* @param jar file to rewrite
|
||||||
|
* @param keep native folder for the target
|
||||||
|
* @return number of bytes removed from the jar
|
||||||
|
*/
|
||||||
|
long stripJar(File jar, String keep) {
|
||||||
|
def tunerPattern = ~/^[^\/]+\/native\/([^\/]+)\/.*/
|
||||||
|
def removed = [] as Set
|
||||||
|
def hadTuner = false, keptTuner = false
|
||||||
|
File temp = new File(jar.parentFile, jar.name + '.tmp')
|
||||||
|
|
||||||
|
new java.util.zip.ZipFile(jar).withCloseable { zip ->
|
||||||
|
def entries = zip.entries().toList()
|
||||||
|
|
||||||
|
entries.each { e ->
|
||||||
|
def tuner = tunerPattern.matcher(e.name)
|
||||||
|
|
||||||
|
if(tuner.matches()) {
|
||||||
|
hadTuner = true
|
||||||
|
if(tuner.group(1) == keep) { keptTuner = true } else { removed << e.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hadTuner && !keptTuner) {
|
||||||
|
throw new GradleException("Native strip: ${jar.name} has no native/${keep} folder")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!removed.isEmpty()) {
|
||||||
|
new java.util.zip.ZipOutputStream(new FileOutputStream(temp)).withCloseable { out ->
|
||||||
|
entries.findAll { !removed.contains(it.name) }.each { e ->
|
||||||
|
def copy = new java.util.zip.ZipEntry(e)
|
||||||
|
if(copy.method == java.util.zip.ZipEntry.DEFLATED) {
|
||||||
|
copy.compressedSize = -1
|
||||||
|
}
|
||||||
|
out.putNextEntry(copy)
|
||||||
|
zip.getInputStream(e).withCloseable { out << it }
|
||||||
|
out.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(removed.isEmpty()) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
long before = jar.length()
|
||||||
|
java.nio.file.Files.move(temp.toPath(), jar.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
return before - jar.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the native libraries for other operating systems and architectures from the jars in each runtime target
|
||||||
|
* image, before the runtimeZip tasks package the images. The tuner libraries (jRTL, jAirspy, etc.) package their
|
||||||
|
* native libraries under '<library>/native/<os>-<arch>/', where the folder name matches the runtime target name
|
||||||
|
* '<os>-<arch>-v<version>' without the version suffix, except that the libraries use 'macos' where the target uses 'osx'.
|
||||||
|
*/
|
||||||
|
tasks.named('runtime') {rt ->
|
||||||
|
rt.doLast {
|
||||||
|
rt.targetPlatforms.get().keySet().each { target ->
|
||||||
|
def nativeFolder = (target - "-v${version}").replaceFirst(/^osx-/, 'macos-')
|
||||||
|
def lib = new File(rt.imageDir.asFile, "${project.name}-${target}/lib")
|
||||||
|
long total = 0
|
||||||
|
lib.listFiles({ File f -> f.name.endsWith('.jar') } as FileFilter).each { jar ->
|
||||||
|
total += stripJar(jar, nativeFolder)
|
||||||
|
}
|
||||||
|
logger.lifecycle("Native strip: removed ${String.format('%.1f', total / 1048576)} MB of other " +
|
||||||
|
"platform native libraries from [${target}]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that each runtime target image contains every module that the sdrtrunk jar requires, as reported by jdeps.
|
||||||
|
* This guards against the runtime plugin's module auto-detection silently missing modules (e.g. when it can't parse
|
||||||
|
* class files compiled for a newer Java version).
|
||||||
|
*/
|
||||||
|
def jdepsHome = javaToolchains.launcherFor(java.toolchain).map { it.metadata.installationPath.asFile }
|
||||||
|
def mainJar = tasks.named('jar').flatMap { it.archiveFile }
|
||||||
|
|
||||||
|
tasks.named('runtime') {rt ->
|
||||||
|
rt.doLast {
|
||||||
|
def jdeps = new File(jdepsHome.get(), 'bin/' + (os.isWindows() ? 'jdeps.exe' : 'jdeps')).absolutePath
|
||||||
|
def process = new ProcessBuilder(jdeps, '--multi-release', java.toolchain.languageVersion.get().toString(),
|
||||||
|
'--ignore-missing-deps', '--print-module-deps', '-q', mainJar.get().asFile.absolutePath)
|
||||||
|
.redirectErrorStream(true).start()
|
||||||
|
def output = process.inputStream.text.trim()
|
||||||
|
|
||||||
|
if(process.waitFor() != 0) {
|
||||||
|
throw new GradleException("Module check: jdeps failed: ${output}")
|
||||||
|
}
|
||||||
|
|
||||||
|
def required = output.split(',')*.trim().findAll { it } as Set
|
||||||
|
|
||||||
|
rt.targetPlatforms.get().keySet().each { target ->
|
||||||
|
def release = new File(rt.imageDir.asFile, "${project.name}-${target}/release")
|
||||||
|
def match = release.text =~ /(?m)^MODULES="([^"]*)"/
|
||||||
|
|
||||||
|
if(!match.find()) {
|
||||||
|
throw new GradleException("Module check: no MODULES entry in ${release}")
|
||||||
|
}
|
||||||
|
|
||||||
|
def missing = required - (match.group(1).split(' ') as Set)
|
||||||
|
|
||||||
|
if(missing) {
|
||||||
|
throw new GradleException("Module check: runtime image [${target}] is missing required modules " +
|
||||||
|
"${missing.sort()} - add them to addModules() in build.gradle")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.lifecycle("Module check: runtime images contain all modules required by sdrtrunk: ${required.sort()}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,35 +401,35 @@ def configure(org.beryx.runtime.RuntimeZipTask rt, List<String> jvmArgs) {
|
|||||||
* Usage: gradlew runtimeZipCurrent (windows - using gradlew)
|
* Usage: gradlew runtimeZipCurrent (windows - using gradlew)
|
||||||
* Usage: ./gradlew runtimeZipCurrent (linux - using gradlew)
|
* Usage: ./gradlew runtimeZipCurrent (linux - using gradlew)
|
||||||
*/
|
*/
|
||||||
tasks.register('runtimeZipCurrent', org.beryx.runtime.RuntimeZipTask) {rt ->
|
tasks.register('runtimeZipCurrent', RuntimeZipTask) {rt ->
|
||||||
def arch = System.properties.getProperty("os.arch")
|
def arch = System.properties.getProperty("os.arch")
|
||||||
def javaHome = org.gradle.internal.jvm.Jvm.current().getJavaHome().toString()
|
def javaHome = Jvm.current().getJavaHome().toString()
|
||||||
|
|
||||||
if(os.isWindows()) {
|
if(os.isWindows()) {
|
||||||
if(arch.equals("amd64")) {
|
if(arch == "amd64") {
|
||||||
rt.extension.targetPlatform(targetWindowsX86_64, javaHome)
|
rt.extension.targetPlatform(targetWindowsX86_64, javaHome)
|
||||||
}
|
}
|
||||||
else if(arch.equals("aarch64")) {
|
else if(arch == "aarch64") {
|
||||||
rt.extension.targetPlatform(targetWindowsAarch64, javaHome)
|
rt.extension.targetPlatform(targetWindowsAarch64, javaHome)
|
||||||
}
|
}
|
||||||
configure(rt, jvmArgsWindows)
|
configure(rt, jvmArgsWindows)
|
||||||
}
|
}
|
||||||
else if(os.isLinux())
|
else if(os.isLinux())
|
||||||
{
|
{
|
||||||
if(arch.equals("amd64")) {
|
if(arch == "amd64") {
|
||||||
rt.extension.targetPlatform(targetLinuxX86_64, javaHome)
|
rt.extension.targetPlatform(targetLinuxX86_64, javaHome)
|
||||||
}
|
}
|
||||||
else if(arch.equals("aarch64")) {
|
else if(arch == "aarch64") {
|
||||||
rt.extension.targetPlatform(targetLinuxAarch64, javaHome)
|
rt.extension.targetPlatform(targetLinuxAarch64, javaHome)
|
||||||
}
|
}
|
||||||
configure(rt, jvmArgsLinux)
|
configure(rt, jvmArgsLinux)
|
||||||
}
|
}
|
||||||
else if(os.isMacOsX())
|
else if(os.isMacOsX())
|
||||||
{
|
{
|
||||||
if(arch.equals("amd64")) {
|
if(arch == "amd64") {
|
||||||
rt.extension.targetPlatform(targetOsxX86_64, javaHome)
|
rt.extension.targetPlatform(targetOsxX86_64, javaHome)
|
||||||
}
|
}
|
||||||
else if(arch.equals("aarch64")) {
|
else if(arch == "aarch64") {
|
||||||
rt.extension.targetPlatform(targetOsxAarch64, javaHome)
|
rt.extension.targetPlatform(targetOsxAarch64, javaHome)
|
||||||
}
|
}
|
||||||
configure(rt, jvmArgsLinux)
|
configure(rt, jvmArgsLinux)
|
||||||
@@ -319,25 +446,15 @@ tasks.register('runtimeZipCurrent', org.beryx.runtime.RuntimeZipTask) {rt ->
|
|||||||
* Usage: gradlew runtimeZipWindows (windows - using gradlew)
|
* Usage: gradlew runtimeZipWindows (windows - using gradlew)
|
||||||
* Usage: ./gradlew runtimeZipWindows (linux - using gradlew)
|
* Usage: ./gradlew runtimeZipWindows (linux - using gradlew)
|
||||||
*/
|
*/
|
||||||
tasks.register('runtimeZipWindows', org.beryx.runtime.RuntimeZipTask) {rt ->
|
tasks.register('runtimeZipWindows', RuntimeZipTask) {rt ->
|
||||||
//Windows aarch64
|
//Windows aarch64
|
||||||
if(file(jdk_windows_aarch64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetWindowsAarch64, jdk_windows_aarch64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetWindowsAarch64) {
|
rt.extension.targetPlatform(targetWindowsAarch64) {
|
||||||
jdkHome = jdkDownload(jdk_download_windows_aarch64)
|
jdkHome = jdkDownload(jdk_download_windows_aarch64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//Windows x86-64
|
//Windows x86-64
|
||||||
if(file(jdk_windows_x86_64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetWindowsX86_64, jdk_windows_x86_64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetWindowsX86_64) {
|
rt.extension.targetPlatform(targetWindowsX86_64) {
|
||||||
jdkHome = jdkDownload(jdk_download_windows_x86_64)
|
jdkHome = jdkDownload(jdk_download_windows_x86_64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
configure(rt, jvmArgsWindows)
|
configure(rt, jvmArgsWindows)
|
||||||
}
|
}
|
||||||
@@ -351,43 +468,23 @@ tasks.register('runtimeZipWindows', org.beryx.runtime.RuntimeZipTask) {rt ->
|
|||||||
* Usage: gradlew runtimeZipOthers (windows - using gradlew)
|
* Usage: gradlew runtimeZipOthers (windows - using gradlew)
|
||||||
* Usage: ./gradlew runtimeZipOthers (linux - using gradlew)
|
* Usage: ./gradlew runtimeZipOthers (linux - using gradlew)
|
||||||
*/
|
*/
|
||||||
tasks.register('runtimeZipOthers', org.beryx.runtime.RuntimeZipTask) {rt ->
|
tasks.register('runtimeZipOthers', RuntimeZipTask) {rt ->
|
||||||
//Linux aarch64
|
//Linux aarch64
|
||||||
if(file(jdk_linux_aarch64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetLinuxAarch64, jdk_linux_aarch64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetLinuxAarch64) {
|
rt.extension.targetPlatform(targetLinuxAarch64) {
|
||||||
jdkHome = jdkDownload(jdk_download_linux_aarch64)
|
jdkHome = jdkDownload(jdk_download_linux_aarch64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//Linux x86-64
|
//Linux x86-64
|
||||||
if(file(jdk_linux_x86_64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetLinuxX86_64, jdk_linux_x86_64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetLinuxX86_64) {
|
rt.extension.targetPlatform(targetLinuxX86_64) {
|
||||||
jdkHome = jdkDownload(jdk_download_linux_x86_64)
|
jdkHome = jdkDownload(jdk_download_linux_x86_64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//OSX aarch64
|
//OSX aarch64
|
||||||
if(file(jdk_osx_aarch64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetOsxAarch64, jdk_osx_aarch64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetOsxAarch64) {
|
rt.extension.targetPlatform(targetOsxAarch64) {
|
||||||
jdkHome = jdkDownload(jdk_download_osx_aarch64)
|
jdkHome = jdkDownload(jdk_download_osx_aarch64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//OSX x86-64
|
//OSX x86-64
|
||||||
if(file(jdk_osx_x86_64).exists()) {
|
|
||||||
rt.extension.targetPlatform(targetOsxX86_64, jdk_osx_x86_64, [])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rt.extension.targetPlatform(targetOsxX86_64) {
|
rt.extension.targetPlatform(targetOsxX86_64) {
|
||||||
jdkHome = jdkDownload(jdk_download_osx_x86_64)
|
jdkHome = jdkDownload(jdk_download_osx_x86_64)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
configure(rt, jvmArgsLinux)
|
configure(rt, jvmArgsLinux)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# ******************************************************************************
|
# ******************************************************************************
|
||||||
# Copyright (C) 2014-2024 Dennis Sheirer
|
# Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,4 +28,4 @@
|
|||||||
# tag name, specifically the dashes inserted before and after the alpha/beta labels.
|
# tag name, specifically the dashes inserted before and after the alpha/beta labels.
|
||||||
# See: https://github.com/DSheirer/sdrtrunk/issues/1651
|
# See: https://github.com/DSheirer/sdrtrunk/issues/1651
|
||||||
|
|
||||||
projectVersion=0.6.2-beta-1
|
projectVersion=1.0.0-beta-1
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
23
gradle/wrapper/gradle-wrapper.properties
vendored
23
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,26 +1,9 @@
|
|||||||
#
|
|
||||||
# ******************************************************************************
|
|
||||||
# Copyright (C) 2014-2025 Dennis Sheirer
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
# *****************************************************************************
|
|
||||||
#
|
|
||||||
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.9.0-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
retries=0
|
||||||
|
retryBackOffMs=500
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
34
gradlew
vendored
34
gradlew
vendored
@@ -1,27 +1,26 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# ******************************************************************************
|
# Copyright © 2015 the original authors.
|
||||||
# Copyright (C) 2014-2025 Dennis Sheirer
|
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# it under the terms of the GNU General Public License as published by
|
# you may not use this file except in compliance with the License.
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# You may obtain a copy of the License at
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# *****************************************************************************
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Gradle start up script for POSIX generated by Gradle.
|
# gradlew start up script for POSIX generated by Gradle.
|
||||||
#
|
#
|
||||||
# Important for running:
|
# Important for running:
|
||||||
#
|
#
|
||||||
@@ -30,7 +29,7 @@
|
|||||||
# bash, then to run this script, type that shell name before the whole
|
# bash, then to run this script, type that shell name before the whole
|
||||||
# command line, like:
|
# command line, like:
|
||||||
#
|
#
|
||||||
# ksh Gradle
|
# ksh gradlew
|
||||||
#
|
#
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
# requires all of these POSIX shell features:
|
# requires all of these POSIX shell features:
|
||||||
@@ -58,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -115,7 +114,6 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH="\\\"\\\""
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -173,7 +171,6 @@ fi
|
|||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if "$cygwin" || "$msys" ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
@@ -213,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
|
||||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
|||||||
86
gradlew.bat
vendored
86
gradlew.bat
vendored
@@ -19,12 +19,39 @@
|
|||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem gradlew startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
setlocal EnableExtensions
|
||||||
|
|
||||||
|
@rem Catch executions from older scripts and ensure they exit cleanly.
|
||||||
|
@rem This can be removed once we can be reasonably confident that few people
|
||||||
|
@rem will be migrating directly to this new wrapper.
|
||||||
|
goto afterSafetyNet
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
goto exitWithErrorLevel
|
||||||
|
:afterSafetyNet
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
@@ -45,13 +72,14 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
1>&2 echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
1>&2 echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
1>&2 echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
goto exitWithErrorLevel
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
@@ -59,36 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
1>&2 echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
1>&2 echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
1>&2 echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
goto exitWithErrorLevel
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute gradlew
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||||
|
@rem which allows us to clear the local environment before executing the java command
|
||||||
|
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
|
||||||
|
|
||||||
:end
|
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
|
||||||
@rem End local scope for the variables with windows NT shell
|
:exitWithErrorLevel
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||||
|
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
||||||
|
|||||||
1023
sdr-trunk.ipr
1023
sdr-trunk.ipr
File diff suppressed because it is too large
Load Diff
@@ -1 +1,86 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
|
||||||
|
}
|
||||||
rootProject.name = 'sdr-trunk'
|
rootProject.name = 'sdr-trunk'
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url = 'https://jitpack.io' }
|
||||||
|
|
||||||
|
//jAirspy is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jAirspy/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jairspy' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jAirspyHF is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jAirspyHF/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jairspyhf' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jRTL is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jRTL/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jrtl' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jlibusb is published as a GitHub release, with libusb for all platforms in the jar. Tuner libraries built on
|
||||||
|
//jlibusb (jAirspy, jAirspyHF, jBladeRF, jHackRF, jHydraSDR, jLimeSDR, jRTL) load their native library next to its libusb, so the process shares one copy.
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jlibusb/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jlibusb' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jHackRF is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jHackRF/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jhackrf' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jHydraSDR is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jHydraSDR/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jhydrasdr' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jLimeSDR is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jLimeSDR/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jlimesdr' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jsdrplay is published as a GitHub release. The jar does not contain the SDRplay API native library, which
|
||||||
|
//users install separately from sdrplay.com
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jsdrplay/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jsdrplay' }
|
||||||
|
}
|
||||||
|
|
||||||
|
//jBladeRF is published as a GitHub release, with the native libraries for all platforms in the jar
|
||||||
|
ivy {
|
||||||
|
url = 'https://github.com/DSheirer/jBladeRF/releases/download'
|
||||||
|
patternLayout { artifact 'v[revision]/[artifact]-[revision].[ext]' }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
content { includeModule 'io.github.dsheirer', 'jbladerf' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sun.java.swing.plaf.windows;
|
||||||
|
|
||||||
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.UIDefaults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-op stub for the JDK's Windows look-and-feel.
|
||||||
|
*
|
||||||
|
* <p>JIDE 3.6.18's {@code LookAndFeelFactory} contains compile-time
|
||||||
|
* {@code instanceof com.sun.java.swing.plaf.windows.WindowsLookAndFeel} checks throughout its
|
||||||
|
* dispatch logic. On Linux and macOS JDK builds that class is genuinely absent from
|
||||||
|
* {@code java.desktop}, so the JVM throws {@link NoClassDefFoundError} the first time JIDE's
|
||||||
|
* dispatch code executes the {@code instanceof} bytecode. That happens during
|
||||||
|
* {@link com.jidesoft.swing.JideSplitPane#updateUI()} on every LAF change.
|
||||||
|
*
|
||||||
|
* <p>This stub lives in the classpath so the class reference resolves on non-Windows JDKs.
|
||||||
|
* On Windows JDK builds the real {@code WindowsLookAndFeel} is loaded from the
|
||||||
|
* {@code java.desktop} module via the boot class loader and shadows this class.
|
||||||
|
*
|
||||||
|
* <p>The stub reports itself as not native and not supported - JIDE never instantiates this
|
||||||
|
* class, it only uses it for {@code instanceof} comparisons against the active LAF. Since
|
||||||
|
* sdrtrunk never installs this LAF, the {@code instanceof} check always returns false and
|
||||||
|
* JIDE proceeds to its next branch.
|
||||||
|
*/
|
||||||
|
public class WindowsLookAndFeel extends LookAndFeel
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return "Windows (stub)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return "WindowsStub";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return "Compatibility stub for JIDE's instanceof checks on non-Windows JDKs.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNativeLookAndFeel()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupportedLookAndFeel()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIDefaults getDefaults()
|
||||||
|
{
|
||||||
|
return new UIDefaults();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,12 +30,16 @@ import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
|||||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||||
import io.github.dsheirer.alias.id.priority.Priority;
|
import io.github.dsheirer.alias.id.priority.Priority;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
||||||
import io.github.dsheirer.alias.id.radio.Radio;
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||||
import io.github.dsheirer.alias.id.record.Record;
|
import io.github.dsheirer.alias.id.record.Record;
|
||||||
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
||||||
import io.github.dsheirer.alias.id.status.UserStatusID;
|
import io.github.dsheirer.alias.id.status.UserStatusID;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||||
@@ -79,6 +83,31 @@ public class AliasFactory
|
|||||||
Min copyMin = new Min();
|
Min copyMin = new Min();
|
||||||
copyMin.setMin(originalMin.getMin());
|
copyMin.setMin(originalMin.getMin());
|
||||||
return copyMin;
|
return copyMin;
|
||||||
|
case NXDN_TYPE_D_RADIO_ID:
|
||||||
|
NXDNTypeDRadio originalTypeDRadio = (NXDNTypeDRadio)id;
|
||||||
|
NXDNTypeDRadio copyTypeDRadio = new NXDNTypeDRadio(originalTypeDRadio.getHomeRepeater(),
|
||||||
|
originalTypeDRadio.getIdentifier());
|
||||||
|
copyTypeDRadio.setOverlap(originalTypeDRadio.overlapProperty().get());
|
||||||
|
return copyTypeDRadio;
|
||||||
|
case NXDN_TYPE_D_RADIO_ID_RANGE:
|
||||||
|
NXDNTypeDRadioRange originalTypeDRadioRange = (NXDNTypeDRadioRange)id;
|
||||||
|
NXDNTypeDRadioRange copyTypeDRadioRange = new NXDNTypeDRadioRange(originalTypeDRadioRange.getHomeRepeater(),
|
||||||
|
originalTypeDRadioRange.getMinIdentifier(), originalTypeDRadioRange.getMaxIdentifier());
|
||||||
|
copyTypeDRadioRange.setOverlap(originalTypeDRadioRange.overlapProperty().get());
|
||||||
|
return copyTypeDRadioRange;
|
||||||
|
case NXDN_TYPE_D_TALKGROUP:
|
||||||
|
NXDNTypeDTalkgroup originalTypeDTalkgroup = (NXDNTypeDTalkgroup)id;
|
||||||
|
NXDNTypeDTalkgroup copyTypeDTalkgroup = new NXDNTypeDTalkgroup(originalTypeDTalkgroup.getHomeRepeater(),
|
||||||
|
originalTypeDTalkgroup.getIdentifier());
|
||||||
|
copyTypeDTalkgroup.setOverlap(originalTypeDTalkgroup.overlapProperty().get());
|
||||||
|
return copyTypeDTalkgroup;
|
||||||
|
case NXDN_TYPE_D_TALKGROUP_RANGE:
|
||||||
|
NXDNTypeDTalkgroupRange originalTypeDTalkgroupRange = (NXDNTypeDTalkgroupRange)id;
|
||||||
|
NXDNTypeDTalkgroupRange copyTypeDTalkgroupRange = new NXDNTypeDTalkgroupRange(
|
||||||
|
originalTypeDTalkgroupRange.getHomeRepeater(), originalTypeDTalkgroupRange.getMinIdentifier(),
|
||||||
|
originalTypeDTalkgroupRange.getMaxIdentifier());
|
||||||
|
copyTypeDTalkgroupRange.setOverlap(originalTypeDTalkgroupRange.overlapProperty().get());
|
||||||
|
return copyTypeDTalkgroupRange;
|
||||||
case P25_FULLY_QUALIFIED_RADIO_ID:
|
case P25_FULLY_QUALIFIED_RADIO_ID:
|
||||||
P25FullyQualifiedRadio originalP25 = (P25FullyQualifiedRadio) id;
|
P25FullyQualifiedRadio originalP25 = (P25FullyQualifiedRadio) id;
|
||||||
P25FullyQualifiedRadio copyP25 = new P25FullyQualifiedRadio(originalP25.getWacn(),
|
P25FullyQualifiedRadio copyP25 = new P25FullyQualifiedRadio(originalP25.getWacn(),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import io.github.dsheirer.identifier.talkgroup.FullyQualifiedTalkgroupIdentifier
|
|||||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||||
import io.github.dsheirer.identifier.tone.ToneIdentifier;
|
import io.github.dsheirer.identifier.tone.ToneIdentifier;
|
||||||
import io.github.dsheirer.identifier.tone.ToneSequence;
|
import io.github.dsheirer.identifier.tone.ToneSequence;
|
||||||
import io.github.dsheirer.module.decode.dcs.DCSCode;
|
import io.github.dsheirer.module.decode.squelch.dcs.DCSCode;
|
||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -134,6 +134,7 @@ public class AliasList
|
|||||||
switch(id.getType())
|
switch(id.getType())
|
||||||
{
|
{
|
||||||
case TALKGROUP:
|
case TALKGROUP:
|
||||||
|
case NXDN_TYPE_D_TALKGROUP:
|
||||||
Talkgroup talkgroup = (Talkgroup)id;
|
Talkgroup talkgroup = (Talkgroup)id;
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
||||||
@@ -147,6 +148,7 @@ public class AliasList
|
|||||||
talkgroupAliasList.add(talkgroup, alias);
|
talkgroupAliasList.add(talkgroup, alias);
|
||||||
break;
|
break;
|
||||||
case TALKGROUP_RANGE:
|
case TALKGROUP_RANGE:
|
||||||
|
case NXDN_TYPE_D_TALKGROUP_RANGE:
|
||||||
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
||||||
@@ -186,6 +188,7 @@ public class AliasList
|
|||||||
p25TalkgroupAliasList.add(qualifiedTalkgroup, alias);
|
p25TalkgroupAliasList.add(qualifiedTalkgroup, alias);
|
||||||
break;
|
break;
|
||||||
case RADIO_ID:
|
case RADIO_ID:
|
||||||
|
case NXDN_TYPE_D_RADIO_ID:
|
||||||
Radio radio = (Radio)id;
|
Radio radio = (Radio)id;
|
||||||
|
|
||||||
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
||||||
@@ -199,6 +202,7 @@ public class AliasList
|
|||||||
radioAliasList.add(radio, alias);
|
radioAliasList.add(radio, alias);
|
||||||
break;
|
break;
|
||||||
case RADIO_ID_RANGE:
|
case RADIO_ID_RANGE:
|
||||||
|
case NXDN_TYPE_D_RADIO_ID_RANGE:
|
||||||
RadioRange radioRange = (RadioRange)id;
|
RadioRange radioRange = (RadioRange)id;
|
||||||
|
|
||||||
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
||||||
|
|||||||
@@ -35,12 +35,16 @@ import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
|||||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||||
import io.github.dsheirer.alias.id.priority.Priority;
|
import io.github.dsheirer.alias.id.priority.Priority;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadio;
|
||||||
|
import io.github.dsheirer.alias.id.radio.NXDNTypeDRadioRange;
|
||||||
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
import io.github.dsheirer.alias.id.radio.P25FullyQualifiedRadio;
|
||||||
import io.github.dsheirer.alias.id.radio.Radio;
|
import io.github.dsheirer.alias.id.radio.Radio;
|
||||||
import io.github.dsheirer.alias.id.radio.RadioRange;
|
import io.github.dsheirer.alias.id.radio.RadioRange;
|
||||||
import io.github.dsheirer.alias.id.record.Record;
|
import io.github.dsheirer.alias.id.record.Record;
|
||||||
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
import io.github.dsheirer.alias.id.status.UnitStatusID;
|
||||||
import io.github.dsheirer.alias.id.status.UserStatusID;
|
import io.github.dsheirer.alias.id.status.UserStatusID;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroup;
|
||||||
|
import io.github.dsheirer.alias.id.talkgroup.NXDNTypeDTalkgroupRange;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.P25FullyQualifiedTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.StreamAsTalkgroup;
|
||||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||||
@@ -64,6 +68,10 @@ import javafx.util.Callback;
|
|||||||
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
||||||
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
||||||
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDRadio.class, name = "nxdnTypeDRadio"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDRadioRange.class, name = "nxdnTypeDRadioRange"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDTalkgroup.class, name = "nxdnTypeDTalkgroup"),
|
||||||
|
@JsonSubTypes.Type(value = NXDNTypeDTalkgroupRange.class, name = "nxdnTypeDTalkgroupRange"),
|
||||||
@JsonSubTypes.Type(value = P25FullyQualifiedRadio.class, name = "p25FullyQualifiedRadio"),
|
@JsonSubTypes.Type(value = P25FullyQualifiedRadio.class, name = "p25FullyQualifiedRadio"),
|
||||||
@JsonSubTypes.Type(value = P25FullyQualifiedTalkgroup.class, name = "p25FullyQualifiedTalkgroup"),
|
@JsonSubTypes.Type(value = P25FullyQualifiedTalkgroup.class, name = "p25FullyQualifiedTalkgroup"),
|
||||||
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ public enum AliasIDType
|
|||||||
LOJACK("LoJack"),
|
LOJACK("LoJack"),
|
||||||
LTR_NET_UID("LTR-Net UID"),
|
LTR_NET_UID("LTR-Net UID"),
|
||||||
MIN("Passport MIN"),
|
MIN("Passport MIN"),
|
||||||
|
NXDN_TYPE_D_RADIO_ID("NXDN Type-D Radio ID"),
|
||||||
|
NXDN_TYPE_D_RADIO_ID_RANGE("NXDN Type-D Radio ID Range"),
|
||||||
|
NXDN_TYPE_D_TALKGROUP("NXDN Type-D Talkgroup"),
|
||||||
|
NXDN_TYPE_D_TALKGROUP_RANGE("NXDN Type-D Talkgroup Range"),
|
||||||
P25_FULLY_QUALIFIED_RADIO_ID("P25 Fully Qualified Radio ID"),
|
P25_FULLY_QUALIFIED_RADIO_ID("P25 Fully Qualified Radio ID"),
|
||||||
P25_FULLY_QUALIFIED_TALKGROUP("P25 Fully Qualified Talkgroup"),
|
P25_FULLY_QUALIFIED_TALKGROUP("P25 Fully Qualified Talkgroup"),
|
||||||
PRIORITY("Audio Priority"),
|
PRIORITY("Audio Priority"),
|
||||||
@@ -58,6 +62,7 @@ public enum AliasIDType
|
|||||||
|
|
||||||
//Values used by the View-By alias editor
|
//Values used by the View-By alias editor
|
||||||
public static EnumSet<AliasIDType> VIEW_BY_VALUES = EnumSet.of(TALKGROUP, TALKGROUP_RANGE, RADIO_ID, RADIO_ID_RANGE,
|
public static EnumSet<AliasIDType> VIEW_BY_VALUES = EnumSet.of(TALKGROUP, TALKGROUP_RANGE, RADIO_ID, RADIO_ID_RANGE,
|
||||||
|
NXDN_TYPE_D_RADIO_ID, NXDN_TYPE_D_RADIO_ID_RANGE, NXDN_TYPE_D_TALKGROUP, NXDN_TYPE_D_TALKGROUP_RANGE,
|
||||||
P25_FULLY_QUALIFIED_RADIO_ID, P25_FULLY_QUALIFIED_TALKGROUP, UNIT_STATUS, STATUS, TONES);
|
P25_FULLY_QUALIFIED_RADIO_ID, P25_FULLY_QUALIFIED_TALKGROUP, UNIT_STATUS, STATUS, TONES);
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
|
|||||||
46
src/main/java/io/github/dsheirer/alias/id/INXDNTypeD.java
Normal file
46
src/main/java/io/github/dsheirer/alias/id/INXDNTypeD.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D alias identifier composed of a home repeater and a radio or talkgroup identifier value.
|
||||||
|
*/
|
||||||
|
public interface INXDNTypeD
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Home repeater for the identifier
|
||||||
|
*/
|
||||||
|
int getHomeRepeater();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the home repeater for the identifier
|
||||||
|
*/
|
||||||
|
void setHomeRepeater(int homeRepeater);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setIdentifier(int identifier);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D alias identifier range of radio or talkgroup values that share a common home repeater.
|
||||||
|
*/
|
||||||
|
public interface INXDNTypeDRange
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Home repeater for the range
|
||||||
|
*/
|
||||||
|
int getHomeRepeater();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the home repeater for the range
|
||||||
|
*/
|
||||||
|
void setHomeRepeater(int homeRepeater);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getMinIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the minimum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setMinIdentifier(int identifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
int getMaxIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum radio or talkgroup value, without the home repeater.
|
||||||
|
*/
|
||||||
|
void setMaxIdentifier(int identifier);
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ package io.github.dsheirer.alias.id.dcs;
|
|||||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||||
import io.github.dsheirer.alias.id.AliasID;
|
import io.github.dsheirer.alias.id.AliasID;
|
||||||
import io.github.dsheirer.alias.id.AliasIDType;
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
import io.github.dsheirer.module.decode.dcs.DCSCode;
|
import io.github.dsheirer.module.decode.squelch.dcs.DCSCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Digital Coded Squelch (DCS) tone identifier
|
* Digital Coded Squelch (DCS) tone identifier
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id.radio;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D radio. The value is the over-the-air 16-bit identifier that combines the home repeater and radio so that
|
||||||
|
* it matches the value of an NXDN Type-D radio identifier.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDRadio extends Radio implements INXDNTypeD
|
||||||
|
{
|
||||||
|
public NXDNTypeDRadio()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the radio
|
||||||
|
* @param radio value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDRadio(int homeRepeater, int radio)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, radio));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_RADIO_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, getIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Radio ID:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id.radio;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D radio range for a single home repeater. The min and max values are the over-the-air 16-bit identifiers
|
||||||
|
* that combine the home repeater and radio.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDRadioRange extends RadioRange implements INXDNTypeDRange
|
||||||
|
{
|
||||||
|
public NXDNTypeDRadioRange()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the range
|
||||||
|
* @param minRadio value, without the home repeater
|
||||||
|
* @param maxRadio value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDRadioRange(int homeRepeater, int minRadio, int maxRadio)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, minRadio),
|
||||||
|
NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, maxRadio));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_RADIO_ID_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMinRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
int min = getMinIdentifier();
|
||||||
|
int max = getMaxIdentifier();
|
||||||
|
setMinRadio(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, min));
|
||||||
|
setMaxRadio(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMinIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMinRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMinRadio(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMaxIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMaxRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMaxRadio(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid when the base range is valid and both ends of the range use the same home repeater.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid()
|
||||||
|
{
|
||||||
|
return super.isValid() && getHomeRepeater() == NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMaxRadio());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Radio ID Range:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMinIdentifier(), true));
|
||||||
|
sb.append(" to ").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMaxIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.alias.id.radio;
|
package io.github.dsheirer.alias.id.radio;
|
||||||
@@ -38,10 +35,11 @@ public enum RadioFormat
|
|||||||
"<html>APCO25 valid range is 0 to 16,777,215"),
|
"<html>APCO25 valid range is 0 to 16,777,215"),
|
||||||
DMR("********", 0, 0xFFFFFF, "0 to 16,777,215",
|
DMR("********", 0, 0xFFFFFF, "0 to 16,777,215",
|
||||||
"<html>DMR unit id valid range is 0 to 16,777,215"),
|
"<html>DMR unit id valid range is 0 to 16,777,215"),
|
||||||
|
NXDN("*****", 1, 0xFFFF, "1 to 65,535", "NXDN valid range is 1 to 65,535"),
|
||||||
PASSPORT("********", 0, 0x7FFFFF, "0 to 8,388,607",
|
PASSPORT("********", 0, 0x7FFFFF, "0 to 8,388,607",
|
||||||
"<html>PASSPORT valid range is 0 to 8,388,607"),
|
"<html>PASSPORT valid range is 0 to 8,388,607"),
|
||||||
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||||
"Unknown protocol valid value range is 1-16,777,215");
|
"<html>Unknown protocol valid value range is 1-16,777,215");
|
||||||
|
|
||||||
private String mMask;
|
private String mMask;
|
||||||
private int mMinimumValue;
|
private int mMinimumValue;
|
||||||
@@ -116,6 +114,8 @@ public enum RadioFormat
|
|||||||
return APCO25;
|
return APCO25;
|
||||||
case DMR:
|
case DMR:
|
||||||
return DMR;
|
return DMR;
|
||||||
|
case NXDN:
|
||||||
|
return NXDN;
|
||||||
case PASSPORT:
|
case PASSPORT:
|
||||||
return PASSPORT;
|
return PASSPORT;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.alias.id.radio;
|
package io.github.dsheirer.alias.id.radio;
|
||||||
@@ -26,14 +23,14 @@ import io.github.dsheirer.preference.identifier.IntegerFormat;
|
|||||||
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.AbstractIntegerFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.AbstractIntegerFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.DMRTalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.DMRTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
|
||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol-specific formatting of radio id values and parsing of formatted radio id values.
|
* Protocol-specific formatting of radio id values and parsing of formatted radio id values.
|
||||||
@@ -47,6 +44,7 @@ public class RadioFormatter
|
|||||||
{
|
{
|
||||||
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
|
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
|
||||||
mFormatterMap.put(Protocol.DMR, new DMRTalkgroupFormatter());
|
mFormatterMap.put(Protocol.DMR, new DMRTalkgroupFormatter());
|
||||||
|
mFormatterMap.put(Protocol.NXDN, new NXDNTalkgroupFormatter());
|
||||||
mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
|
mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id.talkgroup;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeD;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D talkgroup. The value is the over-the-air 16-bit identifier that combines the home repeater and talkgroup
|
||||||
|
* so that it matches the value of an NXDN Type-D talkgroup identifier.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDTalkgroup extends Talkgroup implements INXDNTypeD
|
||||||
|
{
|
||||||
|
public NXDNTypeDTalkgroup()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the talkgroup
|
||||||
|
* @param talkgroup value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDTalkgroup(int homeRepeater, int talkgroup)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, talkgroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_TALKGROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, getIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setValue(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Talkgroup:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.dsheirer.alias.id.talkgroup;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.github.dsheirer.alias.id.AliasIDType;
|
||||||
|
import io.github.dsheirer.alias.id.INXDNTypeDRange;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NXDN Type-D talkgroup range for a single home repeater. The min and max values are the over-the-air 16-bit
|
||||||
|
* identifiers that combine the home repeater and talkgroup.
|
||||||
|
*/
|
||||||
|
public class NXDNTypeDTalkgroupRange extends TalkgroupRange implements INXDNTypeDRange
|
||||||
|
{
|
||||||
|
public NXDNTypeDTalkgroupRange()
|
||||||
|
{
|
||||||
|
//No-arg JAXB constructor
|
||||||
|
setProtocol(Protocol.NXDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param homeRepeater for the range
|
||||||
|
* @param minTalkgroup value, without the home repeater
|
||||||
|
* @param maxTalkgroup value, without the home repeater
|
||||||
|
*/
|
||||||
|
public NXDNTypeDTalkgroupRange(int homeRepeater, int minTalkgroup, int maxTalkgroup)
|
||||||
|
{
|
||||||
|
super(Protocol.NXDN, NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, minTalkgroup),
|
||||||
|
NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, maxTalkgroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AliasIDType getType()
|
||||||
|
{
|
||||||
|
return AliasIDType.NXDN_TYPE_D_TALKGROUP_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getHomeRepeater()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMinTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHomeRepeater(int homeRepeater)
|
||||||
|
{
|
||||||
|
int min = getMinIdentifier();
|
||||||
|
int max = getMaxIdentifier();
|
||||||
|
setMinTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, min));
|
||||||
|
setMaxTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(homeRepeater, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMinIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMinTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMinTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public int getMaxIdentifier()
|
||||||
|
{
|
||||||
|
return NXDNTalkgroupFormatter.getTypeDIdentifier(getMaxTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxIdentifier(int identifier)
|
||||||
|
{
|
||||||
|
setMaxTalkgroup(NXDNTalkgroupFormatter.toTypeDValue(getHomeRepeater(), identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid when the base range is valid and both ends of the range use the same home repeater.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid()
|
||||||
|
{
|
||||||
|
return super.isValid() &&
|
||||||
|
getHomeRepeater() == NXDNTalkgroupFormatter.getTypeDHomeRepeater(getMaxTalkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Type-D Talkgroup Range:").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMinIdentifier(), true));
|
||||||
|
sb.append(" to ").append(NXDNTalkgroupFormatter.toTypeD(getHomeRepeater(), getMaxIdentifier(), true));
|
||||||
|
sb.append(" Protocol:").append(getProtocol());
|
||||||
|
|
||||||
|
if(!isValid())
|
||||||
|
{
|
||||||
|
sb.append(" **NOT VALID**");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.alias.id.talkgroup;
|
package io.github.dsheirer.alias.id.talkgroup;
|
||||||
@@ -50,6 +47,8 @@ public enum TalkgroupFormat
|
|||||||
"<html>MPT-1327 valid ranges are 0-127(prefix)<br>and 1-8192(ident) (ie. 000-0001 to 127-8192)"),
|
"<html>MPT-1327 valid ranges are 0-127(prefix)<br>and 1-8192(ident) (ie. 000-0001 to 127-8192)"),
|
||||||
NBFM("*****", 1, 0xFFFF, "1 to 65,535",
|
NBFM("*****", 1, 0xFFFF, "1 to 65,535",
|
||||||
"NBFM valid value range is 1-65,535"),
|
"NBFM valid value range is 1-65,535"),
|
||||||
|
NXDN("*****", 0, 0xFFFF, "0 to 65,535",
|
||||||
|
"NXDN talkgroup valid range is 0 to 65,535"),
|
||||||
PASSPORT("*****", 1, 0xFFFF, "1 to 65,535",
|
PASSPORT("*****", 1, 0xFFFF, "1 to 65,535",
|
||||||
"Passport valid value range is 1-65,535"),
|
"Passport valid value range is 1-65,535"),
|
||||||
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||||
@@ -139,6 +138,8 @@ public enum TalkgroupFormat
|
|||||||
return MPT1327;
|
return MPT1327;
|
||||||
case NBFM:
|
case NBFM:
|
||||||
return NBFM;
|
return NBFM;
|
||||||
|
case NXDN:
|
||||||
|
return NXDN;
|
||||||
case PASSPORT:
|
case PASSPORT:
|
||||||
return PASSPORT;
|
return PASSPORT;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,6 +28,7 @@ import io.github.dsheirer.preference.identifier.talkgroup.FleetsyncTalkgroupForm
|
|||||||
import io.github.dsheirer.preference.identifier.talkgroup.LTRTalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.LTRTalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.MDC1200TalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.MDC1200TalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.MPT1327TalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.MPT1327TalkgroupFormatter;
|
||||||
|
import io.github.dsheirer.preference.identifier.talkgroup.NXDNTalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.PassportTalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.PassportTalkgroupFormatter;
|
||||||
import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
|
import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
|
||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
@@ -59,6 +60,7 @@ public class TalkgroupFormatter
|
|||||||
mFormatterMap.put(Protocol.LTR_NET, ltr);
|
mFormatterMap.put(Protocol.LTR_NET, ltr);
|
||||||
mFormatterMap.put(Protocol.MDC1200, new MDC1200TalkgroupFormatter());
|
mFormatterMap.put(Protocol.MDC1200, new MDC1200TalkgroupFormatter());
|
||||||
mFormatterMap.put(Protocol.MPT1327, new MPT1327TalkgroupFormatter());
|
mFormatterMap.put(Protocol.MPT1327, new MPT1327TalkgroupFormatter());
|
||||||
|
mFormatterMap.put(Protocol.NXDN, new NXDNTalkgroupFormatter());
|
||||||
mFormatterMap.put(Protocol.PASSPORT, new PassportTalkgroupFormatter());
|
mFormatterMap.put(Protocol.PASSPORT, new PassportTalkgroupFormatter());
|
||||||
mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
|
mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.github.dsheirer.audio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for defining an array list of filter methods to be implemented in AudioModule
|
||||||
|
* The filters will be applied in the order given in the list.
|
||||||
|
* Each audio filter mush implement the filter method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractAudioFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* To be overridden by each audio filter
|
||||||
|
* @param audio a buffer of 8 KHz audio samples
|
||||||
|
* @return float[] filtered buffer of 8 KHz audio samples
|
||||||
|
*/
|
||||||
|
public abstract float[] filter(float[] audio);
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
public abstract class AbstractAudioModule extends Module implements IAudioSegmentProvider, IdentifierUpdateListener
|
public abstract class AbstractAudioModule extends Module implements IAudioSegmentProvider, IdentifierUpdateListener
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(AbstractAudioModule.class);
|
private final static Logger mLog = LoggerFactory.getLogger(AbstractAudioModule.class);
|
||||||
public static final long DEFAULT_SEGMENT_AUDIO_SAMPLE_LENGTH = 60 * 8000; // 1 minute @ 8kHz
|
public static final long DEFAULT_MAX_SEGMENT_LENGTH_MILLIS = 60_000; // 1 minute
|
||||||
public static final int DEFAULT_TIMESLOT = 0;
|
public static final int DEFAULT_TIMESLOT = 0;
|
||||||
private final int mMaxSegmentAudioSampleLength;
|
private final int mMaxSegmentAudioSampleLength;
|
||||||
private Listener<AudioSegment> mAudioSegmentListener;
|
private Listener<AudioSegment> mAudioSegmentListener;
|
||||||
@@ -51,12 +51,12 @@ public abstract class AbstractAudioModule extends Module implements IAudioSegmen
|
|||||||
* Constructs an abstract audio module
|
* Constructs an abstract audio module
|
||||||
*
|
*
|
||||||
* @param aliasList for aliasing identifiers
|
* @param aliasList for aliasing identifiers
|
||||||
* @param maxSegmentAudioSampleLength in milliseconds
|
* @param maxSegmentLengthMillis maximum audio segment length in milliseconds
|
||||||
*/
|
*/
|
||||||
public AbstractAudioModule(AliasList aliasList, int timeslot, long maxSegmentAudioSampleLength)
|
public AbstractAudioModule(AliasList aliasList, int timeslot, long maxSegmentLengthMillis)
|
||||||
{
|
{
|
||||||
mAliasList = aliasList;
|
mAliasList = aliasList;
|
||||||
mMaxSegmentAudioSampleLength = (int)(maxSegmentAudioSampleLength * 8); //Convert milliseconds to samples
|
mMaxSegmentAudioSampleLength = (int)(maxSegmentLengthMillis * 8); //Convert milliseconds to samples
|
||||||
mTimeslot = timeslot;
|
mTimeslot = timeslot;
|
||||||
mIdentifierCollection = new MutableIdentifierCollection(getTimeslot());
|
mIdentifierCollection = new MutableIdentifierCollection(getTimeslot());
|
||||||
mIdentifierUpdateNotificationBroadcaster.addListener(mIdentifierCollection);
|
mIdentifierUpdateNotificationBroadcaster.addListener(mIdentifierCollection);
|
||||||
@@ -67,7 +67,7 @@ public abstract class AbstractAudioModule extends Module implements IAudioSegmen
|
|||||||
*/
|
*/
|
||||||
public AbstractAudioModule(AliasList aliasList)
|
public AbstractAudioModule(AliasList aliasList)
|
||||||
{
|
{
|
||||||
this(aliasList, DEFAULT_TIMESLOT, DEFAULT_SEGMENT_AUDIO_SAMPLE_LENGTH);
|
this(aliasList, DEFAULT_TIMESLOT, DEFAULT_MAX_SEGMENT_LENGTH_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,31 +17,28 @@
|
|||||||
* ****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.source.tuner.sdrplay.api.parameter.event;
|
package io.github.dsheirer.audio;
|
||||||
|
|
||||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_RspDuoModeCbParamT;
|
import io.github.dsheirer.dsp.gain.AudioGainAndDcFilter;
|
||||||
import java.lang.foreign.MemorySegment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RSP-Duo Mode Callback Parameters (sdrplay_api_RspDuoModeCbParamT)
|
* This is a wrapper for the AudioGainAndDcFilter class so it can be used with the AudioModule filter list.
|
||||||
|
* Usually instantiated in the DecoderFactory
|
||||||
*/
|
*/
|
||||||
public class RspDuoModeCallbackParameters
|
public class AudioGainFilter extends AbstractAudioFilter
|
||||||
{
|
{
|
||||||
private final RspDuoModeEventType mRspDuoModeEventType;
|
AudioGainAndDcFilter mAudioGain;
|
||||||
|
|
||||||
/**
|
public AudioGainFilter(float minGain, float maxGain, float objectiveAmplitude)
|
||||||
* Constructs an instance from the foreign memory segment
|
|
||||||
*/
|
|
||||||
public RspDuoModeCallbackParameters(MemorySegment rspDuoModeCbParam)
|
|
||||||
{
|
{
|
||||||
mRspDuoModeEventType = RspDuoModeEventType.fromValue(sdrplay_api_RspDuoModeCbParamT.modeChangeType(rspDuoModeCbParam));
|
mAudioGain = new AudioGainAndDcFilter(minGain, maxGain, objectiveAmplitude);
|
||||||
|
mAudioGain.setDecayRate(2); // to remove pumping effect
|
||||||
|
mAudioGain.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Event type
|
public float[] filter(float[] audio)
|
||||||
*/
|
|
||||||
public RspDuoModeEventType getRspDuoModeEvent()
|
|
||||||
{
|
{
|
||||||
return mRspDuoModeEventType;
|
return mAudioGain.process(audio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,8 @@ import io.github.dsheirer.sample.real.IRealBufferListener;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides packaging of demodulated audio sample buffers into audio segments for broadcast to registered listeners.
|
* Provides packaging of demodulated audio sample buffers into audio segments for broadcast to registered listeners.
|
||||||
* Includes audio packet metadata in constructed audio segments.
|
* Includes audio packet metadata in constructed audio segments.
|
||||||
@@ -42,36 +44,7 @@ public class AudioModule extends AbstractAudioModule implements ISquelchStateLis
|
|||||||
Listener<float[]>
|
Listener<float[]>
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
|
private static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
|
||||||
private static float[] sHighPassFilterCoefficients;
|
private List<AbstractAudioFilter>mAudioFilters;
|
||||||
private final boolean mAudioFilterEnable;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
|
|
||||||
.sampleRate(8000)
|
|
||||||
.stopBandCutoff(200)
|
|
||||||
.stopBandAmplitude(0.0)
|
|
||||||
.stopBandRipple(0.025)
|
|
||||||
.passBandStart(300)
|
|
||||||
.passBandAmplitude(1.0)
|
|
||||||
.passBandRipple(0.01)
|
|
||||||
.build();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
|
|
||||||
|
|
||||||
if(designer.isValid())
|
|
||||||
{
|
|
||||||
sHighPassFilterCoefficients = designer.getImpulseResponse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(FilterDesignException fde)
|
|
||||||
{
|
|
||||||
mLog.error("Filter design error", fde);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final IRealFilter mHighPassFilter = FilterFactory.getRealFilter(sHighPassFilterCoefficients);
|
|
||||||
private final SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
private final SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
||||||
private SquelchState mSquelchState = SquelchState.SQUELCH;
|
private SquelchState mSquelchState = SquelchState.SQUELCH;
|
||||||
|
|
||||||
@@ -81,23 +54,23 @@ public class AudioModule extends AbstractAudioModule implements ISquelchStateLis
|
|||||||
* @param aliasList for aliasing identifiers
|
* @param aliasList for aliasing identifiers
|
||||||
* @param timeslot for this audio module
|
* @param timeslot for this audio module
|
||||||
* @param maxAudioSegmentLength in milliseconds
|
* @param maxAudioSegmentLength in milliseconds
|
||||||
* @param audioFilterEnable to enable or disable high-pass audio filter
|
* @param audioFilters a list of audio filters to apply to the incoming audio samples
|
||||||
*/
|
*/
|
||||||
public AudioModule(AliasList aliasList, int timeslot, long maxAudioSegmentLength, boolean audioFilterEnable)
|
public AudioModule(AliasList aliasList, int timeslot, long maxAudioSegmentLength, List<AbstractAudioFilter> audioFilters)
|
||||||
{
|
{
|
||||||
super(aliasList, timeslot, maxAudioSegmentLength);
|
super(aliasList, timeslot, maxAudioSegmentLength);
|
||||||
mAudioFilterEnable = audioFilterEnable;
|
mAudioFilters = audioFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Audio Module.
|
* Creates an Audio Module.
|
||||||
* @param aliasList for aliasing identifiers
|
* @param aliasList for aliasing identifiers
|
||||||
* @param audioFilterEnable to enable or disable high-pass audio filter
|
* @param audioFilters a list of audio filters to apply to the incoming audio samples
|
||||||
*/
|
*/
|
||||||
public AudioModule(AliasList aliasList, boolean audioFilterEnable)
|
public AudioModule(AliasList aliasList, List<AbstractAudioFilter> audioFilters)
|
||||||
{
|
{
|
||||||
super(aliasList);
|
super(aliasList);
|
||||||
mAudioFilterEnable = audioFilterEnable;
|
mAudioFilters = audioFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -128,9 +101,13 @@ public class AudioModule extends AbstractAudioModule implements ISquelchStateLis
|
|||||||
{
|
{
|
||||||
if(mSquelchState == SquelchState.UNSQUELCH)
|
if(mSquelchState == SquelchState.UNSQUELCH)
|
||||||
{
|
{
|
||||||
if(mAudioFilterEnable)
|
// apply audio filters if any (i.e. deemphasis, high pass, etc.)
|
||||||
|
if(!mAudioFilters.isEmpty())
|
||||||
{
|
{
|
||||||
audioBuffer = mHighPassFilter.filter(audioBuffer);
|
for(AbstractAudioFilter filter : mAudioFilters)
|
||||||
|
{
|
||||||
|
audioBuffer = filter.filter(audioBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addAudio(audioBuffer);
|
addAudio(audioBuffer);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -61,7 +61,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*
|
*
|
||||||
* Producers will add audio buffers and update identifiers throughout the life-cycle of an audio segment. The producer
|
* Producers will add audio buffers and update identifiers throughout the life-cycle of an audio segment. The producer
|
||||||
* will signal the completion of an audio segment by setting the complete property to true. This allows consumers the
|
* will signal the completion of an audio segment by setting the complete property to true. This allows consumers the
|
||||||
* option to process the audio buffers throughout the life-cycle of the segment, or to process all of the buffers once
|
* option to process the audio buffers throughout the life-cycle of the segment, or to process all the buffers once
|
||||||
* the segment is complete.
|
* the segment is complete.
|
||||||
*/
|
*/
|
||||||
public class AudioSegment implements Listener<IdentifierUpdateNotification>
|
public class AudioSegment implements Listener<IdentifierUpdateNotification>
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package io.github.dsheirer.audio;
|
||||||
|
|
||||||
|
import io.github.dsheirer.dsp.filter.FilterFactory;
|
||||||
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
|
||||||
|
import io.github.dsheirer.dsp.filter.fir.real.IRealFilter;
|
||||||
|
import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class HighPassAudioFilter extends AbstractAudioFilter
|
||||||
|
{
|
||||||
|
private static final Logger mLog = LoggerFactory.getLogger(HighPassAudioFilter.class);
|
||||||
|
private static float[] sHighPassFilterCoefficients;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
|
||||||
|
.sampleRate(8000)
|
||||||
|
.stopBandCutoff(200)
|
||||||
|
.stopBandAmplitude(0.0)
|
||||||
|
.stopBandRipple(0.025)
|
||||||
|
.passBandStart(300)
|
||||||
|
.passBandAmplitude(1.0)
|
||||||
|
.passBandRipple(0.01)
|
||||||
|
.build();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
|
||||||
|
|
||||||
|
if(designer.isValid())
|
||||||
|
{
|
||||||
|
sHighPassFilterCoefficients = designer.getImpulseResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(FilterDesignException fde)
|
||||||
|
{
|
||||||
|
mLog.error("Filter design error", fde);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final IRealFilter mHighPassFilter = FilterFactory.getRealFilter(sHighPassFilterCoefficients);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float[] filter(float[] audio)
|
||||||
|
{
|
||||||
|
audio = mHighPassFilter.filter(audio);
|
||||||
|
return audio;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.audio;
|
package io.github.dsheirer.audio;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.playback.AudioOutput;
|
import io.github.dsheirer.audio.playback.AudioChannel;
|
||||||
|
import io.github.dsheirer.audio.playback.AudioPlaybackDeviceDescriptor;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,13 +30,13 @@ import java.util.List;
|
|||||||
public interface IAudioController
|
public interface IAudioController
|
||||||
{
|
{
|
||||||
/* Current Mixer and MixerChannel configuration */
|
/* Current Mixer and MixerChannel configuration */
|
||||||
public void setMixerChannelConfiguration( MixerChannelConfiguration entry ) throws AudioException;
|
public void setAudioPlaybackDevice(AudioPlaybackDeviceDescriptor device ) throws AudioException;
|
||||||
public MixerChannelConfiguration getMixerChannelConfiguration() throws AudioException;
|
public AudioPlaybackDeviceDescriptor getAudioPlaybackDevice() throws AudioException;
|
||||||
|
|
||||||
/* Audio Output(s) */
|
/* Audio Channel(s) */
|
||||||
public List<AudioOutput> getAudioOutputs();
|
public List<AudioChannel> getAudioChannels();
|
||||||
|
|
||||||
/* Controller Audio Event Listener */
|
/* Controller Audio Event Listener */
|
||||||
public void addControllerListener( Listener<AudioEvent> listener );
|
public void addAudioEventListener(Listener<AudioEvent> listener );
|
||||||
public void removeControllerListener( Listener<AudioEvent> listener );
|
public void removeAudioEventListener(Listener<AudioEvent> listener );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public abstract class AbstractAudioBroadcaster<T extends BroadcastConfiguration>
|
|||||||
protected ObjectProperty<BroadcastState> mBroadcastState = new SimpleObjectProperty<>(BroadcastState.READY);
|
protected ObjectProperty<BroadcastState> mBroadcastState = new SimpleObjectProperty<>(BroadcastState.READY);
|
||||||
protected ObjectProperty<BroadcastState> mLastBadBroadcastState = new SimpleObjectProperty<>();
|
protected ObjectProperty<BroadcastState> mLastBadBroadcastState = new SimpleObjectProperty<>();
|
||||||
protected int mStreamedAudioCount = 0;
|
protected int mStreamedAudioCount = 0;
|
||||||
|
protected int mDuplicateRejectedAudioCount = 0;
|
||||||
protected int mErrorAudioCount = 0;
|
protected int mErrorAudioCount = 0;
|
||||||
protected int mAgedOffAudioCount = 0;
|
protected int mAgedOffAudioCount = 0;
|
||||||
|
|
||||||
@@ -163,6 +164,22 @@ public abstract class AbstractAudioBroadcaster<T extends BroadcastConfiguration>
|
|||||||
mStreamedAudioCount++;
|
mStreamedAudioCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of audio recordings rejected by the remote service as duplicates.
|
||||||
|
*/
|
||||||
|
public int getDuplicateRejectedAudioCount()
|
||||||
|
{
|
||||||
|
return mDuplicateRejectedAudioCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the duplicate-rejected audio count by one.
|
||||||
|
*/
|
||||||
|
public void incrementDuplicateRejectedAudioCount()
|
||||||
|
{
|
||||||
|
mDuplicateRejectedAudioCount++;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of audio recordings that were removed for exceeding age limit
|
* Number of audio recordings that were removed for exceeding age limit
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ public class BroadcastEvent
|
|||||||
BROADCASTER_QUEUE_CHANGE,
|
BROADCASTER_QUEUE_CHANGE,
|
||||||
BROADCASTER_STATE_CHANGE,
|
BROADCASTER_STATE_CHANGE,
|
||||||
BROADCASTER_STREAMED_COUNT_CHANGE,
|
BROADCASTER_STREAMED_COUNT_CHANGE,
|
||||||
|
BROADCASTER_DUPLICATE_REJECTED_COUNT_CHANGE,
|
||||||
BROADCASTER_AGED_OFF_COUNT_CHANGE,
|
BROADCASTER_AGED_OFF_COUNT_CHANGE,
|
||||||
BROADCASTER_ERROR_COUNT_CHANGE,
|
BROADCASTER_ERROR_COUNT_CHANGE,
|
||||||
BROADCASTER_DELETE,
|
BROADCASTER_DELETE,
|
||||||
|
|||||||
@@ -62,11 +62,12 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
public static final int COLUMN_BROADCASTER_STATUS = 2;
|
public static final int COLUMN_BROADCASTER_STATUS = 2;
|
||||||
public static final int COLUMN_BROADCASTER_QUEUE_SIZE = 3;
|
public static final int COLUMN_BROADCASTER_QUEUE_SIZE = 3;
|
||||||
public static final int COLUMN_BROADCASTER_STREAMED_COUNT = 4;
|
public static final int COLUMN_BROADCASTER_STREAMED_COUNT = 4;
|
||||||
public static final int COLUMN_BROADCASTER_AGED_OFF_COUNT = 5;
|
public static final int COLUMN_BROADCASTER_DUPLICATE_REJECTED_COUNT = 5;
|
||||||
public static final int COLUMN_BROADCASTER_ERROR_COUNT = 6;
|
public static final int COLUMN_BROADCASTER_AGED_OFF_COUNT = 6;
|
||||||
|
public static final int COLUMN_BROADCASTER_ERROR_COUNT = 7;
|
||||||
|
|
||||||
public static final String[] COLUMN_NAMES = new String[]
|
public static final String[] COLUMN_NAMES = new String[]
|
||||||
{"Stream Type", "Name", "Status", "Queued", "Streamed/Uploaded", "Aged Off", "Upload Error"};
|
{"Stream Type", "Name", "Status", "Queued", "Streamed/Uploaded", "Duplicate Rejected", "Aged Off", "Upload Error"};
|
||||||
|
|
||||||
private ObservableList<ConfiguredBroadcast> mConfiguredBroadcasts =
|
private ObservableList<ConfiguredBroadcast> mConfiguredBroadcasts =
|
||||||
FXCollections.observableArrayList(ConfiguredBroadcast.extractor());
|
FXCollections.observableArrayList(ConfiguredBroadcast.extractor());
|
||||||
@@ -361,7 +362,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
}
|
}
|
||||||
|
|
||||||
broadcast(new BroadcastEvent(audioBroadcaster, BroadcastEvent.Event.BROADCASTER_ADD));
|
broadcast(new BroadcastEvent(audioBroadcaster, BroadcastEvent.Event.BROADCASTER_ADD));
|
||||||
ThreadPool.CACHED.submit(audioBroadcaster::start);
|
ThreadPool.CACHED.submit(() -> audioBroadcaster.start());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,6 +532,12 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
fireTableCellUpdated(row, COLUMN_BROADCASTER_STREAMED_COUNT);
|
fireTableCellUpdated(row, COLUMN_BROADCASTER_STREAMED_COUNT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case BROADCASTER_DUPLICATE_REJECTED_COUNT_CHANGE:
|
||||||
|
if(row >= 0)
|
||||||
|
{
|
||||||
|
fireTableCellUpdated(row, COLUMN_BROADCASTER_DUPLICATE_REJECTED_COUNT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case BROADCASTER_AGED_OFF_COUNT_CHANGE:
|
case BROADCASTER_AGED_OFF_COUNT_CHANGE:
|
||||||
if(row >= 0)
|
if(row >= 0)
|
||||||
{
|
{
|
||||||
@@ -607,6 +614,12 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
return configuredBroadcast.getAudioBroadcaster().getStreamedAudioCount();
|
return configuredBroadcast.getAudioBroadcaster().getStreamedAudioCount();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case COLUMN_BROADCASTER_DUPLICATE_REJECTED_COUNT:
|
||||||
|
if(configuredBroadcast.hasAudioBroadcaster())
|
||||||
|
{
|
||||||
|
return configuredBroadcast.getAudioBroadcaster().getDuplicateRejectedAudioCount();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case COLUMN_BROADCASTER_AGED_OFF_COUNT:
|
case COLUMN_BROADCASTER_AGED_OFF_COUNT:
|
||||||
if(configuredBroadcast.hasAudioBroadcaster())
|
if(configuredBroadcast.hasAudioBroadcaster())
|
||||||
{
|
{
|
||||||
@@ -643,6 +656,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
case COLUMN_BROADCASTER_AGED_OFF_COUNT:
|
case COLUMN_BROADCASTER_AGED_OFF_COUNT:
|
||||||
case COLUMN_BROADCASTER_QUEUE_SIZE:
|
case COLUMN_BROADCASTER_QUEUE_SIZE:
|
||||||
case COLUMN_BROADCASTER_STREAMED_COUNT:
|
case COLUMN_BROADCASTER_STREAMED_COUNT:
|
||||||
|
case COLUMN_BROADCASTER_DUPLICATE_REJECTED_COUNT:
|
||||||
case COLUMN_BROADCASTER_ERROR_COUNT:
|
case COLUMN_BROADCASTER_ERROR_COUNT:
|
||||||
return Integer.class;
|
return Integer.class;
|
||||||
case COLUMN_BROADCAST_SERVER_TYPE:
|
case COLUMN_BROADCAST_SERVER_TYPE:
|
||||||
|
|||||||
@@ -151,7 +151,10 @@ public class BroadcastStatusPanel extends JPanel
|
|||||||
else if(state == BroadcastState.DISABLED)
|
else if(state == BroadcastState.DISABLED)
|
||||||
{
|
{
|
||||||
setBackground(table.getBackground());
|
setBackground(table.getBackground());
|
||||||
setForeground(Color.LIGHT_GRAY);
|
//Use the LAF's disabled-foreground so the cell reads correctly on any
|
||||||
|
//theme - LIGHT_GRAY is invisible on a light background.
|
||||||
|
Color disabled = javax.swing.UIManager.getColor("Label.disabledForeground");
|
||||||
|
setForeground(disabled != null ? disabled : table.getForeground());
|
||||||
}
|
}
|
||||||
else if(state == BroadcastState.INVALID_SETTINGS ||
|
else if(state == BroadcastState.INVALID_SETTINGS ||
|
||||||
state == BroadcastState.NETWORK_UNAVAILABLE)
|
state == BroadcastState.NETWORK_UNAVAILABLE)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import io.github.dsheirer.identifier.Form;
|
|||||||
import io.github.dsheirer.identifier.Identifier;
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
import io.github.dsheirer.identifier.IdentifierClass;
|
import io.github.dsheirer.identifier.IdentifierClass;
|
||||||
import io.github.dsheirer.identifier.Role;
|
import io.github.dsheirer.identifier.Role;
|
||||||
|
import io.github.dsheirer.identifier.alias.TalkerAliasIdentifier;
|
||||||
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
||||||
import io.github.dsheirer.identifier.configuration.ConfigurationLongIdentifier;
|
import io.github.dsheirer.identifier.configuration.ConfigurationLongIdentifier;
|
||||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||||
@@ -253,6 +254,8 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
String radioId = getFrom(audioRecording);
|
String radioId = getFrom(audioRecording);
|
||||||
float frequency = getFrequency(audioRecording);
|
float frequency = getFrequency(audioRecording);
|
||||||
|
|
||||||
|
String radioIdAlias = getFromAlias(audioRecording);
|
||||||
|
|
||||||
BroadcastifyCallBuilder bodyBuilder = new BroadcastifyCallBuilder();
|
BroadcastifyCallBuilder bodyBuilder = new BroadcastifyCallBuilder();
|
||||||
bodyBuilder.addPart(FormField.API_KEY, getBroadcastConfiguration().getApiKey())
|
bodyBuilder.addPart(FormField.API_KEY, getBroadcastConfiguration().getApiKey())
|
||||||
.addPart(FormField.SYSTEM_ID, getBroadcastConfiguration().getSystemID())
|
.addPart(FormField.SYSTEM_ID, getBroadcastConfiguration().getSystemID())
|
||||||
@@ -263,6 +266,11 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
.addPart(FormField.FREQUENCY, frequency)
|
.addPart(FormField.FREQUENCY, frequency)
|
||||||
.addPart(FormField.ENCODING, ENCODING_TYPE_MP3);
|
.addPart(FormField.ENCODING, ENCODING_TYPE_MP3);
|
||||||
|
|
||||||
|
if(radioIdAlias != null && !radioIdAlias.isEmpty())
|
||||||
|
{
|
||||||
|
bodyBuilder.addPart(FormField.RADIO_ID_ALIAS, radioIdAlias);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
@@ -362,6 +370,9 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
else if(urlResponse.startsWith("1 SKIPPED"))
|
else if(urlResponse.startsWith("1 SKIPPED"))
|
||||||
{
|
{
|
||||||
//Broadcastify is telling us to skip audio upload - someone already uploaded it
|
//Broadcastify is telling us to skip audio upload - someone already uploaded it
|
||||||
|
incrementDuplicateRejectedAudioCount();
|
||||||
|
broadcast(new BroadcastEvent(BroadcastifyCallBroadcaster.this,
|
||||||
|
BroadcastEvent.Event.BROADCASTER_DUPLICATE_REJECTED_COUNT_CHANGE));
|
||||||
audioRecording.removePendingReplay();
|
audioRecording.removePendingReplay();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -446,6 +457,27 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the over-the-air talker alias for the FROM (source radio) identifier, acquired in real-time from RF
|
||||||
|
* (e.g. P25 Motorola Talker Alias or DMR Talker Alias). Returns null if no OTA alias was received for this call.
|
||||||
|
* This is sent as the srcId_alias field in Broadcastify uploads.
|
||||||
|
*/
|
||||||
|
private static String getFromAlias(AudioRecording audioRecording)
|
||||||
|
{
|
||||||
|
for(Identifier identifier: audioRecording.getIdentifierCollection().getIdentifiers(Role.FROM))
|
||||||
|
{
|
||||||
|
if(identifier instanceof TalkerAliasIdentifier talkerAliasIdentifier)
|
||||||
|
{
|
||||||
|
if(talkerAliasIdentifier.isValid())
|
||||||
|
{
|
||||||
|
return talkerAliasIdentifier.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a formatted string with the TO identifiers or uses a default of zero (0)
|
* Creates a formatted string with the TO identifiers or uses a default of zero (0)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public enum FormField
|
|||||||
TIMESTAMP("ts"),
|
TIMESTAMP("ts"),
|
||||||
TALKGROUP_ID("tg"),
|
TALKGROUP_ID("tg"),
|
||||||
RADIO_ID("src"),
|
RADIO_ID("src"),
|
||||||
|
RADIO_ID_ALIAS("srcId_alias"),
|
||||||
FREQUENCY("freq"),
|
FREQUENCY("freq"),
|
||||||
ENCODING("enc"),
|
ENCODING("enc"),
|
||||||
TEST("test");
|
TEST("test");
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
private static final long CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS = 5000; // 5 seconds
|
private static final long CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS = 5000; // 5 seconds
|
||||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||||
private static final String HTTP_1_0_OK_HEX_DUMP = "48 54 54 50 2F 31 2E 30 20 32 30 30 20 4F 4B";
|
private static final String HTTP_1_0_OK_HEX_DUMP = "48 54 54 50 2F 31 2E 30 20 32 30 30 20 4F 4B";
|
||||||
|
private static final String HTTP_1_1_CONTINUE_HEX_DUMP = "48 54 54 50 2F 31 2E 31 20 31 30 30";
|
||||||
|
|
||||||
private NioSocketConnector mSocketConnector;
|
private NioSocketConnector mSocketConnector;
|
||||||
private IoSession mStreamingSession = null;
|
private IoSession mStreamingSession = null;
|
||||||
@@ -262,6 +263,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
{
|
{
|
||||||
mHTTPHeaders = new HashMap<>();
|
mHTTPHeaders = new HashMap<>();
|
||||||
mHTTPHeaders.put(IcecastHeader.ACCEPT.getValue(), "*/*");
|
mHTTPHeaders.put(IcecastHeader.ACCEPT.getValue(), "*/*");
|
||||||
|
mHTTPHeaders.put(IcecastHeader.EXPECT.getValue(), "100-continue");
|
||||||
mHTTPHeaders.put(IcecastHeader.CONTENT_TYPE.getValue(), getConfiguration().getBroadcastFormat().getValue());
|
mHTTPHeaders.put(IcecastHeader.CONTENT_TYPE.getValue(), getConfiguration().getBroadcastFormat().getValue());
|
||||||
mHTTPHeaders.put(IcecastHeader.USER_AGENT.getValue(), SystemProperties.getInstance().getApplicationName());
|
mHTTPHeaders.put(IcecastHeader.USER_AGENT.getValue(), SystemProperties.getInstance().getApplicationName());
|
||||||
mHTTPHeaders.put(IcecastHeader.AUTHORIZATION.getValue(), getConfiguration().getBase64EncodedCredentials());
|
mHTTPHeaders.put(IcecastHeader.AUTHORIZATION.getValue(), getConfiguration().getBase64EncodedCredentials());
|
||||||
@@ -350,7 +352,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
{
|
{
|
||||||
String hexDump = ((ProtocolDecoderException)throwable).getHexdump();
|
String hexDump = ((ProtocolDecoderException)throwable).getHexdump();
|
||||||
|
|
||||||
if(hexDump.startsWith(HTTP_1_0_OK_HEX_DUMP))
|
if(hexDump.startsWith(HTTP_1_0_OK_HEX_DUMP) || hexDump.startsWith(HTTP_1_1_CONTINUE_HEX_DUMP))
|
||||||
{
|
{
|
||||||
setBroadcastState(BroadcastState.CONNECTED);
|
setBroadcastState(BroadcastState.CONNECTED);
|
||||||
mConnectionFailureLogged.set(false);
|
mConnectionFailureLogged.set(false);
|
||||||
@@ -432,6 +434,10 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
switch(response.getStatus())
|
switch(response.getStatus())
|
||||||
{
|
{
|
||||||
case INFORMATIONAL_CONTINUE:
|
case INFORMATIONAL_CONTINUE:
|
||||||
|
//Icecast 2.5+ signals that we can start sending audio with 100-continue
|
||||||
|
setBroadcastState(BroadcastState.CONNECTED);
|
||||||
|
mConnecting.set(false);
|
||||||
|
mConnectionFailureLogged.set(false);
|
||||||
break;
|
break;
|
||||||
case SUCCESS_OK:
|
case SUCCESS_OK:
|
||||||
setBroadcastState(BroadcastState.CONNECTED);
|
setBroadcastState(BroadcastState.CONNECTED);
|
||||||
@@ -500,7 +506,8 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
|
|
||||||
mMessage = new String(bytes);
|
mMessage = new String(bytes);
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("HTTP/1.0 (\\d{3})");
|
//Icecast 2.4+ responds with HTTP/1.0 and Icecast 2.5+ responds with HTTP/1.1
|
||||||
|
Pattern pattern = Pattern.compile("HTTP/1\\.[01] (\\d{3})");
|
||||||
Matcher m = pattern.matcher(mMessage);
|
Matcher m = pattern.matcher(mMessage);
|
||||||
|
|
||||||
if(m.find())
|
if(m.find())
|
||||||
|
|||||||
@@ -17,13 +17,14 @@
|
|||||||
* ****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.gui.playlist.streaming;
|
package io.github.dsheirer.audio.broadcast.openmhz;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||||
import io.github.dsheirer.audio.broadcast.openmhz.OpenMHzBroadcaster;
|
import io.github.dsheirer.audio.broadcast.openmhz.OpenMHzBroadcaster;
|
||||||
import io.github.dsheirer.audio.broadcast.openmhz.OpenMHzConfiguration;
|
import io.github.dsheirer.audio.broadcast.openmhz.OpenMHzConfiguration;
|
||||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.gui.playlist.streaming.AbstractBroadcastEditor;
|
||||||
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
|
|||||||
@@ -35,9 +35,12 @@ import java.net.URL;
|
|||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jmbe.iface.IAudioCodec;
|
import jmbe.iface.IAudioCodec;
|
||||||
import jmbe.iface.IAudioCodecLibrary;
|
import jmbe.iface.IAudioCodecLibrary;
|
||||||
|
import jmbe.iface.IAudioCodecLibraryV2;
|
||||||
|
import jmbe.iface.IAudioCodecV2;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
public abstract class JmbeAudioModule extends AbstractAudioModule implements Listener<IMessage>, IMessageListener,
|
public abstract class JmbeAudioModule extends AbstractAudioModule implements Listener<IMessage>, IMessageListener,
|
||||||
ISquelchStateListener
|
ISquelchStateListener
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(JmbeAudioModule.class);
|
private static final Logger LOG = LoggerFactory.getLogger(JmbeAudioModule.class);
|
||||||
private static final String JMBE_AUDIO_LIBRARY = "JMBE";
|
private static final String JMBE_AUDIO_LIBRARY = "JMBE";
|
||||||
private static final List<String> mLibraryLoadStatusLogged = new ArrayList<>();
|
private static final List<String> mLibraryLoadStatusLogged = new ArrayList<>();
|
||||||
private IAudioCodec mAudioCodec;
|
private IAudioCodec mAudioCodec;
|
||||||
@@ -56,12 +59,43 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
|
|
||||||
public JmbeAudioModule(UserPreferences userPreferences, AliasList aliasList, int timeslot)
|
public JmbeAudioModule(UserPreferences userPreferences, AliasList aliasList, int timeslot)
|
||||||
{
|
{
|
||||||
super(aliasList, timeslot, DEFAULT_SEGMENT_AUDIO_SAMPLE_LENGTH);
|
super(aliasList, timeslot, DEFAULT_MAX_SEGMENT_LENGTH_MILLIS);
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
MyEventBus.getGlobalEventBus().register(this);
|
MyEventBus.getGlobalEventBus().register(this);
|
||||||
loadConverter();
|
loadConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of features supported by the JMBE audio library. Note: features are only supported in Version 2.0+
|
||||||
|
* @return list of features or an empty list if the current library version doesn't support features.
|
||||||
|
*/
|
||||||
|
public List<String> getFeatures()
|
||||||
|
{
|
||||||
|
if(mAudioCodec instanceof IAudioCodecV2 v2)
|
||||||
|
{
|
||||||
|
return v2.getFeatures();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the JMBE feature
|
||||||
|
* @param name of the feature
|
||||||
|
* @param value for the feature
|
||||||
|
*/
|
||||||
|
public void setFeature(String name, Object value)
|
||||||
|
{
|
||||||
|
if(mAudioCodec instanceof IAudioCodecV2 v2)
|
||||||
|
{
|
||||||
|
v2.setFeature(name, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.info("Feature [" + name + "] is not supported by the current JMBE audio codec library version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void closeAudioSegment()
|
protected void closeAudioSegment()
|
||||||
{
|
{
|
||||||
@@ -135,7 +169,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.info("Loading JMBE library from [" + path + "]");
|
LOG.info("Loading JMBE library from [" + path + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -143,13 +177,32 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
|
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
|
||||||
this.getClass().getClassLoader());
|
this.getClass().getClassLoader());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sLoadedJmbeAudioConverterClass = Class.forName("jmbe.JMBEAudioLibraryV2", true, childClassLoader);
|
||||||
|
}
|
||||||
|
catch(ClassNotFoundException legacyLibrary)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
sLoadedJmbeAudioConverterClass = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
|
sLoadedJmbeAudioConverterClass = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
|
||||||
}
|
}
|
||||||
|
catch(ClassNotFoundException missingLibrary)
|
||||||
|
{
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
|
{
|
||||||
|
LOG.error("Couldn't load JMBE audio conversion library from [" + path +
|
||||||
|
"] - neither V2 nor V1 library class was found");
|
||||||
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch(IllegalArgumentException iae)
|
catch(IllegalArgumentException iae)
|
||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
|
LOG.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,18 +210,11 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
|
LOG.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(ClassNotFoundException e1)
|
|
||||||
{
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - class not found");
|
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,11 +229,23 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
if((library.getMajorVersion() == 1 && library.getMinorVersion() >= 0 &&
|
if((library.getMajorVersion() == 1 && library.getMinorVersion() >= 0 &&
|
||||||
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
|
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
|
||||||
{
|
{
|
||||||
audioConverter = library.getAudioConverter(getCodecName());
|
audioConverter = library instanceof IAudioCodecLibraryV2 libraryV2 ?
|
||||||
|
libraryV2.getAudioConverterV2(getCodecName()) :
|
||||||
|
library.getAudioConverter(getCodecName());
|
||||||
|
|
||||||
|
String codecStatusKey = JMBE_AUDIO_LIBRARY + ":codec:" + getCodecName();
|
||||||
|
if(!mLibraryLoadStatusLogged.contains(codecStatusKey))
|
||||||
|
{
|
||||||
|
LOG.info("JMBE codec [" + getCodecName() + "] class [" +
|
||||||
|
audioConverter.getClass().getName() + "] features [" +
|
||||||
|
(audioConverter instanceof IAudioCodecV2 v2 ?
|
||||||
|
v2.getFeatures() : Collections.emptyList()) + "]");
|
||||||
|
mLibraryLoadStatusLogged.add(codecStatusKey);
|
||||||
|
}
|
||||||
|
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.info("JMBE audio conversion library loaded: " + library.getVersion());
|
LOG.info("JMBE audio conversion library loaded: " + library.getVersion());
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +253,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.warn("JMBE library version 1.0.0 or higher is required - found: " + library.getVersion());
|
LOG.warn("JMBE library version 1.0.0 or higher is required - found: " + library.getVersion());
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +262,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.info("JMBE audio conversion library NOT FOUND");
|
LOG.info("JMBE audio conversion library NOT FOUND");
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,7 +271,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - invocation target exception", ite);
|
LOG.error("Couldn't load JMBE audio conversion library - invocation target exception", ite);
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +279,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - instantiation exception", e1);
|
LOG.error("Couldn't load JMBE audio conversion library - instantiation exception", e1);
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +287,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - security restrictions");
|
LOG.error("Couldn't load JMBE audio conversion library - security restrictions");
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +295,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.error("Couldn't load JMBE audio conversion library - no such method exception");
|
LOG.error("Couldn't load JMBE audio conversion library - no such method exception");
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +304,7 @@ public abstract class JmbeAudioModule extends AbstractAudioModule implements Lis
|
|||||||
{
|
{
|
||||||
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
|
||||||
{
|
{
|
||||||
mLog.warn("JMBE audio library path is NOT SET in your User Preferences.");
|
LOG.warn("JMBE audio library path is NOT SET in your User Preferences.");
|
||||||
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,6 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
|||||||
import com.fasterxml.jackson.annotation.JsonRootName;
|
import com.fasterxml.jackson.annotation.JsonRootName;
|
||||||
import io.github.dsheirer.identifier.Identifier;
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
import io.github.dsheirer.identifier.encryption.EncryptionKey;
|
import io.github.dsheirer.identifier.encryption.EncryptionKey;
|
||||||
import io.github.dsheirer.module.decode.p25.audio.VoiceFrame;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -288,10 +287,18 @@ public class MBECallSequence
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mVoiceFrames.add(new VoiceFrame(timestamp, frame));
|
add(new VoiceFrame(timestamp, frame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the voice frame to the sequence
|
||||||
|
*/
|
||||||
|
public void add(VoiceFrame voiceFrame)
|
||||||
|
{
|
||||||
|
mVoiceFrames.add(voiceFrame);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an encrypted audio frame to this call sequence
|
* Adds an encrypted audio frame to this call sequence
|
||||||
*
|
*
|
||||||
@@ -317,6 +324,6 @@ public class MBECallSequence
|
|||||||
*/
|
*/
|
||||||
public void addEncryptedVoiceFrame(long timestamp, String frame, int algorithm, int keyid, String messageIndicator)
|
public void addEncryptedVoiceFrame(long timestamp, String frame, int algorithm, int keyid, String messageIndicator)
|
||||||
{
|
{
|
||||||
mVoiceFrames.add(new VoiceFrame(timestamp, frame, algorithm, keyid, messageIndicator));
|
add(new VoiceFrame(timestamp, frame, algorithm, keyid, messageIndicator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -25,7 +25,6 @@ import io.github.dsheirer.audio.AudioSegment;
|
|||||||
import io.github.dsheirer.identifier.IdentifierUpdateNotification;
|
import io.github.dsheirer.identifier.IdentifierUpdateNotification;
|
||||||
import io.github.dsheirer.module.decode.p25.audio.P25P1AudioModule;
|
import io.github.dsheirer.module.decode.p25.audio.P25P1AudioModule;
|
||||||
import io.github.dsheirer.module.decode.p25.audio.P25P1CallSequenceRecorder;
|
import io.github.dsheirer.module.decode.p25.audio.P25P1CallSequenceRecorder;
|
||||||
import io.github.dsheirer.module.decode.p25.audio.VoiceFrame;
|
|
||||||
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
import io.github.dsheirer.module.decode.p25.identifier.radio.APCO25RadioIdentifier;
|
||||||
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
import io.github.dsheirer.module.decode.p25.identifier.talkgroup.APCO25Talkgroup;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* * ******************************************************************************
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
* it under the terms of the GNU General Public License as published by
|
||||||
* *
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
* (at your option) any later version.
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.audio.codec.mbe;
|
package io.github.dsheirer.audio.codec.mbe;
|
||||||
@@ -25,7 +22,6 @@ package io.github.dsheirer.audio.codec.mbe;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import io.github.dsheirer.module.decode.p25.audio.VoiceFrame;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdr-trunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
* Copyright (C) 2014-2026 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
* it under the terms of the GNU General Public License as published by
|
||||||
* later version.
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
* This program is distributed in the hope that it will be useful,
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
* You should have received a copy of the GNU General Public License
|
||||||
* If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
|
|
||||||
package io.github.dsheirer.module.decode.p25.audio;
|
package io.github.dsheirer.audio.codec.mbe;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
@@ -27,7 +30,7 @@ import com.fasterxml.jackson.annotation.JsonRootName;
|
|||||||
*/
|
*/
|
||||||
@JsonRootName(value = "frame")
|
@JsonRootName(value = "frame")
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
@JsonPropertyOrder({"encryption_algorithm", "encryption_key_id", "encryption_mi", "time", "hex"})
|
@JsonPropertyOrder({"tag", "encryption_algorithm", "encryption_key_id", "encryption_mi", "time", "hex"})
|
||||||
public class VoiceFrame
|
public class VoiceFrame
|
||||||
{
|
{
|
||||||
private long mTimestamp;
|
private long mTimestamp;
|
||||||
@@ -35,6 +38,7 @@ public class VoiceFrame
|
|||||||
private Integer mAlgorithm;
|
private Integer mAlgorithm;
|
||||||
private Integer mKeyId;
|
private Integer mKeyId;
|
||||||
private String mMessageIndicator;
|
private String mMessageIndicator;
|
||||||
|
private String mTag;
|
||||||
|
|
||||||
public VoiceFrame()
|
public VoiceFrame()
|
||||||
{
|
{
|
||||||
@@ -70,6 +74,24 @@ public class VoiceFrame
|
|||||||
mMessageIndicator = messageIndicator;
|
mMessageIndicator = messageIndicator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag value for the voice frame
|
||||||
|
*/
|
||||||
|
@JsonProperty("tag")
|
||||||
|
public String getTag()
|
||||||
|
{
|
||||||
|
return mTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional tag value for the frame
|
||||||
|
* @param tag to set
|
||||||
|
*/
|
||||||
|
public void setTag(String tag)
|
||||||
|
{
|
||||||
|
mTag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp the frame was transmitted
|
* Timestamp the frame was transmitted
|
||||||
*
|
*
|
||||||
@@ -1,483 +0,0 @@
|
|||||||
/*
|
|
||||||
* *****************************************************************************
|
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* ****************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv;
|
|
||||||
|
|
||||||
import com.fazecast.jSerialComm.SerialPort;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.AmbeMessage;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.AmbeMessageFactory;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.VocoderRate;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.AmbeRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.DecodeSpeechRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.EncodeSpeechRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.ResetRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.SetVocoderParametersRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.request.SetVocoderRequest;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.DecodeSpeechResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.ReadyResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetVocoderParameterResponse;
|
|
||||||
import io.github.dsheirer.sample.Listener;
|
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.LinkedTransferQueue;
|
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Northwest Digital Radio (NWDR) ThumbDv dongle.
|
|
||||||
*
|
|
||||||
* Note: linux users must allow access to the serial port:
|
|
||||||
*
|
|
||||||
* sudo usermod -a -G uucp username
|
|
||||||
* sudo usermod -a -G dialout username
|
|
||||||
* sudo usermod -a -G lock username
|
|
||||||
* sudo usermod -a -G tty username
|
|
||||||
*/
|
|
||||||
public class ThumbDv implements AutoCloseable
|
|
||||||
{
|
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(ThumbDv.class);
|
|
||||||
private static final String PORT_DESCRIPTION = "USB-to-Serial Port (ftdi_sio)";
|
|
||||||
private static final String PORT_DESCRIPTION_FRAGMENT = "USB Serial Port";
|
|
||||||
private static final int BAUD_RATE = 460800;
|
|
||||||
private static final byte PACKET_START = (byte) 0x61;
|
|
||||||
|
|
||||||
public enum AudioProtocol
|
|
||||||
{
|
|
||||||
DMR,
|
|
||||||
DSTAR,
|
|
||||||
NXDN,
|
|
||||||
P25_PHASE2,
|
|
||||||
}
|
|
||||||
|
|
||||||
private SerialPort mSerialPort;
|
|
||||||
private ScheduledFuture mSerialPortReaderHandle;
|
|
||||||
private ScheduledFuture mAudioDecodeProcessorHandle;
|
|
||||||
private LinkedTransferQueue<DecodeSpeechRequest> mDecodeSpeechRequests = new LinkedTransferQueue<>();
|
|
||||||
private AudioProtocol mAudioProtocol;
|
|
||||||
private Listener<float[]> mAudioBufferListener;
|
|
||||||
private boolean mStarted;
|
|
||||||
|
|
||||||
public ThumbDv(AudioProtocol audioProtocol, Listener<float[]> listener)
|
|
||||||
{
|
|
||||||
mAudioProtocol = audioProtocol;
|
|
||||||
mAudioBufferListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueues the audio code frame for decoding. Decoded PCM speech packet will be sent to the registered
|
|
||||||
* audio packet listener.
|
|
||||||
*
|
|
||||||
* @param codecFrame
|
|
||||||
*/
|
|
||||||
public void decode(byte[] codecFrame)
|
|
||||||
{
|
|
||||||
if(!mStarted || mSerialPort == null)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Must invoke start() method and thumbdv serial device must be available");
|
|
||||||
}
|
|
||||||
|
|
||||||
mDecodeSpeechRequests.offer(new DecodeSpeechRequest(codecFrame));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
if(mSerialPortReaderHandle != null)
|
|
||||||
{
|
|
||||||
mSerialPortReaderHandle.cancel(true);
|
|
||||||
mSerialPortReaderHandle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mSerialPort != null)
|
|
||||||
{
|
|
||||||
mSerialPort.closePort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws IOException
|
|
||||||
{
|
|
||||||
if(mSerialPort == null)
|
|
||||||
{
|
|
||||||
SerialPort[] ports = SerialPort.getCommPorts();
|
|
||||||
|
|
||||||
for(SerialPort port : ports)
|
|
||||||
{
|
|
||||||
mLog.debug("Serial Port Name:" + port.getDescriptivePortName());
|
|
||||||
if(port.getDescriptivePortName().contentEquals(PORT_DESCRIPTION) ||
|
|
||||||
port.getDescriptivePortName().contains(PORT_DESCRIPTION_FRAGMENT))
|
|
||||||
{
|
|
||||||
mSerialPort = port;
|
|
||||||
mSerialPort.setBaudRate(BAUD_RATE);
|
|
||||||
mSerialPort.openPort(0, 5000, 10000);
|
|
||||||
|
|
||||||
if(mSerialPort.isOpen())
|
|
||||||
{
|
|
||||||
mLog.info("Resetting ThumbDv Device");
|
|
||||||
send(new ResetRequest());
|
|
||||||
|
|
||||||
mLog.info("Creating Serial Port Reader");
|
|
||||||
final Runnable r = new SerialPortReader(mSerialPort.getInputStream());
|
|
||||||
mLog.info("Starting Serial Port Reader");
|
|
||||||
mSerialPortReaderHandle = ThreadPool.SCHEDULED.scheduleAtFixedRate(r, 0,
|
|
||||||
5, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
mStarted = true;
|
|
||||||
mLog.info("Startup complete - awaiting reset response");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.warn("Could not open serial port: " + mSerialPort.getSystemPortName());
|
|
||||||
throw new IOException("Could not open serial port:" + mSerialPort.getSystemPortName());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mSerialPort == null)
|
|
||||||
{
|
|
||||||
throw new IOException("ThumbDV serial port not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send(byte[] message) throws IOException
|
|
||||||
{
|
|
||||||
if(mSerialPort == null)
|
|
||||||
{
|
|
||||||
throw new IOException("ThumbDv must be started before use");
|
|
||||||
}
|
|
||||||
|
|
||||||
int bytesWritten = mSerialPort.writeBytes(message, message.length);
|
|
||||||
|
|
||||||
if(bytesWritten < 0)
|
|
||||||
{
|
|
||||||
throw new IOException("Unable to write message:" + Arrays.toString(message));
|
|
||||||
}
|
|
||||||
else if(bytesWritten != message.length)
|
|
||||||
{
|
|
||||||
throw new IOException("Unable to write message:" + Arrays.toString(message) + " Bytes Written:" + bytesWritten);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the AMBE request message
|
|
||||||
*
|
|
||||||
* @param request message
|
|
||||||
* @throws IOException if there is an error
|
|
||||||
*/
|
|
||||||
public void send(AmbeRequest request) throws IOException
|
|
||||||
{
|
|
||||||
send(request.getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void receive(byte[] bytes)
|
|
||||||
{
|
|
||||||
AmbeMessage message = AmbeMessageFactory.getMessage(bytes);
|
|
||||||
|
|
||||||
if(message instanceof DecodeSpeechResponse && mAudioBufferListener != null)
|
|
||||||
{
|
|
||||||
float[] samples = ((DecodeSpeechResponse)message).getSamples();
|
|
||||||
mAudioBufferListener.receive(samples);
|
|
||||||
}
|
|
||||||
else if(message instanceof ReadyResponse && mAudioDecodeProcessorHandle == null)
|
|
||||||
{
|
|
||||||
if(mAudioDecodeProcessorHandle == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch(mAudioProtocol)
|
|
||||||
{
|
|
||||||
case DSTAR:
|
|
||||||
send(new SetVocoderRequest(VocoderRate.RATE_33));
|
|
||||||
send(new SetVocoderParametersRequest(0x0130, 0x0763, 0x4000, 0x0000, 0x0000, 0x0048));
|
|
||||||
break;
|
|
||||||
case DMR:
|
|
||||||
case NXDN:
|
|
||||||
case P25_PHASE2:
|
|
||||||
send(new SetVocoderRequest(VocoderRate.RATE_33));
|
|
||||||
send(new SetVocoderParametersRequest(0x0431, 0x0754, 0x2400, 0x0000, 0x0000, 0x6F48));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Unrecognized audio protocol:" + mAudioProtocol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(IOException ioe)
|
|
||||||
{
|
|
||||||
mLog.error("Error setting audio protocol vocoder parameters");
|
|
||||||
}
|
|
||||||
|
|
||||||
mLog.info("ThumbDv Reset Complete");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.info("ThumbDv Reset Detected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(message instanceof SetVocoderParameterResponse)
|
|
||||||
{
|
|
||||||
if(((SetVocoderParameterResponse)message).isSuccessful())
|
|
||||||
{
|
|
||||||
mLog.info("Audio vocoder parameters configured for " + mAudioProtocol);
|
|
||||||
//Start the audio frame decode processor
|
|
||||||
mAudioDecodeProcessorHandle = ThreadPool.SCHEDULED.scheduleAtFixedRate(new AudioDecodeProcessor(), 0,
|
|
||||||
10, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(message != null)
|
|
||||||
{
|
|
||||||
mLog.debug("RECEIVED:" + message.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs the current settings of the serial port. Note: you must invoke start() before this method so that
|
|
||||||
* the serial port can be discovered and opened.
|
|
||||||
*/
|
|
||||||
public void logSerialPort()
|
|
||||||
{
|
|
||||||
if(mSerialPort != null)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("\nPort:\t\t\t").append(mSerialPort.getSystemPortName()).append("\n");
|
|
||||||
sb.append("Name:\t\t\t").append(mSerialPort.getDescriptivePortName()).append("\n");
|
|
||||||
sb.append("Baud Rate:\t\t").append(mSerialPort.getBaudRate()).append("\n");
|
|
||||||
sb.append("Data Bits:\t\t").append(mSerialPort.getNumDataBits()).append("\n");
|
|
||||||
sb.append("Parity Bits:\t").append(mSerialPort.getParity()).append("\n");
|
|
||||||
sb.append("Stop Bits:\t\t").append(mSerialPort.getNumStopBits()).append("\n");
|
|
||||||
sb.append("Flow Control:\t").append(mSerialPort.getFlowControlSettings()).append("\n");
|
|
||||||
sb.append("Is Open:\t\t").append(mSerialPort.isOpen()).append("\n");
|
|
||||||
|
|
||||||
mLog.info(sb.toString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.info("No serial port found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the audio frame decode queue
|
|
||||||
*/
|
|
||||||
public class AudioDecodeProcessor implements Runnable
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DecodeSpeechRequest request = mDecodeSpeechRequests.poll();
|
|
||||||
|
|
||||||
if(request != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
send(request);
|
|
||||||
}
|
|
||||||
catch(IOException ioe)
|
|
||||||
{
|
|
||||||
mLog.error("Error decoding audio frame", ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// //Force a 20ms sleep after submitting an audio frame to avoid overflowing the thumbdv
|
|
||||||
// Thread.sleep(20);
|
|
||||||
// }
|
|
||||||
// catch(InterruptedException ie)
|
|
||||||
// {
|
|
||||||
// //Do nothing
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Throwable t)
|
|
||||||
{
|
|
||||||
mLog.error("Error", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SerialPortReader implements Runnable
|
|
||||||
{
|
|
||||||
private InputStream mInputStream;
|
|
||||||
|
|
||||||
public SerialPortReader(InputStream inputStream)
|
|
||||||
{
|
|
||||||
mInputStream = inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(mInputStream != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while(mInputStream.available() > 0)
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[400];
|
|
||||||
|
|
||||||
int bytesRead = mInputStream.readNBytes(buffer, 0, 1);
|
|
||||||
|
|
||||||
if(bytesRead == 1 && buffer[0] == PACKET_START)
|
|
||||||
{
|
|
||||||
while(mInputStream.available() < 2)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(1);
|
|
||||||
}
|
|
||||||
catch(InterruptedException ie)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesRead = mInputStream.readNBytes(buffer, 1, 2);
|
|
||||||
|
|
||||||
if(bytesRead == 2)
|
|
||||||
{
|
|
||||||
int length = (0xFF & buffer[1]) << 8;
|
|
||||||
length += (0xFF & buffer[2]);
|
|
||||||
|
|
||||||
if(0 < length && length < 400)
|
|
||||||
{
|
|
||||||
length++; //Add a byte for the type byte
|
|
||||||
|
|
||||||
while(mInputStream.available() < length)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(1);
|
|
||||||
}
|
|
||||||
catch(InterruptedException ie)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesRead = mInputStream.readNBytes(buffer, 3, length);
|
|
||||||
|
|
||||||
if(bytesRead == length)
|
|
||||||
{
|
|
||||||
receive(Arrays.copyOf(buffer, length + 3));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.debug("Expected [" + length + "] but received [" + bytesRead + "] bytes - " + Arrays.toString(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.error("Received packet with unexpected length: " + length);
|
|
||||||
//Don't process the buffer ... let the reader read and inspect 1 byte at a time
|
|
||||||
//to regain sync on the packet start byte
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.debug("Expected [2] but received [" + bytesRead + "] -- this shouldn't happen");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mLog.debug("Unrecognized byte: " + Arrays.toString(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(IOException ioe)
|
|
||||||
{
|
|
||||||
mLog.error("Error while reading ThumbDv serial port", ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Throwable t)
|
|
||||||
{
|
|
||||||
mLog.error("Error", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
mLog.debug("Starting");
|
|
||||||
|
|
||||||
String silence = "BEDDEA821EFD660C08";
|
|
||||||
|
|
||||||
String[] frames = {"0E46122323067C60F8", "0E469433C1067CF1BC", "0E46122B23067C60F8", "0E67162BE08874E2B4",
|
|
||||||
"0E46163BE1067CF1BC", "0E46122B23067C60F8", "0A06163BE00A5C303E", "0E46122B23067C60F8", "0E46163BE1847CE1FC",
|
|
||||||
"0E46122B23067C60F8"};
|
|
||||||
|
|
||||||
List<byte[]> frameData = new ArrayList<>();
|
|
||||||
|
|
||||||
for(String frame : frames)
|
|
||||||
{
|
|
||||||
byte[] bytes = new byte[frame.length() / 2];
|
|
||||||
for(int x = 0; x < frame.length(); x += 2)
|
|
||||||
{
|
|
||||||
String hex = frame.substring(x, x + 2);
|
|
||||||
bytes[x / 2] = (byte) (0xFF & Integer.parseInt(hex, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
frameData.add(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLog.debug("Starting thumb dv thread(s)");
|
|
||||||
|
|
||||||
final Listener<float[]> listener = packet -> {
|
|
||||||
mLog.info("Got an audio packet!");
|
|
||||||
};
|
|
||||||
|
|
||||||
try(ThumbDv thumbDv = new ThumbDv(AudioProtocol.P25_PHASE2, listener))
|
|
||||||
{
|
|
||||||
thumbDv.start();
|
|
||||||
|
|
||||||
Thread.sleep(6000);
|
|
||||||
|
|
||||||
for(int x = 0; x < 20; x++)
|
|
||||||
{
|
|
||||||
thumbDv.send(new EncodeSpeechRequest(new short[160]));
|
|
||||||
Thread.sleep(20);
|
|
||||||
}
|
|
||||||
// for(byte[] frame : frameData)
|
|
||||||
// {
|
|
||||||
// thumbDv.decode(frame);
|
|
||||||
// }
|
|
||||||
|
|
||||||
while(true);
|
|
||||||
}
|
|
||||||
catch(IOException ioe)
|
|
||||||
{
|
|
||||||
mLog.error("Error", ioe);
|
|
||||||
}
|
|
||||||
catch(InterruptedException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AMBE-3000R Message
|
|
||||||
*/
|
|
||||||
public abstract class AmbeMessage
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Converts the byte array to a hexadecimal string array
|
|
||||||
*/
|
|
||||||
public static String toHex(byte[] data)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
for(byte b: data)
|
|
||||||
{
|
|
||||||
sb.append(String.format("%02X", b));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.DecodeSpeechResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.EncodeSpeechResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.GetConfigResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.InitializeCodecResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.ProductIdResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.ReadyResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetChannelFormatResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetChannelResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetPacketModeResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetSpeechFormatResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetVocoderParameterResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.SetVocoderResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.UnknownResponse;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.response.VersionResponse;
|
|
||||||
|
|
||||||
public class AmbeMessageFactory
|
|
||||||
{
|
|
||||||
private static final byte CONTROL_PACKET = (byte)0x00;
|
|
||||||
private static final byte CHANNEL_PACKET = (byte)0x01;
|
|
||||||
private static final byte SPEECH_PACKET = (byte)0x02;
|
|
||||||
private static final int INDEX_PACKET_TYPE = 3;
|
|
||||||
private static final int INDEX_CONTROL_PACKET_TYPE = 4;
|
|
||||||
|
|
||||||
|
|
||||||
public static AmbeMessage getMessage(byte[] data)
|
|
||||||
{
|
|
||||||
if(data != null && data.length >= 5)
|
|
||||||
{
|
|
||||||
if(data[INDEX_PACKET_TYPE] == CONTROL_PACKET)
|
|
||||||
{
|
|
||||||
PacketField packetField = PacketField.fromValue(data[INDEX_CONTROL_PACKET_TYPE]);
|
|
||||||
|
|
||||||
switch(packetField)
|
|
||||||
{
|
|
||||||
case PKT_CHANNEL_0:
|
|
||||||
return new SetChannelResponse(data);
|
|
||||||
case PKT_CHANNEL_FORMAT:
|
|
||||||
return new SetChannelFormatResponse(data);
|
|
||||||
case PKT_CODEC_STOP:
|
|
||||||
return new SetPacketModeResponse(data);
|
|
||||||
case PKT_GET_CONFIG:
|
|
||||||
return new GetConfigResponse(data);
|
|
||||||
case PKT_INIT:
|
|
||||||
return new InitializeCodecResponse(data);
|
|
||||||
case PKT_PRODUCT_ID:
|
|
||||||
return new ProductIdResponse(data);
|
|
||||||
case PKT_RATE_PARAMETER:
|
|
||||||
return new SetVocoderParameterResponse(data);
|
|
||||||
case PKT_RATE_TABLE:
|
|
||||||
return new SetVocoderResponse(data);
|
|
||||||
case PKT_READY:
|
|
||||||
return new ReadyResponse(data);
|
|
||||||
case PKT_SPEECH_FORMAT:
|
|
||||||
return new SetSpeechFormatResponse(data);
|
|
||||||
case PKT_VERSION_STRING:
|
|
||||||
return new VersionResponse(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(data[INDEX_PACKET_TYPE] == CHANNEL_PACKET)
|
|
||||||
{
|
|
||||||
return new EncodeSpeechResponse(data);
|
|
||||||
}
|
|
||||||
else if(data[INDEX_PACKET_TYPE] == SPEECH_PACKET)
|
|
||||||
{
|
|
||||||
return new DecodeSpeechResponse(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UnknownResponse(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AMBE-3000 Initialization Options
|
|
||||||
*/
|
|
||||||
public enum InitializeOption
|
|
||||||
{
|
|
||||||
ENCODER((byte)0x01),
|
|
||||||
DECODER((byte)0x02),
|
|
||||||
ENCODER_AND_DECODER((byte)0x03),
|
|
||||||
ECHO_CANCELLER((byte)0x04),
|
|
||||||
ENCODER_DECODER_ECHO_CANCELLER((byte)0x07);
|
|
||||||
|
|
||||||
private byte mCode;
|
|
||||||
|
|
||||||
InitializeOption(byte code)
|
|
||||||
{
|
|
||||||
mCode = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getCode()
|
|
||||||
{
|
|
||||||
return mCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
/*
|
|
||||||
* *****************************************************************************
|
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* ****************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AMBE-3000R Control Packet Field enumeration
|
|
||||||
*/
|
|
||||||
public enum PacketField
|
|
||||||
{
|
|
||||||
PKT_ENCODER_CMODE((byte)0x05),
|
|
||||||
PKT_DECODER_CMODE((byte)0x06),
|
|
||||||
PKT_RATE_TABLE((byte)0x09),
|
|
||||||
PKT_RATE_PARAMETER((byte)0x0A),
|
|
||||||
PKT_INIT((byte)0x0B),
|
|
||||||
PKT_LOW_POWER((byte)0x10),
|
|
||||||
PKT_CHANNEL_FORMAT((byte)0x15),
|
|
||||||
PKT_SPEECH_FORMAT((byte)0x16),
|
|
||||||
PKT_CODEC_START((byte)0x2A),
|
|
||||||
PKT_CODEC_STOP((byte)0x2B),
|
|
||||||
PKT_PRODUCT_ID((byte)0x30),
|
|
||||||
PKT_VERSION_STRING((byte)0x31),
|
|
||||||
PKT_COMPAND((byte)0x32),
|
|
||||||
PKT_RESET((byte)0x33),
|
|
||||||
PKT_RESET_TO_SOFTWARE_CONFIG((byte)0x34),
|
|
||||||
PKT_HALT((byte)0x35),
|
|
||||||
PKT_GET_CONFIG((byte)0x36),
|
|
||||||
PKT_READ_CONFIG((byte)0x37),
|
|
||||||
PKT_CODEC_CFG((byte)0x38),
|
|
||||||
PKT_READY((byte)0x39),
|
|
||||||
PKT_PARITY_MODE((byte)0x3F),
|
|
||||||
PKT_CHANNEL_0((byte)0x40),
|
|
||||||
PKT_WRITE_I2C((byte)0x44),
|
|
||||||
PKT_CLEAR_CODEC_RESET((byte)0x46),
|
|
||||||
PKT_SET_CODEC_RESET((byte)0x47),
|
|
||||||
PKT_DISCARD_CODEC_SAMPLES((byte)0x48),
|
|
||||||
PKT_DELAY_NUMBER_MICRO_SECONDS((byte)0x49),
|
|
||||||
PKT_DELAY_NUMBER_NANO_SECONDS((byte)0x4A),
|
|
||||||
PKT_GAIN((byte)0x4B),
|
|
||||||
PKT_RTS_THRESHOLD((byte)0x4E),
|
|
||||||
|
|
||||||
//Speech packet values
|
|
||||||
SPEECH_DATA((byte)0x00),
|
|
||||||
CHANNEL_DATA_HARD_SYMBOL((byte)0x01),
|
|
||||||
CMODE((byte)0x02),
|
|
||||||
SAMPLE_COUNT((byte)0x03),
|
|
||||||
TONE((byte)0x08),
|
|
||||||
CHANNEL_DATA_SOFT_SYMBOL((byte)0x17),
|
|
||||||
VOCODER((byte)0x40),
|
|
||||||
|
|
||||||
//Packet Types
|
|
||||||
PACKET_TYPE_CONTROL((byte)0x00),
|
|
||||||
PACKET_TYPE_ENCODE_SPEECH((byte)0x01),
|
|
||||||
PACKET_TYPE_DECODE_SPEECH((byte)0x02),
|
|
||||||
|
|
||||||
UNKNOWN((byte)0x00);
|
|
||||||
|
|
||||||
private byte mCode;
|
|
||||||
|
|
||||||
PacketField(byte code)
|
|
||||||
{
|
|
||||||
mCode = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet type byte code value
|
|
||||||
*/
|
|
||||||
public byte getCode()
|
|
||||||
{
|
|
||||||
return mCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup a packet type from the code byte value
|
|
||||||
*/
|
|
||||||
public static PacketField fromValue(byte value)
|
|
||||||
{
|
|
||||||
switch(value)
|
|
||||||
{
|
|
||||||
case (byte)0x05:
|
|
||||||
return PKT_ENCODER_CMODE;
|
|
||||||
case (byte)0x06:
|
|
||||||
return PKT_DECODER_CMODE;
|
|
||||||
case (byte)0x09:
|
|
||||||
return PKT_RATE_TABLE;
|
|
||||||
case (byte)0x0A:
|
|
||||||
return PKT_RATE_PARAMETER;
|
|
||||||
case (byte)0x0B:
|
|
||||||
return PKT_INIT;
|
|
||||||
case (byte)0x10:
|
|
||||||
return PKT_LOW_POWER;
|
|
||||||
case (byte)0x15:
|
|
||||||
return PKT_CHANNEL_FORMAT;
|
|
||||||
case (byte)0x16:
|
|
||||||
return PKT_SPEECH_FORMAT;
|
|
||||||
case (byte)0x2A:
|
|
||||||
return PKT_CODEC_START;
|
|
||||||
case (byte)0x2B:
|
|
||||||
return PKT_CODEC_STOP;
|
|
||||||
case (byte)0x30:
|
|
||||||
return PKT_PRODUCT_ID;
|
|
||||||
case (byte)0x31:
|
|
||||||
return PKT_VERSION_STRING;
|
|
||||||
case (byte)0x32:
|
|
||||||
return PKT_COMPAND;
|
|
||||||
case (byte)0x33:
|
|
||||||
return PKT_RESET;
|
|
||||||
case (byte)0x34:
|
|
||||||
return PKT_RESET_TO_SOFTWARE_CONFIG;
|
|
||||||
case (byte)0x35:
|
|
||||||
return PKT_HALT;
|
|
||||||
case (byte)0x36:
|
|
||||||
return PKT_GET_CONFIG;
|
|
||||||
case (byte)0x37:
|
|
||||||
return PKT_READ_CONFIG;
|
|
||||||
case (byte)0x38:
|
|
||||||
return PKT_CODEC_CFG;
|
|
||||||
case (byte)0x39:
|
|
||||||
return PKT_READY;
|
|
||||||
case (byte)0x3F:
|
|
||||||
return PKT_PARITY_MODE;
|
|
||||||
case (byte)0x40:
|
|
||||||
return PKT_CHANNEL_0;
|
|
||||||
case (byte)0x44:
|
|
||||||
return PKT_WRITE_I2C;
|
|
||||||
case (byte)0x46:
|
|
||||||
return PKT_CLEAR_CODEC_RESET;
|
|
||||||
case (byte)0x47:
|
|
||||||
return PKT_SET_CODEC_RESET;
|
|
||||||
case (byte)0x48:
|
|
||||||
return PKT_DISCARD_CODEC_SAMPLES;
|
|
||||||
case (byte)0x49:
|
|
||||||
return PKT_DELAY_NUMBER_MICRO_SECONDS;
|
|
||||||
case (byte)0x4A:
|
|
||||||
return PKT_DELAY_NUMBER_NANO_SECONDS;
|
|
||||||
case (byte)0x4B:
|
|
||||||
return PKT_GAIN;
|
|
||||||
case (byte)0x4E:
|
|
||||||
return PKT_RTS_THRESHOLD;
|
|
||||||
default:
|
|
||||||
return UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message;
|
|
||||||
|
|
||||||
public enum VocoderRate
|
|
||||||
{
|
|
||||||
//AMBE-1000 Standard Rates
|
|
||||||
RATE_0((byte)0x00, 2400,0),
|
|
||||||
RATE_1((byte)0x01, 3600,0),
|
|
||||||
RATE_2((byte)0x02, 3600,1200),
|
|
||||||
RATE_3((byte)0x03, 4800,0),
|
|
||||||
RATE_4((byte)0x04, 9600,0),
|
|
||||||
RATE_5((byte)0x05, 2350,50),
|
|
||||||
RATE_6((byte)0x06, 4850,4750),
|
|
||||||
RATE_7((byte)0x07, 4550,250),
|
|
||||||
RATE_8((byte)0x08, 3100,1700),
|
|
||||||
RATE_9((byte)0x09, 4400,2800),
|
|
||||||
RATE_10((byte)0x0A, 4150,2250),
|
|
||||||
RATE_11((byte)0x0B, 3350,250),
|
|
||||||
RATE_12((byte)0x0C, 7750,250),
|
|
||||||
RATE_13((byte)0x0D, 4650,3350),
|
|
||||||
RATE_14((byte)0x0E, 3750,250),
|
|
||||||
RATE_15((byte)0x0F, 4000,0),
|
|
||||||
|
|
||||||
//AMBE-2000 Standard Rates
|
|
||||||
RATE_16((byte)0x10, 3600,0),
|
|
||||||
RATE_17((byte)0x11, 4000,0),
|
|
||||||
RATE_18((byte)0x12, 4800,0),
|
|
||||||
RATE_19((byte)0x13, 6400,0),
|
|
||||||
RATE_20((byte)0x14, 8000,0),
|
|
||||||
RATE_21((byte)0x15, 9600,0),
|
|
||||||
RATE_22((byte)0x16, 2400,1600),
|
|
||||||
RATE_23((byte)0x17, 3600,1200),
|
|
||||||
RATE_24((byte)0x18, 4000,800),
|
|
||||||
RATE_25((byte)0x19, 2400,2400),
|
|
||||||
RATE_26((byte)0x1A, 4000,2400),
|
|
||||||
RATE_27((byte)0x1B, 4400,2800), //Is this compatible with APCO25 Phase 1?
|
|
||||||
RATE_28((byte)0x1C, 4000,4000),
|
|
||||||
RATE_29((byte)0x1D, 2400,7200),
|
|
||||||
RATE_30((byte)0x1E, 3600,6000),
|
|
||||||
RATE_31((byte)0x1F, 2000,0),
|
|
||||||
RATE_32((byte)0x20, 3600,2800),
|
|
||||||
|
|
||||||
//AMBE-3000 Standard Rates (AMBE+2)
|
|
||||||
RATE_33((byte)0x21, 2450,1150), //APCO25 HR (Phase 2), DMR, NXDN, DSTAR
|
|
||||||
RATE_34((byte)0x22, 2450,0),
|
|
||||||
RATE_35((byte)0x23, 2250,1150),
|
|
||||||
RATE_36((byte)0x24, 2250,0),
|
|
||||||
RATE_37((byte)0x25, 2400,0),
|
|
||||||
RATE_38((byte)0x26, 3000,0),
|
|
||||||
RATE_39((byte)0x27, 3600,0),
|
|
||||||
RATE_40((byte)0x28, 4000,0),
|
|
||||||
RATE_41((byte)0x29, 4400,0),
|
|
||||||
RATE_42((byte)0x2A, 4800,0),
|
|
||||||
RATE_43((byte)0x2B, 6400,0),
|
|
||||||
RATE_44((byte)0x2C, 7200,0),
|
|
||||||
RATE_45((byte)0x2D, 8000,0),
|
|
||||||
RATE_46((byte)0x2E, 9600,0),
|
|
||||||
RATE_47((byte)0x2F, 2450,250),
|
|
||||||
RATE_48((byte)0x30, 3350,250),
|
|
||||||
RATE_49((byte)0x31, 3750,250),
|
|
||||||
RATE_50((byte)0x32, 4550,250),
|
|
||||||
RATE_51((byte)0x33, 2450,1950),
|
|
||||||
RATE_52((byte)0x34, 2450,2350),
|
|
||||||
RATE_53((byte)0x35, 2450,3550),
|
|
||||||
RATE_54((byte)0x36, 2450,4750),
|
|
||||||
RATE_55((byte)0x37, 2600,1400),
|
|
||||||
RATE_56((byte)0x38, 3600,1200),
|
|
||||||
RATE_57((byte)0x39, 4000,800),
|
|
||||||
RATE_58((byte)0x3A, 4000,2400),
|
|
||||||
RATE_59((byte)0x3B, 4400,2800), //Is this compatible with APCO25 Phase 1?
|
|
||||||
RATE_60((byte)0x3C, 4000,4000),
|
|
||||||
RATE_61((byte)0x3D, 3600,6000);
|
|
||||||
|
|
||||||
private byte mCode;
|
|
||||||
private int mSpeechRate;
|
|
||||||
private int mFecRate;
|
|
||||||
|
|
||||||
VocoderRate(byte code, int speechRate, int fecRate)
|
|
||||||
{
|
|
||||||
mCode = code;
|
|
||||||
mSpeechRate = speechRate;
|
|
||||||
mFecRate = fecRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Byte code value for the vocoder rate
|
|
||||||
*/
|
|
||||||
public byte getCode()
|
|
||||||
{
|
|
||||||
return mCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Speech rate in bits per second (bps)
|
|
||||||
*/
|
|
||||||
public int getSpeechRate()
|
|
||||||
{
|
|
||||||
return mSpeechRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forward Error Correction rate in bits per second (bps)
|
|
||||||
*/
|
|
||||||
public int getFecRate()
|
|
||||||
{
|
|
||||||
return mFecRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.AmbeMessage;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AMBE-3000R Request Packet
|
|
||||||
*/
|
|
||||||
public abstract class AmbeRequest extends AmbeMessage
|
|
||||||
{
|
|
||||||
private static final byte PACKET_START_BYTE = (byte)0x61;
|
|
||||||
protected static final int PACKET_TYPE_INDEX = 3;
|
|
||||||
protected static final int PAYLOAD_START_INDEX = 4;
|
|
||||||
|
|
||||||
public abstract PacketField getType();
|
|
||||||
public abstract byte[] getData();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a byte array of the specified length plus 4 packet header bytes with packet start, length and control
|
|
||||||
* bytes filled in.
|
|
||||||
*
|
|
||||||
* @param length of the message (not including the 4 byte packet header)
|
|
||||||
* @return byte array with packet header pre-filled.
|
|
||||||
*/
|
|
||||||
protected byte[] createMessage(int length, PacketField type)
|
|
||||||
{
|
|
||||||
byte[] data = new byte[length + 4];
|
|
||||||
|
|
||||||
data[0] = PACKET_START_BYTE;
|
|
||||||
data[1] = (byte)((length >> 8 & 0xFF));
|
|
||||||
data[2] = (byte)(length & 0xFF);
|
|
||||||
|
|
||||||
if(type == PacketField.PACKET_TYPE_ENCODE_SPEECH || type == PacketField.PACKET_TYPE_DECODE_SPEECH)
|
|
||||||
{
|
|
||||||
data[PACKET_TYPE_INDEX] = type.getCode();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data[PACKET_TYPE_INDEX] = PacketField.PACKET_TYPE_CONTROL.getCode();
|
|
||||||
data[PAYLOAD_START_INDEX] = type.getCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.VocoderRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode speech request, used to request decode of an encoded audio frame.
|
|
||||||
*/
|
|
||||||
public class DecodeSpeechRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private static final int CHANNEL_DATA_IDENTIFIER_INDEX = 4;
|
|
||||||
private static final byte SAMPLE_COUNT = (byte)(0xFF & 160); //8 kHz Audio sample count for 20ms frame
|
|
||||||
|
|
||||||
private byte[] mAudioFrame;
|
|
||||||
private VocoderRate mVocoderRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an audio frame decode request using the specified vocoder rate.
|
|
||||||
* @param audioFrame of encoded audio samples
|
|
||||||
* @param vocoderRate to use when decoding
|
|
||||||
*/
|
|
||||||
public DecodeSpeechRequest(byte[] audioFrame, VocoderRate vocoderRate)
|
|
||||||
{
|
|
||||||
mAudioFrame = audioFrame;
|
|
||||||
mVocoderRate = vocoderRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an audio frame decode request using the current vocoder rate.
|
|
||||||
* @param audioFrame of encoded audio samples
|
|
||||||
*/
|
|
||||||
public DecodeSpeechRequest(byte[] audioFrame)
|
|
||||||
{
|
|
||||||
this(audioFrame, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PACKET_TYPE_ENCODE_SPEECH;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasVocoderRate()
|
|
||||||
{
|
|
||||||
return mVocoderRate != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
if(hasVocoderRate())
|
|
||||||
{
|
|
||||||
int length = mAudioFrame.length + 9;
|
|
||||||
|
|
||||||
byte[] data = createMessage(length, getType());
|
|
||||||
int offset = CHANNEL_DATA_IDENTIFIER_INDEX;
|
|
||||||
|
|
||||||
data[offset++] = PacketField.VOCODER.getCode();
|
|
||||||
data[offset++] = mVocoderRate.getCode();
|
|
||||||
|
|
||||||
data[offset++] = PacketField.CHANNEL_DATA_HARD_SYMBOL.getCode();
|
|
||||||
data[offset++] = (byte)(0xFF & (mAudioFrame.length * 8));
|
|
||||||
System.arraycopy(mAudioFrame, 0, data, offset, mAudioFrame.length);
|
|
||||||
offset += mAudioFrame.length;
|
|
||||||
data[offset++] = PacketField.SAMPLE_COUNT.getCode();
|
|
||||||
data[offset++] = (byte)0xA0;
|
|
||||||
data[offset++] = (byte)0x02;
|
|
||||||
data[offset++] = (byte)0x00;
|
|
||||||
data[offset] = (byte)0x00;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int length = mAudioFrame.length + 2;
|
|
||||||
byte[] data = createMessage(length, getType());
|
|
||||||
|
|
||||||
int offset = CHANNEL_DATA_IDENTIFIER_INDEX;
|
|
||||||
data[offset++] = PacketField.CHANNEL_DATA_HARD_SYMBOL.getCode();
|
|
||||||
data[offset++] = (byte)(0xFF & (mAudioFrame.length * 8));
|
|
||||||
System.arraycopy(mAudioFrame, 0, data, offset, mAudioFrame.length);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
public class EncodeSpeechRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private static final int CHANNEL_IDENTIFIER_INDEX = 4;
|
|
||||||
private static final int SPEECH_DATA_IDENTIFIER_INDEX = 5;
|
|
||||||
private static final int SAMPLE_COUNT_INDEX = 6;
|
|
||||||
private static final int SPEECH_DATA_START_INDEX = 7;
|
|
||||||
|
|
||||||
private short[] mSamples;
|
|
||||||
|
|
||||||
public EncodeSpeechRequest(short[] samples)
|
|
||||||
{
|
|
||||||
mSamples = samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EncodeSpeechRequest(float[] samples)
|
|
||||||
{
|
|
||||||
mSamples = new short[samples.length];
|
|
||||||
|
|
||||||
for(int x = 0; x < samples.length; x++)
|
|
||||||
{
|
|
||||||
if(samples[x] > 1.0f)
|
|
||||||
{
|
|
||||||
mSamples[x] = Short.MAX_VALUE;
|
|
||||||
}
|
|
||||||
else if(samples[x] < -1.0f)
|
|
||||||
{
|
|
||||||
mSamples[x] = Short.MIN_VALUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mSamples[x] = (short)(samples[x] * Short.MAX_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PACKET_TYPE_DECODE_SPEECH;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
int length = (mSamples.length * 2) + 3;
|
|
||||||
byte[] data = createMessage(length, getType());
|
|
||||||
|
|
||||||
data[CHANNEL_IDENTIFIER_INDEX] = PacketField.PKT_CHANNEL_0.getCode();
|
|
||||||
data[SPEECH_DATA_IDENTIFIER_INDEX] = (byte)0x00;
|
|
||||||
data[SAMPLE_COUNT_INDEX] = (byte)(0xFF & mSamples.length);
|
|
||||||
|
|
||||||
int pointer = SPEECH_DATA_START_INDEX;
|
|
||||||
|
|
||||||
for(short sample: mSamples)
|
|
||||||
{
|
|
||||||
data[pointer++] = (byte)((sample >> 8 & 0xFF));
|
|
||||||
data[pointer++] = (byte)(sample & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get configuration request packet
|
|
||||||
*/
|
|
||||||
public class GetConfigRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_GET_CONFIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.InitializeOption;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize CODEC request packet
|
|
||||||
*/
|
|
||||||
public class InitializeCodecRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private static final int INITIALIZE_OPTION_INDEX = 5;
|
|
||||||
private InitializeOption mInitializeOption;
|
|
||||||
|
|
||||||
public InitializeCodecRequest(InitializeOption option)
|
|
||||||
{
|
|
||||||
mInitializeOption = option;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
byte[] data = createMessage(2, getType());
|
|
||||||
data[INITIALIZE_OPTION_INDEX] = mInitializeOption.getCode();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Product ID request packet
|
|
||||||
*/
|
|
||||||
public class ProductIdRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_PRODUCT_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset request packet
|
|
||||||
*/
|
|
||||||
public class ResetRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_RESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set channel format request packet
|
|
||||||
*/
|
|
||||||
public class SetChannelFormatRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private static final int FORMAT_INDEX = 5;
|
|
||||||
private static final byte FORMAT = (byte)0x00;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_CHANNEL_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
byte[] data = createMessage(2, getType());
|
|
||||||
data[FORMAT_INDEX] = FORMAT;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set channel request packet
|
|
||||||
*/
|
|
||||||
public class SetChannelRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_CHANNEL_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet mode (versus CODEC mode) request packet
|
|
||||||
*/
|
|
||||||
public class SetPacketModeRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_CODEC_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set speech format request packet
|
|
||||||
*/
|
|
||||||
public class SetSpeechFormatRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private static final int FORMAT_INDEX = 5;
|
|
||||||
private static final byte FORMAT = (byte)0x00;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_SPEECH_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
byte[] data = createMessage(2, getType());
|
|
||||||
data[FORMAT_INDEX] = FORMAT;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Vocoder parameters request packet
|
|
||||||
*/
|
|
||||||
public class SetVocoderParametersRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private int mWord0;
|
|
||||||
private int mWord1;
|
|
||||||
private int mWord2;
|
|
||||||
private int mWord3;
|
|
||||||
private int mWord4;
|
|
||||||
private int mWord5;
|
|
||||||
|
|
||||||
public SetVocoderParametersRequest(int word0, int word1, int word2, int word3, int word4, int word5)
|
|
||||||
{
|
|
||||||
mWord0 = word0;
|
|
||||||
mWord1 = word1;
|
|
||||||
mWord2 = word2;
|
|
||||||
mWord3 = word3;
|
|
||||||
mWord4 = word4;
|
|
||||||
mWord5 = word5;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_RATE_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
byte[] data = createMessage(14, getType());
|
|
||||||
data[PAYLOAD_START_INDEX + 1] = (byte)(mWord0 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 2] = (byte)(mWord0 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 3] = (byte)(mWord1 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 4] = (byte)(mWord1 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 5] = (byte)(mWord2 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 6] = (byte)(mWord2 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 7] = (byte)(mWord3 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 8] = (byte)(mWord3 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 9] = (byte)(mWord4 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 10] = (byte)(mWord4 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 11] = (byte)(mWord5 >> 8 & 0xFF);
|
|
||||||
data[PAYLOAD_START_INDEX + 12] = (byte)(mWord5 & 0xFF);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.VocoderRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Vocoder Rate request packet
|
|
||||||
*/
|
|
||||||
public class SetVocoderRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
private VocoderRate mVocoderRate;
|
|
||||||
|
|
||||||
public SetVocoderRequest(VocoderRate rate)
|
|
||||||
{
|
|
||||||
mVocoderRate = rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_RATE_TABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
byte[] data = createMessage(2, getType());
|
|
||||||
data[PAYLOAD_START_INDEX + 1] = mVocoderRate.getCode();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * ******************************************************************************
|
|
||||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
* *
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
* * *****************************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.request;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version string request packet
|
|
||||||
*/
|
|
||||||
public class VersionRequest extends AmbeRequest
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PKT_VERSION_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getData()
|
|
||||||
{
|
|
||||||
return createMessage(1, getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* sdr-trunk
|
|
||||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
|
||||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
package io.github.dsheirer.audio.convert.thumbdv.message.response;
|
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.thumbdv.message.PacketField;
|
|
||||||
import io.github.dsheirer.sample.ConversionUtils;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode speech response
|
|
||||||
*/
|
|
||||||
public class DecodeSpeechResponse extends AmbeResponse
|
|
||||||
{
|
|
||||||
public DecodeSpeechResponse(byte[] message)
|
|
||||||
{
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PacketField getType()
|
|
||||||
{
|
|
||||||
return PacketField.PACKET_TYPE_DECODE_SPEECH;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Payload of the packet (does not include the packet header)
|
|
||||||
*/
|
|
||||||
protected byte[] getPayload()
|
|
||||||
{
|
|
||||||
return Arrays.copyOfRange(getMessage(), PAYLOAD_START_INDEX + 1, getMessage().length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float[] getSamples()
|
|
||||||
{
|
|
||||||
return ConversionUtils.convertFromSigned16BitSamples(getPayload());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return "DECODED SPEECH: SAMPLE COUNT:" + getSamples().length + " " + toHex(getPayload());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user