mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 17:17:29 -05:00
Compare commits
40 Commits
v0.5.0-bet
...
v0.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a24c3736f4 | ||
|
|
ac61b681e6 | ||
|
|
0866bfd555 | ||
|
|
79fed701d9 | ||
|
|
48a93990e8 | ||
|
|
414ba25d61 | ||
|
|
f67f90e8b0 | ||
|
|
5751c70212 | ||
|
|
4e15c426a8 | ||
|
|
ceda189260 | ||
|
|
fce0ae33e7 | ||
|
|
fc5c6ef841 | ||
|
|
d0033578d5 | ||
|
|
670ec3a097 | ||
|
|
8bfb1d5470 | ||
|
|
46a916a945 | ||
|
|
459e77390a | ||
|
|
f4ab46b79d | ||
|
|
3c58e98788 | ||
|
|
36de81248c | ||
|
|
925353d515 | ||
|
|
7c32897321 | ||
|
|
cbeda19d27 | ||
|
|
8148ca48af | ||
|
|
adcb55ffbc | ||
|
|
1152b13220 | ||
|
|
166383e1ed | ||
|
|
0d5d1b20e3 | ||
|
|
77ea43f61a | ||
|
|
f988344222 | ||
|
|
60489e1fef | ||
|
|
ac8aa17a80 | ||
|
|
25a42126df | ||
|
|
1b90e0b50c | ||
|
|
7f5ad7eb20 | ||
|
|
0e6713b6e2 | ||
|
|
96d3996bec | ||
|
|
0fb148d31e | ||
|
|
cebca28b19 | ||
|
|
af8cc0255e |
5
.idea/misc.xml
generated
5
.idea/misc.xml
generated
@@ -1,7 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="liberica-17.0.2-fx" project-jdk-type="JavaSDK">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="liberica-19.0.1.fx" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
64
build.gradle
64
build.gradle
@@ -28,7 +28,7 @@ repositories {
|
|||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
|
|
||||||
version = '0.5.0-beta2'
|
version = '0.5.0-beta6'
|
||||||
sourceCompatibility = '17'
|
sourceCompatibility = '17'
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@@ -43,10 +43,10 @@ test {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
// JUnit Tests
|
// JUnit Tests
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
testImplementation 'org.assertj:assertj-core:3.8.0'
|
testImplementation 'org.assertj:assertj-core:3.23.1'
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
testImplementation('org.junit.jupiter:junit-jupiter-api:5.9.0')
|
||||||
testImplementation 'org.mockito:mockito-core:3.+'
|
testImplementation 'org.mockito:mockito-core:4.8.0'
|
||||||
|
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
||||||
|
|
||||||
@@ -56,37 +56,37 @@ dependencies {
|
|||||||
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.2.3'
|
implementation 'ch.qos.logback:logback-classic:1.4.4'
|
||||||
implementation 'ch.qos.logback:logback-core:1.2.3'
|
implementation 'ch.qos.logback:logback-core:1.4.4'
|
||||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.0'
|
||||||
implementation 'com.fazecast:jSerialComm:2.5.0'
|
implementation 'com.fazecast:jSerialComm:2.9.2'
|
||||||
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.1'
|
||||||
implementation 'com.google.code.gson:gson:2.8.6'
|
implementation 'com.google.code.gson:gson:2.10'
|
||||||
implementation 'com.google.guava:guava:27.0.1-jre'
|
implementation 'com.google.guava:guava:31.1-jre'
|
||||||
implementation 'com.jidesoft:jide-oss:3.6.18'
|
implementation 'com.jidesoft:jide-oss:3.6.18'
|
||||||
implementation 'com.miglayout:miglayout-swing:5.2'
|
implementation 'com.miglayout:miglayout-swing:11.0'
|
||||||
implementation 'com.mpatric:mp3agic:0.9.1'
|
implementation 'com.mpatric:mp3agic:0.9.1'
|
||||||
implementation 'commons-io:commons-io:2.7'
|
implementation 'commons-io:commons-io:2.11.0'
|
||||||
implementation 'eu.hansolo:charts:1.0.5'
|
implementation 'eu.hansolo:charts:1.0.5'
|
||||||
implementation 'io.github.dsheirer:radio-reference-api:15.1.8'
|
implementation 'io.github.dsheirer:radio-reference-api:15.1.8'
|
||||||
implementation 'javax.usb:usb-api:1.0.2'
|
implementation 'javax.usb:usb-api:1.0.2'
|
||||||
implementation 'net.coderazzi:tablefilter-swing:5.4.0'
|
implementation 'net.coderazzi:tablefilter-swing:5.5.4'
|
||||||
implementation 'org.apache.commons:commons-compress:1.20'
|
implementation 'org.apache.commons:commons-compress:1.21'
|
||||||
implementation 'org.apache.commons:commons-lang3:3.8.1'
|
implementation 'org.apache.commons:commons-lang3:3.12.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.9.0'
|
implementation 'org.apache.commons:commons-csv:1.9.0'
|
||||||
implementation 'org.apache.mina:mina-core:2.1.3'
|
implementation 'org.apache.mina:mina-core:2.2.1'
|
||||||
implementation 'org.apache.mina:mina-http:2.1.3'
|
implementation 'org.apache.mina:mina-http:2.2.1'
|
||||||
implementation 'org.controlsfx:controlsfx:11.1.0'
|
implementation 'org.controlsfx:controlsfx:11.1.2'
|
||||||
implementation 'org.rauschig:jarchivelib:1.0.0'
|
implementation 'org.rauschig:jarchivelib:1.2.0'
|
||||||
implementation 'org.slf4j:slf4j-api:1.7.25'
|
implementation 'org.slf4j:slf4j-api:2.0.3'
|
||||||
implementation 'org.usb4java:libusb4java:1.3.0'
|
implementation 'org.usb4java:libusb4java:1.3.0'
|
||||||
implementation 'org.usb4java:usb4java:1.3.0'
|
implementation 'org.usb4java:usb4java:1.3.0'
|
||||||
implementation 'org.usb4java:usb4java-javax:1.3.0'
|
implementation 'org.usb4java:usb4java-javax:1.3.0'
|
||||||
implementation 'io.github.dsheirer:libusb4java-darwin-aarch64:1.3.0' //usb4java native lib for OSX M1 cpu
|
implementation 'io.github.dsheirer:libusb4java-darwin-aarch64:1.3.1' //usb4java native lib for OSX M1 cpu
|
||||||
implementation 'pl.edu.icm:JLargeArrays:1.6'
|
implementation 'pl.edu.icm:JLargeArrays:1.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,11 +139,11 @@ String targetWindowsX86_64 = 'windows-x86_64-v' + version
|
|||||||
* author's development environment, but can be changed to your environment if you want to use this build pattern.
|
* 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_base = '/home/denny/java_jdks/'
|
||||||
String jdk_linux_aarch64 = jdk_base + 'linux-arm64/jdk-17.0.2-full'
|
String jdk_linux_aarch64 = jdk_base + 'linux-arm64/jdk-19.0.1-full'
|
||||||
String jdk_linux_x86_64 = jdk_base + 'linux-x64/jdk-17.0.2-full'
|
String jdk_linux_x86_64 = jdk_base + 'linux-x64/jdk-19.0.1-full'
|
||||||
String jdk_osx_x86_64 = jdk_base + 'osx-x64/jdk-17.0.2-full.jdk'
|
String jdk_osx_x86_64 = jdk_base + 'osx-x64/jdk-19.0.1-full.jdk'
|
||||||
String jdk_osx_aarch64 = jdk_base + 'osx-arm64/jdk-17.0.2-full.jdk'
|
String jdk_osx_aarch64 = jdk_base + 'osx-arm64/jdk-19.0.1-full.jdk'
|
||||||
String jdk_windows_x86_64 = jdk_base + 'windows-x64/jdk-17.0.2-full'
|
String jdk_windows_x86_64 = jdk_base + 'windows-x64/jdk-19.0.1-full'
|
||||||
|
|
||||||
boolean hasTargetJdks = file(jdk_linux_x86_64).exists() || file(jdk_linux_aarch64).exists() ||
|
boolean hasTargetJdks = file(jdk_linux_x86_64).exists() || file(jdk_linux_aarch64).exists() ||
|
||||||
file(jdk_osx_x86_64).exists() || file(jdk_osx_aarch64).exists() || file(jdk_windows_x86_64).exists()
|
file(jdk_osx_x86_64).exists() || file(jdk_osx_aarch64).exists() || file(jdk_windows_x86_64).exists()
|
||||||
@@ -172,19 +172,19 @@ runtime {
|
|||||||
println("Building all runtime images")
|
println("Building all runtime images")
|
||||||
println("The [ > jre: ] build phase downloads several target JDKs and this may take a while ... please wait")
|
println("The [ > jre: ] build phase downloads several target JDKs and this may take a while ... please wait")
|
||||||
targetPlatform(targetLinuxAarch64) {
|
targetPlatform(targetLinuxAarch64) {
|
||||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/17.0.2+9/bellsoft-jdk17.0.2+9-linux-aarch64-full.tar.gz")
|
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-linux-aarch64-full.tar.gz")
|
||||||
}
|
}
|
||||||
targetPlatform(targetLinuxX86_64) {
|
targetPlatform(targetLinuxX86_64) {
|
||||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/17.0.2+9/bellsoft-jdk17.0.2+9-linux-amd64-full.tar.gz")
|
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-linux-amd64-full.tar.gz")
|
||||||
}
|
}
|
||||||
targetPlatform(targetOsxAarch64) {
|
targetPlatform(targetOsxAarch64) {
|
||||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/17.0.2+9/bellsoft-jdk17.0.2+9-macos-aarch64-full.tar.gz")
|
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-macos-aarch64-full.tar.gz")
|
||||||
}
|
}
|
||||||
targetPlatform(targetOsxX86_64) {
|
targetPlatform(targetOsxX86_64) {
|
||||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/17.0.2+9/bellsoft-jdk17.0.2+9-macos-amd64-full.tar.gz")
|
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-macos-amd64-full.tar.gz")
|
||||||
}
|
}
|
||||||
targetPlatform(targetWindowsX86_64) {
|
targetPlatform(targetWindowsX86_64) {
|
||||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/17.0.2+9/bellsoft-jdk17.0.2+9-windows-amd64-full.zip")
|
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-windows-amd64-full.zip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Build using pre-downloaded JDKs
|
//Build using pre-downloaded JDKs
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
21
gradle/wrapper/gradle-wrapper.properties
vendored
21
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,24 @@
|
|||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
# 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/>
|
||||||
|
# *****************************************************************************
|
||||||
|
#
|
||||||
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-rc-3-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
290
gradlew
vendored
290
gradlew
vendored
@@ -1,94 +1,132 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2015 the original author or authors.
|
# ******************************************************************************
|
||||||
|
# Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# you may not use this file except in compliance with the License.
|
# it under the terms of the GNU General Public License as published by
|
||||||
# You may obtain a copy of the License at
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
# 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.
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# You should have received a copy of the GNU General Public License
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
# 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.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## Gradle start up script for UN*X
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
##
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
APP_NAME="Gradle"
|
||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=${0##*/}
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@@ -97,7 +135,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
@@ -105,79 +143,95 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
warn "Could not query maximum file descriptor limit"
|
||||||
fi
|
esac
|
||||||
ulimit -n $MAX_FD
|
case $MAX_FD in #(
|
||||||
if [ $? -ne 0 ] ; then
|
'' | soft) :;; #(
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
*)
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
else
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
0) set -- ;;
|
|
||||||
1) set -- "$args0" ;;
|
|
||||||
2) set -- "$args0" "$args1" ;;
|
|
||||||
3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=`save "$@"`
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
25
gradlew.bat
vendored
25
gradlew.bat
vendored
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -51,7 +54,7 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
@@ -61,28 +64,14 @@ echo location of your Java installation.
|
|||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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;
|
package io.github.dsheirer.alias;
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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;
|
package io.github.dsheirer.alias;
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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;
|
package io.github.dsheirer.alias;
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class AudioSegmentBroadcaster<T extends AudioSegment> extends Broadcaster
|
|||||||
@Override
|
@Override
|
||||||
public void broadcast(T audioSegment)
|
public void broadcast(T audioSegment)
|
||||||
{
|
{
|
||||||
for(Listener<T> listener : mListeners)
|
for(Listener<T> listener : getListeners())
|
||||||
{
|
{
|
||||||
audioSegment.incrementConsumerCount();
|
audioSegment.incrementConsumerCount();
|
||||||
listener.receive(audioSegment);
|
listener.receive(audioSegment);
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.Float;
|
||||||
|
import java.lang.Math;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AudioUtils
|
public class AudioUtils
|
||||||
@@ -78,4 +81,43 @@ public class AudioUtils
|
|||||||
|
|
||||||
return stream.toByteArray();
|
return stream.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize audio samples
|
||||||
|
*/
|
||||||
|
public static List<float[]> normalize(List<float[]> audioBuffers)
|
||||||
|
{
|
||||||
|
float targetMax = 0.95f; // -0.44dBFS
|
||||||
|
float max = 0.1f; // Initialize at 0.1 (-20dBFS) to limit maximum gain
|
||||||
|
|
||||||
|
for(float[] audioBuffer: audioBuffers)
|
||||||
|
{
|
||||||
|
for(float value: audioBuffer)
|
||||||
|
{
|
||||||
|
float newMax = Math.max(max, Math.abs(value));
|
||||||
|
if(!Float.isNaN(newMax))
|
||||||
|
{
|
||||||
|
max = newMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(targetMax == max)
|
||||||
|
{
|
||||||
|
return audioBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
float gain = targetMax / max;
|
||||||
|
|
||||||
|
for(float[] audioBuffer: audioBuffers)
|
||||||
|
{
|
||||||
|
for(int i=0;i<audioBuffer.length;i++)
|
||||||
|
{
|
||||||
|
audioBuffer[i] *= gain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return audioBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
private final static Logger mLog = LoggerFactory.getLogger(AudioStreamingBroadcaster.class);
|
private final static Logger mLog = LoggerFactory.getLogger(AudioStreamingBroadcaster.class);
|
||||||
|
|
||||||
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
|
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
|
||||||
private ScheduledFuture mRecordingQueueProcessorFuture;
|
private ScheduledFuture<?> mRecordingQueueProcessorFuture;
|
||||||
|
|
||||||
private RecordingQueueProcessor mRecordingQueueProcessor = new RecordingQueueProcessor();
|
private RecordingQueueProcessor mRecordingQueueProcessor = new RecordingQueueProcessor();
|
||||||
private Queue<AudioRecording> mAudioRecordingQueue = new LinkedTransferQueue<>();
|
private Queue<AudioRecording> mAudioRecordingQueue = new LinkedTransferQueue<>();
|
||||||
@@ -52,6 +52,10 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
private long mMaximumRecordingAge;
|
private long mMaximumRecordingAge;
|
||||||
private AtomicBoolean mStreaming = new AtomicBoolean();
|
private AtomicBoolean mStreaming = new AtomicBoolean();
|
||||||
|
|
||||||
|
protected boolean mInlineActive = false;
|
||||||
|
protected int mInlineInterval;
|
||||||
|
protected int mInlineRemaining = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AudioBroadcaster for streaming audio recordings to a remote streaming audio server. Audio recordings are
|
* AudioBroadcaster for streaming audio recordings to a remote streaming audio server. Audio recordings are
|
||||||
* generated by an internal StreamManager that converts an inbound stream of AudioPackets into a recording of the
|
* generated by an internal StreamManager that converts an inbound stream of AudioPackets into a recording of the
|
||||||
@@ -89,7 +93,7 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
/**
|
/**
|
||||||
* Broadcast binary audio data frames or sequences.
|
* Broadcast binary audio data frames or sequences.
|
||||||
*/
|
*/
|
||||||
protected abstract void broadcastAudio(byte[] audio);
|
protected abstract void broadcastAudio(byte[] audio, IdentifierCollection identifierCollection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol-specific metadata updater
|
* Protocol-specific metadata updater
|
||||||
@@ -205,13 +209,15 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
|
|
||||||
super.setBroadcastState(state);
|
super.setBroadcastState(state);
|
||||||
|
|
||||||
if(mBroadcastState.get() instanceof BroadcastState && ((BroadcastState)mBroadcastState.get()).isErrorState())
|
if(mBroadcastState.get() != null && mBroadcastState.get().isErrorState())
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!connected())
|
if(!connected())
|
||||||
{
|
{
|
||||||
|
//Reset inline metadata
|
||||||
|
mInlineRemaining = -1;
|
||||||
//Remove all pending audio recordings
|
//Remove all pending audio recordings
|
||||||
while(!mAudioRecordingQueue.isEmpty())
|
while(!mAudioRecordingQueue.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -265,9 +271,9 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
{
|
{
|
||||||
private AtomicBoolean mProcessing = new AtomicBoolean();
|
private AtomicBoolean mProcessing = new AtomicBoolean();
|
||||||
private ByteArrayInputStream mInputStream;
|
private ByteArrayInputStream mInputStream;
|
||||||
|
private IdentifierCollection mInputIdentifierCollection;
|
||||||
private long mFinalSilencePadding = 0;
|
private long mFinalSilencePadding = 0;
|
||||||
private int mBytesStreamedActual = 0;
|
private int mBytesToStreamPerInterval = 0;
|
||||||
private int mBytesStreamedRequired = 0;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
@@ -278,51 +284,44 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
{
|
{
|
||||||
if(mInputStream == null || mInputStream.available() <= 0)
|
if(mInputStream == null || mInputStream.available() <= 0)
|
||||||
{
|
{
|
||||||
if(mFinalSilencePadding > 0)
|
|
||||||
{
|
|
||||||
List<byte[]> finalSilence = mSilenceGenerator.generate(mFinalSilencePadding);
|
|
||||||
|
|
||||||
for(byte[] silence: finalSilence)
|
|
||||||
{
|
|
||||||
broadcastAudio(silence);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFinalSilencePadding = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextRecording();
|
nextRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mInputStream != null)
|
if(mInputStream != null)
|
||||||
{
|
{
|
||||||
//We need to stream at 13.888 fps (144 byte frame) to achieve 2000 Bps or 16 kbps
|
int length = FastMath.min(mBytesToStreamPerInterval, mInputStream.available());
|
||||||
mBytesStreamedRequired += 2000; //2000 bytes per second for 16 kbps data rate
|
|
||||||
int bytesToStream = mBytesStreamedRequired - mBytesStreamedActual;
|
|
||||||
|
|
||||||
//Trim length to whole-frame intervals (144 byte frame)
|
|
||||||
bytesToStream -= (bytesToStream % 144);
|
|
||||||
|
|
||||||
int length = FastMath.min(bytesToStream, mInputStream.available());
|
|
||||||
|
|
||||||
byte[] audio = new byte[length];
|
byte[] audio = new byte[length];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mBytesStreamedActual += mInputStream.read(audio);
|
int read = mInputStream.read(audio);
|
||||||
|
broadcastAudio(audio, mInputIdentifierCollection);
|
||||||
broadcastAudio(audio);
|
|
||||||
}
|
}
|
||||||
catch(IOException ioe)
|
catch(IOException ioe)
|
||||||
{
|
{
|
||||||
mLog.error("Error reading from in-memory audio recording input stream", ioe);
|
mLog.error("Error reading from in-memory audio recording input stream", ioe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If this is the final frame fragment then append silence padding to fill the final interval segment
|
||||||
|
if(length < mBytesToStreamPerInterval && mFinalSilencePadding > 0)
|
||||||
|
{
|
||||||
|
List<byte[]> finalSilence = mSilenceGenerator.generate(mFinalSilencePadding);
|
||||||
|
|
||||||
|
for(byte[] silence: finalSilence)
|
||||||
|
{
|
||||||
|
broadcastAudio(silence, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
mFinalSilencePadding = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<byte[]> silenceFrames = mSilenceGenerator.generate(PROCESSOR_RUN_INTERVAL_MS);
|
List<byte[]> silenceFrames = mSilenceGenerator.generate(PROCESSOR_RUN_INTERVAL_MS);
|
||||||
for(byte[] silence: silenceFrames)
|
for(byte[] silence: silenceFrames)
|
||||||
{
|
{
|
||||||
broadcastAudio(silence);
|
broadcastAudio(silence, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,9 +339,6 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
*/
|
*/
|
||||||
private void nextRecording()
|
private void nextRecording()
|
||||||
{
|
{
|
||||||
mBytesStreamedActual = 0;
|
|
||||||
mBytesStreamedRequired = 0;
|
|
||||||
|
|
||||||
boolean metadataUpdateRequired = false;
|
boolean metadataUpdateRequired = false;
|
||||||
|
|
||||||
if(mInputStream != null)
|
if(mInputStream != null)
|
||||||
@@ -354,6 +350,7 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
}
|
}
|
||||||
|
|
||||||
mInputStream = null;
|
mInputStream = null;
|
||||||
|
mInputIdentifierCollection = null;
|
||||||
|
|
||||||
//Peek at the next recording but don't remove it from the queue yet, so we can inspect the start time for
|
//Peek at the next recording but don't remove it from the queue yet, so we can inspect the start time for
|
||||||
//age limits and/or delay elapsed
|
//age limits and/or delay elapsed
|
||||||
@@ -381,9 +378,14 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
{
|
{
|
||||||
byte[] audio = Files.readAllBytes(nextRecording.getPath());
|
byte[] audio = Files.readAllBytes(nextRecording.getPath());
|
||||||
|
|
||||||
if(audio != null && audio.length > 0)
|
if(audio.length > 0)
|
||||||
{
|
{
|
||||||
|
//Calculate how many bytes we'll send with each processor run interval
|
||||||
|
double intervals = (double)nextRecording.getRecordingLength() / (double)PROCESSOR_RUN_INTERVAL_MS;
|
||||||
|
mBytesToStreamPerInterval = (int)((double)audio.length / intervals);
|
||||||
|
|
||||||
mInputStream = new ByteArrayInputStream(audio);
|
mInputStream = new ByteArrayInputStream(audio);
|
||||||
|
mInputIdentifierCollection = nextRecording.getIdentifierCollection();
|
||||||
|
|
||||||
mFinalSilencePadding = PROCESSOR_RUN_INTERVAL_MS -
|
mFinalSilencePadding = PROCESSOR_RUN_INTERVAL_MS -
|
||||||
(nextRecording.getRecordingLength() % PROCESSOR_RUN_INTERVAL_MS);
|
(nextRecording.getRecordingLength() % PROCESSOR_RUN_INTERVAL_MS);
|
||||||
@@ -408,6 +410,7 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
"stream recording [" + nextRecording.getPath().toString() + "] - skipping recording - ", ioe);
|
"stream recording [" + nextRecording.getPath().toString() + "] - skipping recording - ", ioe);
|
||||||
|
|
||||||
mInputStream = null;
|
mInputStream = null;
|
||||||
|
mInputIdentifierCollection = null;
|
||||||
metadataUpdateRequired = false;
|
metadataUpdateRequired = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.audio.broadcast;
|
package io.github.dsheirer.audio.broadcast;
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,8 @@ import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1AudioBroadcast
|
|||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2AudioStreamingBroadcaster;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2AudioStreamingBroadcaster;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
|
||||||
import io.github.dsheirer.audio.convert.IAudioConverter;
|
|
||||||
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
||||||
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
|
import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
@@ -88,26 +86,6 @@ public class BroadcastFactory
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an audio convert to convert from 8 kHz PCM audio to the specified format
|
|
||||||
*
|
|
||||||
* @param configuration containing the requested output audio format
|
|
||||||
* @return audio convert or null
|
|
||||||
*/
|
|
||||||
public static IAudioConverter getAudioConverter(BroadcastConfiguration configuration, InputAudioFormat inputAudioFormat,
|
|
||||||
MP3Setting mp3Setting)
|
|
||||||
{
|
|
||||||
switch(configuration.getBroadcastFormat())
|
|
||||||
{
|
|
||||||
case MP3:
|
|
||||||
return new MP3AudioConverter(inputAudioFormat, mp3Setting);
|
|
||||||
default:
|
|
||||||
mLog.info("Unrecognized broadcastAudio format: " + configuration.getBroadcastFormat().name());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a broadcastAudio configuration for the specified server type and format
|
* Creates a broadcastAudio configuration for the specified server type and format
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.audio.broadcast;
|
package io.github.dsheirer.audio.broadcast;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
private static final String MULTIPART_TYPE = "multipart";
|
private static final String MULTIPART_TYPE = "multipart";
|
||||||
private static final String DEFAULT_SUBTYPE = "form-data";
|
private static final String DEFAULT_SUBTYPE = "form-data";
|
||||||
private static final String MULTIPART_FORM_DATA = MULTIPART_TYPE + "/" + DEFAULT_SUBTYPE;
|
private static final String MULTIPART_FORM_DATA = MULTIPART_TYPE + "/" + DEFAULT_SUBTYPE;
|
||||||
|
private ScheduledFuture<?> mBroadcastifyTestFuture;
|
||||||
private Queue<AudioRecording> mAudioRecordingQueue = new LinkedTransferQueue<>();
|
private Queue<AudioRecording> mAudioRecordingQueue = new LinkedTransferQueue<>();
|
||||||
private ScheduledFuture<?> mAudioRecordingProcessorFuture;
|
private ScheduledFuture<?> mAudioRecordingProcessorFuture;
|
||||||
private HttpClient mHttpClient = HttpClient.newBuilder()
|
private HttpClient mHttpClient = HttpClient.newBuilder()
|
||||||
@@ -109,6 +110,12 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
setBroadcastState(BroadcastState.ERROR);
|
setBroadcastState(BroadcastState.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mBroadcastifyTestFuture == null && getBroadcastConfiguration().isTestEnabled())
|
||||||
|
{
|
||||||
|
// Test periodically so we don't get marked offline due to radio inactivity
|
||||||
|
mBroadcastifyTestFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BroadcastifyCallTest(), getBroadcastConfiguration().getTestInterval(), getBroadcastConfiguration().getTestInterval(), TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
if(mAudioRecordingProcessorFuture == null)
|
if(mAudioRecordingProcessorFuture == null)
|
||||||
{
|
{
|
||||||
mAudioRecordingProcessorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new AudioRecordingProcessor(),
|
mAudioRecordingProcessorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new AudioRecordingProcessor(),
|
||||||
@@ -122,6 +129,11 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
@Override
|
@Override
|
||||||
public void stop()
|
public void stop()
|
||||||
{
|
{
|
||||||
|
if(mBroadcastifyTestFuture != null)
|
||||||
|
{
|
||||||
|
mBroadcastifyTestFuture.cancel(true);
|
||||||
|
mBroadcastifyTestFuture = null;
|
||||||
|
}
|
||||||
if(mAudioRecordingProcessorFuture != null)
|
if(mAudioRecordingProcessorFuture != null)
|
||||||
{
|
{
|
||||||
mAudioRecordingProcessorFuture.cancel(true);
|
mAudioRecordingProcessorFuture.cancel(true);
|
||||||
@@ -131,6 +143,23 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BroadcastifyCallTest implements Runnable
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
String response = testConnection(getBroadcastConfiguration());
|
||||||
|
if(response != null && response.toLowerCase().startsWith("ok"))
|
||||||
|
{
|
||||||
|
mLog.info("Broadcastify Calls keep-alive success");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLog.info("Broadcastify Calls keep-alive failure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares for disposal
|
* Prepares for disposal
|
||||||
*/
|
*/
|
||||||
@@ -418,28 +447,20 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
*/
|
*/
|
||||||
private static String getTo(AudioRecording audioRecording)
|
private static String getTo(AudioRecording audioRecording)
|
||||||
{
|
{
|
||||||
List<Identifier> toIdentifiers = audioRecording.getIdentifierCollection().getIdentifiers(Role.TO);
|
Identifier identifier = audioRecording.getIdentifierCollection().getToIdentifier();
|
||||||
|
|
||||||
//Format a patch group first, if there are multiples
|
if(identifier instanceof PatchGroupIdentifier patchGroupIdentifier)
|
||||||
for(Identifier identifier: toIdentifiers)
|
|
||||||
{
|
{
|
||||||
if(identifier instanceof PatchGroupIdentifier patchGroupIdentifier)
|
return format(patchGroupIdentifier);
|
||||||
{
|
|
||||||
return format(patchGroupIdentifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if(identifier instanceof TalkgroupIdentifier talkgroupIdentifier)
|
||||||
for(Identifier identifier: toIdentifiers)
|
|
||||||
{
|
{
|
||||||
if(identifier instanceof TalkgroupIdentifier talkgroupIdentifier)
|
return String.valueOf(RadioReferenceDecoder.convertToRadioReferenceTalkgroup(talkgroupIdentifier.getValue(),
|
||||||
{
|
talkgroupIdentifier.getProtocol()));
|
||||||
return String.valueOf(RadioReferenceDecoder.convertToRadioReferenceTalkgroup(talkgroupIdentifier.getValue(),
|
}
|
||||||
talkgroupIdentifier.getProtocol()));
|
else if(identifier instanceof RadioIdentifier radioIdentifier)
|
||||||
}
|
{
|
||||||
else if(identifier instanceof RadioIdentifier radioIdentifier)
|
return radioIdentifier.getValue().toString();
|
||||||
{
|
|
||||||
return radioIdentifier.getValue().toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "0";
|
return "0";
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
|||||||
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.IntegerProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
@@ -42,6 +44,8 @@ public class BroadcastifyCallConfiguration extends BroadcastConfiguration
|
|||||||
|
|
||||||
private IntegerProperty mSystemID = new SimpleIntegerProperty();
|
private IntegerProperty mSystemID = new SimpleIntegerProperty();
|
||||||
private StringProperty mApiKey = new SimpleStringProperty();
|
private StringProperty mApiKey = new SimpleStringProperty();
|
||||||
|
private BooleanProperty mTestEnabled= new SimpleBooleanProperty(false);
|
||||||
|
private IntegerProperty mTestInterval = new SimpleIntegerProperty(15);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for faster jackson
|
* Constructor for faster jackson
|
||||||
@@ -128,6 +132,34 @@ public class BroadcastifyCallConfiguration extends BroadcastConfiguration
|
|||||||
return BroadcastServerType.BROADCASTIFY_CALL;
|
return BroadcastServerType.BROADCASTIFY_CALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this instance should schedule tests after connecting
|
||||||
|
*/
|
||||||
|
@JacksonXmlProperty(isAttribute = true, localName = "test_enabled")
|
||||||
|
public boolean isTestEnabled()
|
||||||
|
{
|
||||||
|
return mTestEnabled.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestEnabled(boolean enabled)
|
||||||
|
{
|
||||||
|
mTestEnabled.set(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the interval at which tests should be performed while enabled
|
||||||
|
*/
|
||||||
|
@JacksonXmlProperty(isAttribute = true, localName = "test_interval")
|
||||||
|
public int getTestInterval()
|
||||||
|
{
|
||||||
|
return mTestInterval.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestInterval(int interval)
|
||||||
|
{
|
||||||
|
mTestInterval.set(interval);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BroadcastConfiguration copyOf()
|
public BroadcastConfiguration copyOf()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public class BroadcastifyFeedConfiguration extends IcecastTCPConfiguration
|
|||||||
setBitRate(16);
|
setBitRate(16);
|
||||||
setChannels(1);
|
setChannels(1);
|
||||||
setSampleRate(8000);
|
setSampleRate(8000);
|
||||||
|
setInline(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BroadcastifyFeedConfiguration from(UserFeedBroadcast userFeedBroadcast)
|
public static BroadcastifyFeedConfiguration from(UserFeedBroadcast userFeedBroadcast)
|
||||||
@@ -86,9 +87,9 @@ public class BroadcastifyFeedConfiguration extends IcecastTCPConfiguration
|
|||||||
copy.setName(getName());
|
copy.setName(getName());
|
||||||
copy.setHost(getHost());
|
copy.setHost(getHost());
|
||||||
copy.setPort(getPort());
|
copy.setPort(getPort());
|
||||||
|
copy.setInline(getInline());
|
||||||
copy.setPassword(getPassword());
|
copy.setPassword(getPassword());
|
||||||
copy.setDelay(getDelay());
|
copy.setDelay(getDelay());
|
||||||
|
|
||||||
copy.setEnabled(false);
|
copy.setEnabled(false);
|
||||||
|
|
||||||
//Icecast Configuration Parameters
|
//Icecast Configuration Parameters
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import io.github.dsheirer.audio.convert.MP3Setting;
|
|||||||
public abstract class IcecastAudioBroadcaster extends AudioStreamingBroadcaster
|
public abstract class IcecastAudioBroadcaster extends AudioStreamingBroadcaster
|
||||||
{
|
{
|
||||||
private IBroadcastMetadataUpdater mMetadataUpdater;
|
private IBroadcastMetadataUpdater mMetadataUpdater;
|
||||||
private AliasModel mAliasModel;
|
protected AliasModel mAliasModel;
|
||||||
|
|
||||||
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, InputAudioFormat inputAudioFormat,
|
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import io.github.dsheirer.alias.Alias;
|
|||||||
import io.github.dsheirer.alias.AliasList;
|
import io.github.dsheirer.alias.AliasList;
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||||
|
import io.github.dsheirer.audio.broadcast.icecast.IcecastConfiguration;
|
||||||
|
import io.github.dsheirer.audio.broadcast.icecast.IcecastMetadata;
|
||||||
import io.github.dsheirer.identifier.Form;
|
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;
|
||||||
@@ -73,6 +75,12 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
|||||||
*/
|
*/
|
||||||
public void update(IdentifierCollection identifierCollection)
|
public void update(IdentifierCollection identifierCollection)
|
||||||
{
|
{
|
||||||
|
if(mIcecastConfiguration.hasInline())
|
||||||
|
{
|
||||||
|
// Never send out-of-band metadata if inline metadata is enabled.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -84,7 +92,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
|||||||
sb.append("/admin/metadata?mode=updinfo&mount=");
|
sb.append("/admin/metadata?mode=updinfo&mount=");
|
||||||
sb.append(URLEncoder.encode(mIcecastConfiguration.getMountPoint(), UTF8));
|
sb.append(URLEncoder.encode(mIcecastConfiguration.getMountPoint(), UTF8));
|
||||||
sb.append("&charset=UTF%2d8");
|
sb.append("&charset=UTF%2d8");
|
||||||
sb.append("&song=").append(URLEncoder.encode(getSong(identifierCollection), UTF8));
|
sb.append("&song=").append(URLEncoder.encode(IcecastMetadata.getTitle(identifierCollection, mAliasModel), UTF8));
|
||||||
}
|
}
|
||||||
catch(UnsupportedEncodingException uee)
|
catch(UnsupportedEncodingException uee)
|
||||||
{
|
{
|
||||||
@@ -157,82 +165,4 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the song information for a metadata update
|
|
||||||
*/
|
|
||||||
private String getSong(IdentifierCollection identifierCollection)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
if(identifierCollection != null)
|
|
||||||
{
|
|
||||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
|
||||||
|
|
||||||
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
|
||||||
|
|
||||||
if(to == null)
|
|
||||||
{
|
|
||||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(to == null)
|
|
||||||
{
|
|
||||||
List<Identifier> toIdentifiers = identifierCollection.getIdentifiers(Role.TO);
|
|
||||||
if(!toIdentifiers.isEmpty())
|
|
||||||
{
|
|
||||||
to = toIdentifiers.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(to != null)
|
|
||||||
{
|
|
||||||
sb.append("TO:").append(to);
|
|
||||||
|
|
||||||
List<Alias> aliases = aliasList.getAliases(to);
|
|
||||||
|
|
||||||
if(aliases != null && !aliases.isEmpty())
|
|
||||||
{
|
|
||||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append("TO:UNKNOWN");
|
|
||||||
}
|
|
||||||
|
|
||||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.RADIO, Role.FROM);
|
|
||||||
|
|
||||||
if(from == null)
|
|
||||||
{
|
|
||||||
List<Identifier> fromIdentifiers = identifierCollection.getIdentifiers(Role.FROM);
|
|
||||||
|
|
||||||
if(!fromIdentifiers.isEmpty())
|
|
||||||
{
|
|
||||||
from = fromIdentifiers.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(from != null)
|
|
||||||
{
|
|
||||||
sb.append(" FROM:").append(from);
|
|
||||||
|
|
||||||
List<Alias> aliases = aliasList.getAliases(from);
|
|
||||||
|
|
||||||
if(aliases != null && !aliases.isEmpty())
|
|
||||||
{
|
|
||||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append(" FROM:UNKNOWN");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.append("Scanning ....");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public abstract class IcecastConfiguration extends BroadcastConfiguration
|
|||||||
private int mChannels = 1;
|
private int mChannels = 1;
|
||||||
private int mSampleRate = 8000;
|
private int mSampleRate = 8000;
|
||||||
private String mURL;
|
private String mURL;
|
||||||
|
private boolean mInline = true;
|
||||||
|
|
||||||
public IcecastConfiguration(BroadcastFormat format)
|
public IcecastConfiguration(BroadcastFormat format)
|
||||||
{
|
{
|
||||||
@@ -275,6 +276,37 @@ public abstract class IcecastConfiguration extends BroadcastConfiguration
|
|||||||
return mURL != null;
|
return mURL != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control whether metadata is sent inline or out-of-band.
|
||||||
|
*/
|
||||||
|
@JacksonXmlProperty(isAttribute = true, localName = "inline")
|
||||||
|
public boolean getInline()
|
||||||
|
{
|
||||||
|
return mInline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public int getInlineInterval()
|
||||||
|
{
|
||||||
|
if (hasBitRate())
|
||||||
|
{
|
||||||
|
// Interval = BitRate * 1000 / 8 = 1 second
|
||||||
|
return getBitRate() * 125;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInline(boolean inline)
|
||||||
|
{
|
||||||
|
mInline = inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasInline()
|
||||||
|
{
|
||||||
|
// Bitrate must be known to calculate metadata interval
|
||||||
|
return mInline != false && hasBitRate();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid()
|
public boolean isValid()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ package io.github.dsheirer.audio.broadcast.icecast;
|
|||||||
|
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
|
import io.github.dsheirer.audio.broadcast.icecast.IcecastMetadata;
|
||||||
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
import io.github.dsheirer.properties.SystemProperties;
|
import io.github.dsheirer.properties.SystemProperties;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import org.apache.mina.core.RuntimeIoException;
|
import org.apache.mina.core.RuntimeIoException;
|
||||||
@@ -42,6 +44,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@@ -80,14 +83,41 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
* Broadcasts the audio frame or sequence
|
* Broadcasts the audio frame or sequence
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void broadcastAudio(byte[] audio)
|
protected void broadcastAudio(byte[] audio, IdentifierCollection identifierCollection)
|
||||||
{
|
{
|
||||||
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
||||||
{
|
{
|
||||||
IoBuffer buffer = IoBuffer.allocate(audio.length);
|
IoBuffer buffer = IoBuffer.allocate(audio.length);
|
||||||
buffer.put(audio);
|
|
||||||
buffer.flip();
|
|
||||||
|
|
||||||
|
if(mInlineActive)
|
||||||
|
{
|
||||||
|
byte[] metadata = IcecastMetadata.formatInline(IcecastMetadata.getTitle(identifierCollection, mAliasModel)).getBytes();
|
||||||
|
buffer.setAutoExpand(true);
|
||||||
|
if (mInlineRemaining == -1)
|
||||||
|
{
|
||||||
|
mInlineRemaining = mInlineInterval;
|
||||||
|
}
|
||||||
|
int audioOffset = 0;
|
||||||
|
while(audioOffset < audio.length)
|
||||||
|
{
|
||||||
|
byte[] chunk = Arrays.copyOfRange(audio, audioOffset, Math.min(audioOffset + mInlineRemaining, audio.length));
|
||||||
|
mInlineRemaining -= chunk.length;
|
||||||
|
audioOffset += chunk.length;
|
||||||
|
buffer.put(chunk);
|
||||||
|
if(mInlineRemaining == 0)
|
||||||
|
{
|
||||||
|
mInlineRemaining = mInlineInterval;
|
||||||
|
buffer.put(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.shrink();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer.put(audio);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.flip();
|
||||||
mStreamingSession.write(buffer);
|
mStreamingSession.write(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +268,17 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
{
|
{
|
||||||
mHTTPHeaders.put(IcecastHeader.BITRATE.getValue(), String.valueOf(getConfiguration().getBitRate()));
|
mHTTPHeaders.put(IcecastHeader.BITRATE.getValue(), String.valueOf(getConfiguration().getBitRate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(getConfiguration().hasInline())
|
||||||
|
{
|
||||||
|
mInlineActive = true;
|
||||||
|
mInlineInterval = getConfiguration().getInlineInterval();
|
||||||
|
mHTTPHeaders.put(IcecastHeader.METAINT.getValue(), String.valueOf(mInlineInterval));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mInlineActive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mHTTPHeaders;
|
return mHTTPHeaders;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class IcecastHTTPConfiguration extends IcecastConfiguration
|
|||||||
copy.setName(getName());
|
copy.setName(getName());
|
||||||
copy.setHost(getHost());
|
copy.setHost(getHost());
|
||||||
copy.setPort(getPort());
|
copy.setPort(getPort());
|
||||||
|
copy.setInline(getInline());
|
||||||
copy.setPassword(getPassword());
|
copy.setPassword(getPassword());
|
||||||
copy.setDelay(getDelay());
|
copy.setDelay(getDelay());
|
||||||
copy.setEnabled(false);
|
copy.setEnabled(false);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public enum IcecastHeader
|
|||||||
PUBLIC("ice-public"),
|
PUBLIC("ice-public"),
|
||||||
URL("ice-url"),
|
URL("ice-url"),
|
||||||
USER_AGENT("User-Agent"),
|
USER_AGENT("User-Agent"),
|
||||||
|
METAINT("icy-metaint"),
|
||||||
|
|
||||||
UNKNOWN("unknown");
|
UNKNOWN("unknown");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * ******************************************************************************
|
||||||
|
* * Copyright (C) 2014-2020 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.broadcast.icecast;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import io.github.dsheirer.alias.Alias;
|
||||||
|
import io.github.dsheirer.alias.AliasList;
|
||||||
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
|
import io.github.dsheirer.audio.broadcast.icecast.IcecastConfiguration;
|
||||||
|
import io.github.dsheirer.identifier.Form;
|
||||||
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
|
import io.github.dsheirer.identifier.IdentifierClass;
|
||||||
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
|
import io.github.dsheirer.identifier.Role;
|
||||||
|
import io.github.dsheirer.properties.SystemProperties;
|
||||||
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IcecastMetadata
|
||||||
|
{
|
||||||
|
private final static Logger mLog = LoggerFactory.getLogger(IcecastMetadata.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the title for a metadata update
|
||||||
|
*/
|
||||||
|
public static String getTitle(IdentifierCollection identifierCollection, AliasModel AliasModel)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if(identifierCollection != null)
|
||||||
|
{
|
||||||
|
AliasList aliasList = AliasModel.getAliasList(identifierCollection);
|
||||||
|
|
||||||
|
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
||||||
|
|
||||||
|
if(to == null)
|
||||||
|
{
|
||||||
|
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(to == null)
|
||||||
|
{
|
||||||
|
List<Identifier> toIdentifiers = identifierCollection.getIdentifiers(Role.TO);
|
||||||
|
if(!toIdentifiers.isEmpty())
|
||||||
|
{
|
||||||
|
to = toIdentifiers.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(to != null)
|
||||||
|
{
|
||||||
|
sb.append("TO:").append(to);
|
||||||
|
|
||||||
|
List<Alias> aliases = aliasList.getAliases(to);
|
||||||
|
|
||||||
|
if(aliases != null && !aliases.isEmpty())
|
||||||
|
{
|
||||||
|
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("TO:UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
|
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.RADIO, Role.FROM);
|
||||||
|
|
||||||
|
if(from == null)
|
||||||
|
{
|
||||||
|
List<Identifier> fromIdentifiers = identifierCollection.getIdentifiers(Role.FROM);
|
||||||
|
|
||||||
|
if(!fromIdentifiers.isEmpty())
|
||||||
|
{
|
||||||
|
from = fromIdentifiers.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(from != null)
|
||||||
|
{
|
||||||
|
sb.append(" FROM:").append(from);
|
||||||
|
|
||||||
|
List<Alias> aliases = aliasList.getAliases(from);
|
||||||
|
|
||||||
|
if(aliases != null && !aliases.isEmpty())
|
||||||
|
{
|
||||||
|
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(" FROM:UNKNOWN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("Scanning...");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatInline(String title)
|
||||||
|
{
|
||||||
|
title = "StreamTitle='" + title + "';";
|
||||||
|
int chunks = (int)Math.ceil((title.length() + 1) / 16.0d);
|
||||||
|
int nulls = (chunks * 16) - title.length();
|
||||||
|
char[] padding = new char[nulls];
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append((char)chunks).append(title).append(padding);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,9 +21,11 @@ package io.github.dsheirer.audio.broadcast.icecast;
|
|||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
|
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
|
||||||
|
import io.github.dsheirer.audio.broadcast.icecast.IcecastMetadata;
|
||||||
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
import io.github.dsheirer.properties.SystemProperties;
|
import io.github.dsheirer.properties.SystemProperties;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import org.apache.mina.core.RuntimeIoException;
|
import org.apache.mina.core.RuntimeIoException;
|
||||||
@@ -39,13 +41,14 @@ import java.io.IOException;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.nio.channels.UnresolvedAddressException;
|
import java.nio.channels.UnresolvedAddressException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(IcecastTCPAudioBroadcaster.class);
|
private final static Logger mLog = LoggerFactory.getLogger(IcecastTCPAudioBroadcaster.class);
|
||||||
private final static String TERMINATOR = "\r\n";
|
private final static String TERMINATOR = "\n";
|
||||||
private final static String SEPARATOR = ":";
|
private final static String SEPARATOR = ":";
|
||||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 3000; //3 seconds
|
private static final long RECONNECT_INTERVAL_MILLISECONDS = 3000; //3 seconds
|
||||||
private static final long CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS = 5000; //5 seconds
|
private static final long CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS = 5000; //5 seconds
|
||||||
@@ -78,11 +81,35 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
* Broadcasts the audio frame or sequence
|
* Broadcasts the audio frame or sequence
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void broadcastAudio(byte[] audio)
|
protected void broadcastAudio(byte[] audio, IdentifierCollection identifierCollection)
|
||||||
{
|
{
|
||||||
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
||||||
{
|
{
|
||||||
mStreamingSession.write(audio);
|
if(mInlineActive)
|
||||||
|
{
|
||||||
|
byte[] metadata = IcecastMetadata.formatInline(IcecastMetadata.getTitle(identifierCollection, mAliasModel)).getBytes();
|
||||||
|
if (mInlineRemaining == -1)
|
||||||
|
{
|
||||||
|
mInlineRemaining = mInlineInterval;
|
||||||
|
}
|
||||||
|
int audioOffset = 0;
|
||||||
|
while(audioOffset < audio.length)
|
||||||
|
{
|
||||||
|
byte[] chunk = Arrays.copyOfRange(audio, audioOffset, Math.min(audioOffset + mInlineRemaining, audio.length));
|
||||||
|
mInlineRemaining -= chunk.length;
|
||||||
|
audioOffset += chunk.length;
|
||||||
|
mStreamingSession.write(chunk);
|
||||||
|
if(mInlineRemaining == 0)
|
||||||
|
{
|
||||||
|
mInlineRemaining = mInlineInterval;
|
||||||
|
mStreamingSession.write(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mStreamingSession.write(audio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +265,18 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
.append(getConfiguration().getDescription()).append(TERMINATOR);
|
.append(getConfiguration().getDescription()).append(TERMINATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(TERMINATOR).append(TERMINATOR);
|
if(getConfiguration().hasInline())
|
||||||
|
{
|
||||||
|
mInlineActive = true;
|
||||||
|
mInlineInterval = getConfiguration().getInlineInterval();
|
||||||
|
sb.append(IcecastHeader.METAINT.getValue()).append(SEPARATOR)
|
||||||
|
.append(String.valueOf(mInlineInterval))
|
||||||
|
.append(TERMINATOR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mInlineActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
session.write(sb.toString());
|
session.write(sb.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class IcecastTCPConfiguration extends IcecastConfiguration
|
|||||||
copy.setName(getName());
|
copy.setName(getName());
|
||||||
copy.setHost(getHost());
|
copy.setHost(getHost());
|
||||||
copy.setPort(getPort());
|
copy.setPort(getPort());
|
||||||
|
copy.setInline(getInline());
|
||||||
copy.setPassword(getPassword());
|
copy.setPassword(getPassword());
|
||||||
copy.setDelay(getDelay());
|
copy.setDelay(getDelay());
|
||||||
copy.setEnabled(false);
|
copy.setEnabled(false);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.audio.broadcast.icecast.codec;
|
package io.github.dsheirer.audio.broadcast.icecast.codec;
|
||||||
|
|
||||||
import org.apache.mina.core.buffer.IoBuffer;
|
import org.apache.mina.core.buffer.IoBuffer;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import io.github.dsheirer.audio.broadcast.BroadcastState;
|
|||||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||||
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import org.apache.mina.core.RuntimeIoException;
|
import org.apache.mina.core.RuntimeIoException;
|
||||||
import org.apache.mina.core.buffer.IoBuffer;
|
import org.apache.mina.core.buffer.IoBuffer;
|
||||||
@@ -93,7 +94,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioStreamingBroadcaster
|
|||||||
* Broadcasts the audio frame or sequence
|
* Broadcasts the audio frame or sequence
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void broadcastAudio(byte[] audio)
|
protected void broadcastAudio(byte[] audio, IdentifierCollection identifierCollection)
|
||||||
{
|
{
|
||||||
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
if(audio != null && audio.length > 0 && connect() && mStreamingSession != null && mStreamingSession.isConnected())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public class ShoutcastV2AudioStreamingBroadcaster extends AudioStreamingBroadcas
|
|||||||
* Broadcasts the audio frame or sequence
|
* Broadcasts the audio frame or sequence
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void broadcastAudio(byte[] audio)
|
protected void broadcastAudio(byte[] audio, IdentifierCollection identifierCollection)
|
||||||
{
|
{
|
||||||
//Dispatch any queued metadata messages
|
//Dispatch any queued metadata messages
|
||||||
UltravoxMessage metadataMessage = mMetadataMessageQueue.poll();
|
UltravoxMessage metadataMessage = mMetadataMessageQueue.poll();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
||||||
|
|
||||||
import io.github.dsheirer.bits.BinaryMessage;
|
import io.github.dsheirer.bits.BinaryMessage;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
package io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox;
|
||||||
|
|
||||||
public class UltravoxMessageFactory
|
public class UltravoxMessageFactory
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2021 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -18,19 +18,19 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.dsheirer.audio.convert;
|
package io.github.dsheirer.audio.convert;
|
||||||
|
|
||||||
|
import io.github.dsheirer.audio.AudioUtils;
|
||||||
import io.github.dsheirer.dsp.filter.resample.RealResampler;
|
import io.github.dsheirer.dsp.filter.resample.RealResampler;
|
||||||
import io.github.dsheirer.sample.ConversionUtils;
|
import io.github.dsheirer.sample.ConversionUtils;
|
||||||
import net.sourceforge.lame.lowlevel.LameEncoder;
|
|
||||||
import net.sourceforge.lame.mp3.Lame;
|
|
||||||
import org.apache.commons.math3.util.FastMath;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.sourceforge.lame.lowlevel.LameEncoder;
|
||||||
|
import net.sourceforge.lame.mp3.Lame;
|
||||||
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts PCM audio packets to Mono, MP3 encoded audio
|
* Converts PCM audio packets to Mono, MP3 encoded audio
|
||||||
@@ -45,16 +45,20 @@ public class MP3AudioConverter implements IAudioConverter
|
|||||||
private byte[] mOutputFramesBuffer;
|
private byte[] mOutputFramesBuffer;
|
||||||
private InputAudioFormat mInputAudioFormat;
|
private InputAudioFormat mInputAudioFormat;
|
||||||
|
|
||||||
|
private boolean mNormalizeAudio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance.
|
* Constructs an instance.
|
||||||
*
|
*
|
||||||
* @param inputAudioFormat for the desired input sample rate and bit size (resampled from default 8 kHz as needed)
|
* @param inputAudioFormat for the desired input sample rate and bit size (resampled from default 8 kHz as needed)
|
||||||
* @param setting to configure the LAME encoder
|
* @param setting to configure the LAME encoder
|
||||||
|
* @param normalizeAudio to normalize the audio gain prior to encoding
|
||||||
*/
|
*/
|
||||||
public MP3AudioConverter(InputAudioFormat inputAudioFormat, MP3Setting setting)
|
public MP3AudioConverter(InputAudioFormat inputAudioFormat, MP3Setting setting, boolean normalizeAudio)
|
||||||
{
|
{
|
||||||
mInputAudioFormat = inputAudioFormat;
|
mInputAudioFormat = inputAudioFormat;
|
||||||
mEncoder = LameFactory.getLameEncoder(inputAudioFormat, setting);
|
mEncoder = LameFactory.getLameEncoder(inputAudioFormat, setting);
|
||||||
|
mNormalizeAudio = normalizeAudio;
|
||||||
|
|
||||||
//Resampling is only required if desired input sample rate is not system default of 8kHz
|
//Resampling is only required if desired input sample rate is not system default of 8kHz
|
||||||
if(inputAudioFormat != InputAudioFormat.SR_8000 && inputAudioFormat != InputAudioFormat.SR_32_8000)
|
if(inputAudioFormat != InputAudioFormat.SR_8000 && inputAudioFormat != InputAudioFormat.SR_32_8000)
|
||||||
@@ -74,6 +78,11 @@ public class MP3AudioConverter implements IAudioConverter
|
|||||||
{
|
{
|
||||||
List<byte[]> converted = new ArrayList<>();
|
List<byte[]> converted = new ArrayList<>();
|
||||||
|
|
||||||
|
if(mNormalizeAudio)
|
||||||
|
{
|
||||||
|
audioPackets = AudioUtils.normalize(audioPackets);
|
||||||
|
}
|
||||||
|
|
||||||
if(mResampler != null)
|
if(mResampler != null)
|
||||||
{
|
{
|
||||||
audioPackets = mResampler.resample(audioPackets);
|
audioPackets = mResampler.resample(audioPackets);
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ public enum MP3Setting
|
|||||||
CBR_16(false, 16, "CBR - Constant Bit Rate 16 kbps (default)"),
|
CBR_16(false, 16, "CBR - Constant Bit Rate 16 kbps (default)"),
|
||||||
CBR_32(false, 32, "CBR - Constant Bit Rate 32 kbps"),
|
CBR_32(false, 32, "CBR - Constant Bit Rate 32 kbps"),
|
||||||
ABR_56(true, 56, "ABR - Average Bit Rate 56 kbps"),
|
ABR_56(true, 56, "ABR - Average Bit Rate 56 kbps"),
|
||||||
VBR_5(true, Lame.QUALITY_MIDDLE, "VBR - Middle Quality (5)"),
|
VBR_5(true, Lame.QUALITY_MIDDLE, "VBR - Variable Bit Rate - Better Quality"),
|
||||||
VBR_7(true, Lame.QUALITY_LOW, "VBR - Low Quality (7)");
|
VBR_7(true, Lame.QUALITY_LOW, "VBR - Variable Bit Rate - Good Quality");
|
||||||
|
|
||||||
private boolean mVariableBitRate;
|
private boolean mVariableBitRate;
|
||||||
private int mSetting;
|
private int mSetting;
|
||||||
|
|||||||
@@ -18,11 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.dsheirer.audio.convert;
|
package io.github.dsheirer.audio.convert;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class MP3SilenceGenerator implements ISilenceGenerator
|
public class MP3SilenceGenerator implements ISilenceGenerator
|
||||||
{
|
{
|
||||||
@@ -40,7 +39,7 @@ public class MP3SilenceGenerator implements ISilenceGenerator
|
|||||||
public MP3SilenceGenerator(InputAudioFormat inputAudioFormat, MP3Setting setting)
|
public MP3SilenceGenerator(InputAudioFormat inputAudioFormat, MP3Setting setting)
|
||||||
{
|
{
|
||||||
mInputAudioFormat = inputAudioFormat;
|
mInputAudioFormat = inputAudioFormat;
|
||||||
mMP3AudioConverter = new MP3AudioConverter(inputAudioFormat, setting);
|
mMP3AudioConverter = new MP3AudioConverter(inputAudioFormat, setting, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.convert.thumbdv.message;
|
package io.github.dsheirer.audio.convert.thumbdv.message;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.convert.thumbdv.message.response;
|
package io.github.dsheirer.audio.convert.thumbdv.message.response;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ******************************************************************************
|
* *****************************************************************************
|
||||||
* sdrtrunk
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
* Copyright (C) 2014-2018 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
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
* *****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
package io.github.dsheirer.audio.playback;
|
package io.github.dsheirer.audio.playback;
|
||||||
|
|
||||||
@@ -30,7 +29,6 @@ import io.github.dsheirer.icon.IconModel;
|
|||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
|
||||||
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
|
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
|
||||||
import jiconfont.icons.font_awesome.FontAwesome;
|
import jiconfont.icons.font_awesome.FontAwesome;
|
||||||
import jiconfont.swing.IconFontSwing;
|
import jiconfont.swing.IconFontSwing;
|
||||||
@@ -69,7 +67,6 @@ public class AudioPanel extends JPanel implements Listener<AudioEvent>
|
|||||||
|
|
||||||
private IconModel mIconModel;
|
private IconModel mIconModel;
|
||||||
private SettingsManager mSettingsManager;
|
private SettingsManager mSettingsManager;
|
||||||
private SourceManager mSourceManager;
|
|
||||||
private IAudioController mController;
|
private IAudioController mController;
|
||||||
private AliasModel mAliasModel;
|
private AliasModel mAliasModel;
|
||||||
private UserPreferences mUserPreferences;
|
private UserPreferences mUserPreferences;
|
||||||
@@ -78,11 +75,10 @@ public class AudioPanel extends JPanel implements Listener<AudioEvent>
|
|||||||
private AudioChannelsPanel mAudioChannelsPanel;
|
private AudioChannelsPanel mAudioChannelsPanel;
|
||||||
|
|
||||||
public AudioPanel(IconModel iconModel, UserPreferences userPreferences, SettingsManager settingsManager,
|
public AudioPanel(IconModel iconModel, UserPreferences userPreferences, SettingsManager settingsManager,
|
||||||
SourceManager sourceManager, IAudioController controller, AliasModel aliasModel)
|
IAudioController controller, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
mIconModel = iconModel;
|
mIconModel = iconModel;
|
||||||
mSettingsManager = settingsManager;
|
mSettingsManager = settingsManager;
|
||||||
mSourceManager = sourceManager;
|
|
||||||
mController = controller;
|
mController = controller;
|
||||||
mAliasModel = aliasModel;
|
mAliasModel = aliasModel;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class BinaryMessage extends BitSet
|
|||||||
* Logical (ie constructed) size of this bitset, despite the actual size of
|
* Logical (ie constructed) size of this bitset, despite the actual size of
|
||||||
* the super bitset that this class is based on
|
* the super bitset that this class is based on
|
||||||
*/
|
*/
|
||||||
private int mSize = 0;
|
private int mSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the next fill index location, when adding bits to this bitset
|
* Pointer to the next fill index location, when adding bits to this bitset
|
||||||
@@ -43,21 +43,21 @@ public class BinaryMessage extends BitSet
|
|||||||
*/
|
*/
|
||||||
private int mPointer = 0;
|
private int mPointer = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Bitset that buffers bits added one at a time, up to the size of the this
|
|
||||||
* bitset.
|
|
||||||
*
|
|
||||||
* Note: the super class bitset behind this class may have a size larger
|
|
||||||
* that the size parameter specified.
|
|
||||||
* @param size
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for temporary storage of CRC check results when we're passing this
|
* Used for temporary storage of CRC check results when we're passing this
|
||||||
* message to an EDAC function.
|
* message to an EDAC function.
|
||||||
*/
|
*/
|
||||||
private CRC mCRC;
|
private CRC mCRC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitset that buffers bits added one at a time, up to the size
|
||||||
|
* of the this bitset.
|
||||||
|
* <p>
|
||||||
|
* Note: the super class bitset behind this class may have a size larger
|
||||||
|
* that the size parameter specified.
|
||||||
|
*
|
||||||
|
* @param size of constructed bitset
|
||||||
|
*/
|
||||||
public BinaryMessage(int size)
|
public BinaryMessage(int size)
|
||||||
{
|
{
|
||||||
super(size);
|
super(size);
|
||||||
@@ -214,9 +214,7 @@ public class BinaryMessage extends BitSet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a (new) copy of this bitsetbuffer
|
* @return a (new) copy of this binary message
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public BinaryMessage copy()
|
public BinaryMessage copy()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package io.github.dsheirer.buffer;
|
|||||||
|
|
||||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +41,7 @@ public class ByteNativeBuffer implements INativeBuffer
|
|||||||
|
|
||||||
for(int x = 0; x < 256; x++)
|
for(int x = 0; x < 256; x++)
|
||||||
{
|
{
|
||||||
LOOKUP_VALUES[x] = (float)(x - 127) / 128.0f;
|
LOOKUP_VALUES[x] = ((float)x - 127.5f) / 128.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,20 @@ import java.nio.ByteBuffer;
|
|||||||
*/
|
*/
|
||||||
public class ByteNativeBufferFactory implements INativeBufferFactory
|
public class ByteNativeBufferFactory implements INativeBufferFactory
|
||||||
{
|
{
|
||||||
private static final float DC_FILTER_GAIN = 0.007f; //Normalizes DC over period of ~142 (1 / .007) buffers
|
private DcCorrectionManager mDcCorrectionManager = new DcCorrectionManager();
|
||||||
private float mAverageDc = 0.0f;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public INativeBuffer getBuffer(ByteBuffer samples, long timestamp)
|
public INativeBuffer getBuffer(ByteBuffer samples, long timestamp)
|
||||||
{
|
{
|
||||||
byte[] copy = new byte[samples.capacity()];
|
byte[] copy = new byte[samples.capacity()];
|
||||||
samples.get(copy);
|
samples.get(copy);
|
||||||
calculateDc(copy);
|
|
||||||
return new ByteNativeBuffer(copy, timestamp, mAverageDc);
|
if(mDcCorrectionManager.shouldCalculateDc())
|
||||||
|
{
|
||||||
|
calculateDc(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ByteNativeBuffer(copy, timestamp, mDcCorrectionManager.getAverageDc());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +49,7 @@ public class ByteNativeBufferFactory implements INativeBufferFactory
|
|||||||
*/
|
*/
|
||||||
private void calculateDc(byte[] samples)
|
private void calculateDc(byte[] samples)
|
||||||
{
|
{
|
||||||
double dcAccumulator = 0;
|
float dcAccumulator = 0;
|
||||||
|
|
||||||
for(byte sample: samples)
|
for(byte sample: samples)
|
||||||
{
|
{
|
||||||
@@ -53,9 +57,8 @@ public class ByteNativeBufferFactory implements INativeBufferFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
dcAccumulator /= samples.length;
|
dcAccumulator /= samples.length;
|
||||||
dcAccumulator -= 127.0f;
|
dcAccumulator -= 127.5f;
|
||||||
dcAccumulator /= 128.0f;
|
dcAccumulator /= 128.0f;
|
||||||
dcAccumulator -= mAverageDc;
|
mDcCorrectionManager.adjust(dcAccumulator);
|
||||||
mAverageDc += (dcAccumulator * DC_FILTER_GAIN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* SDR Trunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
package io.github.dsheirer.buffer;
|
package io.github.dsheirer.buffer;
|
||||||
|
|
||||||
import io.github.dsheirer.sample.complex.Complex;
|
import io.github.dsheirer.sample.complex.Complex;
|
||||||
|
|||||||
114
src/main/java/io/github/dsheirer/buffer/DcCorrectionManager.java
Normal file
114
src/main/java/io/github/dsheirer/buffer/DcCorrectionManager.java
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* 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.buffer;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides DC offset correction value and manages calculation processing interval.
|
||||||
|
*/
|
||||||
|
public class DcCorrectionManager
|
||||||
|
{
|
||||||
|
// private static Logger mLog = LoggerFactory.getLogger(DcCorrectionManager.class);
|
||||||
|
// private DecimalFormat mDecimalFormat = new DecimalFormat("0.00000");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time (delay) interval for running DC removal calculations
|
||||||
|
*/
|
||||||
|
private static final long DC_PROCESSING_INTERVAL = TimeUnit.SECONDS.toMillis(50);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of buffers to process per DC calculation processing interval.
|
||||||
|
*/
|
||||||
|
private static final int DC_CALCULATIONS_PER_INTERVAL = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DC offset processing residual threshold for ending DC processing interval
|
||||||
|
*/
|
||||||
|
private static final float TARGET_DC_OFFSET_REMAINING = 0.0001f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of DC calculations remaining in the current interval
|
||||||
|
*/
|
||||||
|
private int mDcCalculationsRemaining = DC_CALCULATIONS_PER_INTERVAL; //Initial value for coarse correction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last time DC offset calculation interval ran
|
||||||
|
*/
|
||||||
|
private long mLastDcCalculationTimestamp = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DC offset calculation gain.
|
||||||
|
*/
|
||||||
|
private static final float DC_FILTER_GAIN = 0.05f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current DC offset correction value
|
||||||
|
*/
|
||||||
|
private float mAverageDc = 0.0f;
|
||||||
|
|
||||||
|
public float getAverageDc()
|
||||||
|
{
|
||||||
|
return mAverageDc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the average DC based on the current calculated DC offset present in a sample buffer.
|
||||||
|
* @param calculatedDc for the current sample buffer
|
||||||
|
*/
|
||||||
|
public void adjust(float calculatedDc)
|
||||||
|
{
|
||||||
|
//Calculate the average scaled DC offset so that it can be applied in the native buffer's converted samples
|
||||||
|
float residualOffsetToRemove = calculatedDc - mAverageDc;
|
||||||
|
|
||||||
|
mAverageDc += (residualOffsetToRemove * DC_FILTER_GAIN);
|
||||||
|
|
||||||
|
if(Math.abs(residualOffsetToRemove) < TARGET_DC_OFFSET_REMAINING)
|
||||||
|
{
|
||||||
|
mDcCalculationsRemaining--;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// mLog.info("DC: " + mDecimalFormat.format(mAverageDc) +
|
||||||
|
// " RES:" + mDecimalFormat.format(residualOffsetToRemove) +
|
||||||
|
// " REM:" + mDcCalculationsRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if a DC offset calculation for a buffer should be performed.
|
||||||
|
*/
|
||||||
|
public boolean shouldCalculateDc()
|
||||||
|
{
|
||||||
|
if(System.currentTimeMillis() > (mLastDcCalculationTimestamp + DC_PROCESSING_INTERVAL))
|
||||||
|
{
|
||||||
|
if(mDcCalculationsRemaining > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Reset the number of buffers to calculate and the timestamp
|
||||||
|
mDcCalculationsRemaining = DC_CALCULATIONS_PER_INTERVAL;
|
||||||
|
mLastDcCalculationTimestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2021 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.buffer;
|
package io.github.dsheirer.buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,14 +20,51 @@
|
|||||||
package io.github.dsheirer.buffer;
|
package io.github.dsheirer.buffer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements a factory for creating SignedByteNativeBuffer instances
|
* Implements a factory for creating SignedByteNativeBuffer instances
|
||||||
*/
|
*/
|
||||||
public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
||||||
{
|
{
|
||||||
private static final float DC_FILTER_GAIN = 0.02f; //Normalizes DC over period of ~50 (1 / .02) buffers
|
/**
|
||||||
|
* DC removal calculations will run once a minute
|
||||||
|
*/
|
||||||
|
private static final long DC_PROCESSING_INTERVAL = TimeUnit.SECONDS.toMillis(60);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of buffers to process per DC calculation processing interval.
|
||||||
|
*/
|
||||||
|
private static final int DC_CALCULATIONS_PER_INTERVAL = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DC offset processing residual threshold for ending DC processing interval
|
||||||
|
*/
|
||||||
|
private static final float TARGET_DC_OFFSET_REMAINING = 0.0002f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of DC calculations remaining in the current interval
|
||||||
|
*/
|
||||||
|
private int mDcCalculationsRemaining = DC_CALCULATIONS_PER_INTERVAL; //Initial value for coarse correction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last time DC offset calculation interval ran
|
||||||
|
*/
|
||||||
|
private long mLastDcCalculationTimestamp = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DC offset calculation gain.
|
||||||
|
*/
|
||||||
|
private static final float DC_FILTER_GAIN = 0.05f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current DC offset correction for Inphase samples
|
||||||
|
*/
|
||||||
private float mIAverageDc = 0.0f;
|
private float mIAverageDc = 0.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current DC offset correction for Quadrature samples
|
||||||
|
*/
|
||||||
private float mQAverageDc = 0.0f;
|
private float mQAverageDc = 0.0f;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,10 +72,37 @@ public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
|||||||
{
|
{
|
||||||
byte[] copy = new byte[samples.capacity()];
|
byte[] copy = new byte[samples.capacity()];
|
||||||
samples.get(copy);
|
samples.get(copy);
|
||||||
calculateDc(copy);
|
|
||||||
|
if(shouldCalculateDc())
|
||||||
|
{
|
||||||
|
calculateDc(copy);
|
||||||
|
}
|
||||||
|
|
||||||
return new SignedByteNativeBuffer(copy, timestamp, mIAverageDc, mQAverageDc);
|
return new SignedByteNativeBuffer(copy, timestamp, mIAverageDc, mQAverageDc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if a DC offset calculation for a buffer should be performed.
|
||||||
|
*/
|
||||||
|
private boolean shouldCalculateDc()
|
||||||
|
{
|
||||||
|
if(System.currentTimeMillis() > (mLastDcCalculationTimestamp + DC_PROCESSING_INTERVAL))
|
||||||
|
{
|
||||||
|
if(mDcCalculationsRemaining > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Reset the number of buffers to calculate and the timestamp
|
||||||
|
mDcCalculationsRemaining = DC_CALCULATIONS_PER_INTERVAL;
|
||||||
|
mLastDcCalculationTimestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the average DC in the sample stream so that it can be subtracted from the samples when the
|
* Calculates the average DC in the sample stream so that it can be subtracted from the samples when the
|
||||||
* native buffer is used.
|
* native buffer is used.
|
||||||
@@ -46,8 +110,8 @@ public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
|||||||
*/
|
*/
|
||||||
private void calculateDc(byte[] samples)
|
private void calculateDc(byte[] samples)
|
||||||
{
|
{
|
||||||
double iDcAccumulator = 0;
|
float iDcAccumulator = 0;
|
||||||
double qDcAccumulator = 0;
|
float qDcAccumulator = 0;
|
||||||
|
|
||||||
for(int x = 0; x < samples.length; x += 2)
|
for(int x = 0; x < samples.length; x += 2)
|
||||||
{
|
{
|
||||||
@@ -64,5 +128,10 @@ public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
|||||||
qDcAccumulator /= 128.0f;
|
qDcAccumulator /= 128.0f;
|
||||||
qDcAccumulator -= mQAverageDc;
|
qDcAccumulator -= mQAverageDc;
|
||||||
mQAverageDc += (qDcAccumulator * DC_FILTER_GAIN);
|
mQAverageDc += (qDcAccumulator * DC_FILTER_GAIN);
|
||||||
|
|
||||||
|
if(Math.abs(iDcAccumulator) < TARGET_DC_OFFSET_REMAINING && Math.abs(qDcAccumulator) < TARGET_DC_OFFSET_REMAINING)
|
||||||
|
{
|
||||||
|
mDcCalculationsRemaining--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.buffer.airspy;
|
package io.github.dsheirer.buffer.airspy;
|
||||||
|
|
||||||
|
import io.github.dsheirer.buffer.DcCorrectionManager;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,40 +27,61 @@ import java.nio.ByteBuffer;
|
|||||||
*/
|
*/
|
||||||
public class ScalarPackedSampleConverter implements IAirspySampleConverter
|
public class ScalarPackedSampleConverter implements IAirspySampleConverter
|
||||||
{
|
{
|
||||||
private static final float DC_FILTER_GAIN = 0.007f; //Normalizes DC over period of ~142 (1 / .007) buffers
|
/**
|
||||||
private float mAverageDc = 0.0f;
|
* Manages DC calculations and processing interval
|
||||||
|
*/
|
||||||
|
private DcCorrectionManager mDcCalculationManager = new DcCorrectionManager();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short[] convert(ByteBuffer buffer)
|
public short[] convert(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
|
boolean shouldCalculateDc = mDcCalculationManager.shouldCalculateDc();
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
long dcAccumulator = 0;
|
|
||||||
short sample;
|
short sample;
|
||||||
short[] samples;
|
short[] samples;
|
||||||
byte b1, b2, b3;
|
byte b1, b2, b3;
|
||||||
|
|
||||||
samples = new short[buffer.capacity() / 3 * 2];
|
samples = new short[buffer.capacity() / 3 * 2];
|
||||||
|
|
||||||
for(int x = 0; x < samples.length; x += 2)
|
if(shouldCalculateDc)
|
||||||
{
|
{
|
||||||
b1 = buffer.get(offset++);
|
long dcAccumulator = 0;
|
||||||
b2 = buffer.get(offset++);
|
|
||||||
b3 = buffer.get(offset++);
|
|
||||||
|
|
||||||
sample = (short)(((b1 & 0xFF) << 4) | ((b2 & 0xF0) >> 4));
|
for(int x = 0; x < samples.length; x += 2)
|
||||||
samples[x] = sample;
|
{
|
||||||
dcAccumulator += sample;
|
b1 = buffer.get(offset++);
|
||||||
|
b2 = buffer.get(offset++);
|
||||||
|
b3 = buffer.get(offset++);
|
||||||
|
|
||||||
sample = (short)(((b2 & 0xF) << 8) | (b3 & 0xFF));
|
sample = (short)(((b1 & 0xFF) << 4) | ((b2 & 0xF0) >> 4));
|
||||||
samples[x] = sample;
|
samples[x] = sample;
|
||||||
dcAccumulator += sample;
|
dcAccumulator += sample;
|
||||||
|
|
||||||
|
sample = (short)(((b2 & 0xF) << 8) | (b3 & 0xFF));
|
||||||
|
samples[x] = sample;
|
||||||
|
dcAccumulator += sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
||||||
|
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
||||||
|
mDcCalculationManager.adjust(averageDcNow);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int x = 0; x < samples.length; x += 2)
|
||||||
|
{
|
||||||
|
b1 = buffer.get(offset++);
|
||||||
|
b2 = buffer.get(offset++);
|
||||||
|
b3 = buffer.get(offset++);
|
||||||
|
|
||||||
//Calculate the average scaled DC offset so that it can be applied in the native buffer's converted samples
|
sample = (short)(((b1 & 0xFF) << 4) | ((b2 & 0xF0) >> 4));
|
||||||
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
samples[x] = sample;
|
||||||
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
|
||||||
averageDcNow -= mAverageDc;
|
sample = (short)(((b2 & 0xF) << 8) | (b3 & 0xFF));
|
||||||
mAverageDc += (averageDcNow * DC_FILTER_GAIN);
|
samples[x] = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
@@ -67,7 +89,7 @@ public class ScalarPackedSampleConverter implements IAirspySampleConverter
|
|||||||
@Override
|
@Override
|
||||||
public float getAverageDc()
|
public float getAverageDc()
|
||||||
{
|
{
|
||||||
return mAverageDc;
|
return mDcCalculationManager.getAverageDc();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.buffer.airspy;
|
package io.github.dsheirer.buffer.airspy;
|
||||||
|
|
||||||
|
import io.github.dsheirer.buffer.DcCorrectionManager;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,34 +27,50 @@ import java.nio.ByteBuffer;
|
|||||||
*/
|
*/
|
||||||
public class ScalarUnpackedSampleConverter implements IAirspySampleConverter
|
public class ScalarUnpackedSampleConverter implements IAirspySampleConverter
|
||||||
{
|
{
|
||||||
private static final float DC_FILTER_GAIN = 0.007f; //Normalizes DC over period of ~142 (1 / .007) buffers
|
/**
|
||||||
private float mAverageDc = 0.0f;
|
* Manages DC calculations and processing interval
|
||||||
|
*/
|
||||||
|
private DcCorrectionManager mDcCalculationManager = new DcCorrectionManager();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short[] convert(ByteBuffer buffer)
|
public short[] convert(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
|
boolean shouldCalculateDc = mDcCalculationManager.shouldCalculateDc();
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
long dcAccumulator = 0;
|
|
||||||
short sample;
|
short sample;
|
||||||
short[] samples;
|
short[] samples;
|
||||||
byte b1, b2;
|
byte b1, b2;
|
||||||
|
|
||||||
samples = new short[buffer.capacity() / 2];
|
samples = new short[buffer.capacity() / 2];
|
||||||
|
|
||||||
for(int x = 0; x < samples.length; x++)
|
if(shouldCalculateDc)
|
||||||
{
|
{
|
||||||
b1 = buffer.get(offset++);
|
long dcAccumulator = 0;
|
||||||
b2 = buffer.get(offset++);
|
|
||||||
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
|
||||||
samples[x] = sample;
|
|
||||||
dcAccumulator += sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Calculate the average scaled DC offset so that it can be applied in the native buffer's converted samples
|
for(int x = 0; x < samples.length; x++)
|
||||||
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
{
|
||||||
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
b1 = buffer.get(offset++);
|
||||||
averageDcNow -= mAverageDc;
|
b2 = buffer.get(offset++);
|
||||||
mAverageDc += (averageDcNow * DC_FILTER_GAIN);
|
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
||||||
|
samples[x] = sample;
|
||||||
|
dcAccumulator += sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
||||||
|
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
||||||
|
mDcCalculationManager.adjust(averageDcNow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int x = 0; x < samples.length; x++)
|
||||||
|
{
|
||||||
|
b1 = buffer.get(offset++);
|
||||||
|
b2 = buffer.get(offset++);
|
||||||
|
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
||||||
|
samples[x] = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
@@ -61,6 +78,6 @@ public class ScalarUnpackedSampleConverter implements IAirspySampleConverter
|
|||||||
@Override
|
@Override
|
||||||
public float getAverageDc()
|
public float getAverageDc()
|
||||||
{
|
{
|
||||||
return mAverageDc;
|
return mDcCalculationManager.getAverageDc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,25 +19,29 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.buffer.airspy;
|
package io.github.dsheirer.buffer.airspy;
|
||||||
|
|
||||||
|
import io.github.dsheirer.buffer.DcCorrectionManager;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import jdk.incubator.vector.ShortVector;
|
import jdk.incubator.vector.ShortVector;
|
||||||
import jdk.incubator.vector.VectorOperators;
|
import jdk.incubator.vector.VectorOperators;
|
||||||
import jdk.incubator.vector.VectorSpecies;
|
import jdk.incubator.vector.VectorSpecies;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scalar implementation of airspy sample converter for un-packed samples.
|
* Scalar implementation of airspy sample converter for un-packed samples.
|
||||||
*/
|
*/
|
||||||
public class VectorUnpackedSampleConverter implements IAirspySampleConverter
|
public class VectorUnpackedSampleConverter implements IAirspySampleConverter
|
||||||
{
|
{
|
||||||
private static final VectorSpecies<Short> VECTOR_SPECIES = ShortVector.SPECIES_PREFERRED;
|
private static final VectorSpecies<Short> VECTOR_SPECIES = ShortVector.SPECIES_PREFERRED;
|
||||||
private static final float DC_FILTER_GAIN = 0.007f; //Normalizes DC over period of ~142 (1 / .007) buffers
|
|
||||||
private float mAverageDc = 0.0f;
|
/**
|
||||||
|
* Manages DC calculations and processing interval
|
||||||
|
*/
|
||||||
|
private DcCorrectionManager mDcCalculationManager = new DcCorrectionManager();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short[] convert(ByteBuffer buffer)
|
public short[] convert(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
long dcAccumulator = 0;
|
boolean shouldCalculateDc = mDcCalculationManager.shouldCalculateDc();
|
||||||
|
|
||||||
short sample;
|
short sample;
|
||||||
short[] samples;
|
short[] samples;
|
||||||
byte b1, b2;
|
byte b1, b2;
|
||||||
@@ -53,44 +57,73 @@ public class VectorUnpackedSampleConverter implements IAirspySampleConverter
|
|||||||
short[] bytes1 = new short[VECTOR_SPECIES.length()];
|
short[] bytes1 = new short[VECTOR_SPECIES.length()];
|
||||||
short[] bytes2 = new short[VECTOR_SPECIES.length()];
|
short[] bytes2 = new short[VECTOR_SPECIES.length()];
|
||||||
|
|
||||||
for(; samplesOffset < VECTOR_SPECIES.loopBound(samples.length); samplesOffset += VECTOR_SPECIES.length())
|
if(shouldCalculateDc)
|
||||||
{
|
{
|
||||||
bytesOffset = 0;
|
long dcAccumulator = 0;
|
||||||
|
|
||||||
while(bytesOffset < VECTOR_SPECIES.length())
|
for(; samplesOffset < VECTOR_SPECIES.loopBound(samples.length); samplesOffset += VECTOR_SPECIES.length())
|
||||||
{
|
{
|
||||||
bytes1[bytesOffset] = (short)(buffer.get(rawPointer++) & 0xFF);
|
bytesOffset = 0;
|
||||||
bytes2[bytesOffset++] = (short)(buffer.get(rawPointer++) & 0x0F);
|
|
||||||
|
while(bytesOffset < VECTOR_SPECIES.length())
|
||||||
|
{
|
||||||
|
bytes1[bytesOffset] = (short)(buffer.get(rawPointer++) & 0xFF);
|
||||||
|
bytes2[bytesOffset++] = (short)(buffer.get(rawPointer++) & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector = ShortVector.fromArray(VECTOR_SPECIES, bytes1, 0)
|
||||||
|
.or(ShortVector.fromArray(VECTOR_SPECIES, bytes2, 0).lanewise(VectorOperators.LSHL, 8));
|
||||||
|
dcAccumulator += vector.reduceLanes(VectorOperators.ADD);
|
||||||
|
vector.intoArray(samples, samplesOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector = ShortVector.fromArray(VECTOR_SPECIES, bytes1, 0)
|
for(; samplesOffset < samples.length; samplesOffset++)
|
||||||
.or(ShortVector.fromArray(VECTOR_SPECIES, bytes2, 0).lanewise(VectorOperators.LSHL, 8));
|
{
|
||||||
dcAccumulator += vector.reduceLanes(VectorOperators.ADD);
|
b1 = buffer.get(rawPointer++);
|
||||||
vector.intoArray(samples, samplesOffset);
|
b2 = buffer.get(rawPointer++);
|
||||||
}
|
|
||||||
|
|
||||||
for(; samplesOffset < samples.length; samplesOffset++)
|
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
||||||
|
samples[samplesOffset] = sample;
|
||||||
|
dcAccumulator += sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
||||||
|
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
||||||
|
mDcCalculationManager.adjust(averageDcNow);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
b1 = buffer.get(rawPointer++);
|
for(; samplesOffset < VECTOR_SPECIES.loopBound(samples.length); samplesOffset += VECTOR_SPECIES.length())
|
||||||
b2 = buffer.get(rawPointer++);
|
{
|
||||||
|
bytesOffset = 0;
|
||||||
|
|
||||||
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
while(bytesOffset < VECTOR_SPECIES.length())
|
||||||
samples[samplesOffset] = sample;
|
{
|
||||||
dcAccumulator += sample;
|
bytes1[bytesOffset] = (short)(buffer.get(rawPointer++) & 0xFF);
|
||||||
|
bytes2[bytesOffset++] = (short)(buffer.get(rawPointer++) & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector = ShortVector.fromArray(VECTOR_SPECIES, bytes1, 0)
|
||||||
|
.or(ShortVector.fromArray(VECTOR_SPECIES, bytes2, 0).lanewise(VectorOperators.LSHL, 8));
|
||||||
|
vector.intoArray(samples, samplesOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; samplesOffset < samples.length; samplesOffset++)
|
||||||
|
{
|
||||||
|
b1 = buffer.get(rawPointer++);
|
||||||
|
b2 = buffer.get(rawPointer++);
|
||||||
|
|
||||||
|
sample = (short)(((b2 & 0x0F) << 8) | (b1 & 0xFF));
|
||||||
|
samples[samplesOffset] = sample;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Calculate the average scaled DC offset so that it can be applied in the native buffer's converted samples
|
|
||||||
float averageDcNow = ((float)dcAccumulator / (float)samples.length) - 2048.0f;
|
|
||||||
averageDcNow *= AirspyBufferIterator.SCALE_SIGNED_12_BIT_TO_FLOAT;
|
|
||||||
averageDcNow -= mAverageDc;
|
|
||||||
mAverageDc += (averageDcNow * DC_FILTER_GAIN);
|
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getAverageDc()
|
public float getAverageDc()
|
||||||
{
|
{
|
||||||
return mAverageDc;
|
return mDcCalculationManager.getAverageDc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.metadata;
|
package io.github.dsheirer.channel.metadata;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.state;
|
package io.github.dsheirer.channel.state;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.state;
|
package io.github.dsheirer.channel.state;
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.state;
|
package io.github.dsheirer.channel.state;
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.state;
|
package io.github.dsheirer.channel.state;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.channel.state;
|
package io.github.dsheirer.channel.state;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -30,8 +30,8 @@ import io.github.dsheirer.map.MapService;
|
|||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.source.tuner.TunerViewPanel;
|
import io.github.dsheirer.source.tuner.ui.TunerViewPanel;
|
||||||
import jiconfont.icons.font_awesome.FontAwesome;
|
import jiconfont.icons.font_awesome.FontAwesome;
|
||||||
import jiconfont.swing.IconFontSwing;
|
import jiconfont.swing.IconFontSwing;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
@@ -59,13 +59,13 @@ public class ControllerPanel extends JPanel
|
|||||||
|
|
||||||
public ControllerPanel(PlaylistManager playlistManager, AudioPlaybackManager audioPlaybackManager,
|
public ControllerPanel(PlaylistManager playlistManager, AudioPlaybackManager audioPlaybackManager,
|
||||||
IconModel iconModel, MapService mapService, SettingsManager settingsManager,
|
IconModel iconModel, MapService mapService, SettingsManager settingsManager,
|
||||||
SourceManager sourceManager, UserPreferences userPreferences)
|
TunerManager tunerManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
mAudioPanel = new AudioPanel(iconModel, userPreferences, settingsManager, sourceManager, audioPlaybackManager,
|
mAudioPanel = new AudioPanel(iconModel, userPreferences, settingsManager, audioPlaybackManager,
|
||||||
playlistManager.getAliasModel());
|
playlistManager.getAliasModel());
|
||||||
mNowPlayingPanel = new NowPlayingPanel(playlistManager, iconModel, userPreferences);
|
mNowPlayingPanel = new NowPlayingPanel(playlistManager, iconModel, userPreferences);
|
||||||
mMapPanel = new MapPanel(mapService, playlistManager.getAliasModel(), iconModel, settingsManager);
|
mMapPanel = new MapPanel(mapService, playlistManager.getAliasModel(), iconModel, settingsManager);
|
||||||
mTunerManagerPanel = new TunerViewPanel(sourceManager.getTunerModel(), userPreferences);
|
mTunerManagerPanel = new TunerViewPanel(tunerManager, userPreferences);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.controller.channel;
|
package io.github.dsheirer.controller.channel;
|
||||||
|
|
||||||
@@ -28,6 +25,7 @@ import io.github.dsheirer.channel.metadata.ChannelAndMetadata;
|
|||||||
import io.github.dsheirer.channel.metadata.ChannelMetadata;
|
import io.github.dsheirer.channel.metadata.ChannelMetadata;
|
||||||
import io.github.dsheirer.channel.metadata.ChannelMetadataModel;
|
import io.github.dsheirer.channel.metadata.ChannelMetadataModel;
|
||||||
import io.github.dsheirer.controller.channel.event.ChannelStartProcessingRequest;
|
import io.github.dsheirer.controller.channel.event.ChannelStartProcessingRequest;
|
||||||
|
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
|
||||||
import io.github.dsheirer.controller.channel.event.PreloadDataContent;
|
import io.github.dsheirer.controller.channel.event.PreloadDataContent;
|
||||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||||
import io.github.dsheirer.identifier.Form;
|
import io.github.dsheirer.identifier.Form;
|
||||||
@@ -47,14 +45,12 @@ import io.github.dsheirer.sample.Listener;
|
|||||||
import io.github.dsheirer.source.Source;
|
import io.github.dsheirer.source.Source;
|
||||||
import io.github.dsheirer.source.SourceEvent;
|
import io.github.dsheirer.source.SourceEvent;
|
||||||
import io.github.dsheirer.source.SourceException;
|
import io.github.dsheirer.source.SourceException;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
|
||||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||||
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
||||||
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import javafx.application.Platform;
|
import java.awt.GraphicsEnvironment;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -64,6 +60,9 @@ import java.util.concurrent.ScheduledFuture;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel processing manager handles all starting and stopping of channel decoding. A processing chain is created
|
* Channel processing manager handles all starting and stopping of channel decoding. A processing chain is created
|
||||||
@@ -86,7 +85,7 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
private ChannelMapModel mChannelMapModel;
|
private ChannelMapModel mChannelMapModel;
|
||||||
private ChannelMetadataModel mChannelMetadataModel;
|
private ChannelMetadataModel mChannelMetadataModel;
|
||||||
private EventLogManager mEventLogManager;
|
private EventLogManager mEventLogManager;
|
||||||
private SourceManager mSourceManager;
|
private TunerManager mTunerManager;
|
||||||
private AliasModel mAliasModel;
|
private AliasModel mAliasModel;
|
||||||
private UserPreferences mUserPreferences;
|
private UserPreferences mUserPreferences;
|
||||||
private List<Long> mLoggedFrequencies = new ArrayList<>();
|
private List<Long> mLoggedFrequencies = new ArrayList<>();
|
||||||
@@ -97,16 +96,16 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
*
|
*
|
||||||
* @param channelMapModel containing channel maps defined by the user
|
* @param channelMapModel containing channel maps defined by the user
|
||||||
* @param eventLogManager for adding event loggers to channels
|
* @param eventLogManager for adding event loggers to channels
|
||||||
* @param sourceManager for obtaining a tuner channel source for the channel
|
* @param tunerManager for obtaining a tuner channel source for the channel
|
||||||
* @param aliasModel for aliasing of identifiers produced by the channel
|
* @param aliasModel for aliasing of identifiers produced by the channel
|
||||||
* @param userPreferences for user defined behavior and settings
|
* @param userPreferences for user defined behavior and settings
|
||||||
*/
|
*/
|
||||||
public ChannelProcessingManager(ChannelMapModel channelMapModel, EventLogManager eventLogManager,
|
public ChannelProcessingManager(ChannelMapModel channelMapModel, EventLogManager eventLogManager,
|
||||||
SourceManager sourceManager, AliasModel aliasModel, UserPreferences userPreferences)
|
TunerManager tunerManager, AliasModel aliasModel, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
mChannelMapModel = channelMapModel;
|
mChannelMapModel = channelMapModel;
|
||||||
mEventLogManager = eventLogManager;
|
mEventLogManager = eventLogManager;
|
||||||
mSourceManager = sourceManager;
|
mTunerManager = tunerManager;
|
||||||
mAliasModel = aliasModel;
|
mAliasModel = aliasModel;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
mChannelMetadataModel = new ChannelMetadataModel();
|
mChannelMetadataModel = new ChannelMetadataModel();
|
||||||
@@ -126,7 +125,20 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
*/
|
*/
|
||||||
private boolean isProcessing(Channel channel)
|
private boolean isProcessing(Channel channel)
|
||||||
{
|
{
|
||||||
return mProcessingChains.containsKey(channel) && mProcessingChains.get(channel).isProcessing();
|
boolean isProcessing = false;
|
||||||
|
|
||||||
|
mLock.lock();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
isProcessing = mProcessingChains.containsKey(channel) && mProcessingChains.get(channel).isProcessing();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return isProcessing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,18 +167,60 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
*/
|
*/
|
||||||
public Channel getChannel(ProcessingChain processingChain)
|
public Channel getChannel(ProcessingChain processingChain)
|
||||||
{
|
{
|
||||||
|
Channel channel = null;
|
||||||
|
|
||||||
if(processingChain != null)
|
if(processingChain != null)
|
||||||
{
|
{
|
||||||
for(Map.Entry<Channel,ProcessingChain> entry : mProcessingChains.entrySet())
|
mLock.lock();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if(entry.getValue() == processingChain)
|
for(Map.Entry<Channel,ProcessingChain> entry : mProcessingChains.entrySet())
|
||||||
{
|
{
|
||||||
return entry.getKey();
|
if(entry.getValue() == processingChain)
|
||||||
|
{
|
||||||
|
channel = entry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mLock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the channel associated with the processing chain that is consuming from the tuner channel source
|
||||||
|
* @param tunerChannelSource to find the channel
|
||||||
|
* @return channel
|
||||||
|
*/
|
||||||
|
private Channel getChannel(TunerChannelSource tunerChannelSource)
|
||||||
|
{
|
||||||
|
Channel channel = null;
|
||||||
|
|
||||||
|
mLock.lock();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for(Map.Entry<Channel,ProcessingChain> entry : mProcessingChains.entrySet())
|
||||||
|
{
|
||||||
|
if(entry.getValue().hasSource(tunerChannelSource))
|
||||||
|
{
|
||||||
|
channel = entry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,6 +329,28 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to stop a channel that is currently processing
|
||||||
|
* @param request with the tuner channel source feeding the channel to be stopped.
|
||||||
|
*/
|
||||||
|
@Subscribe
|
||||||
|
public void stopChannelRequest(ChannelStopProcessingRequest request)
|
||||||
|
{
|
||||||
|
Channel channel = getChannel(request.getTunerChannelSource());
|
||||||
|
|
||||||
|
if(channel != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stop(channel);
|
||||||
|
}
|
||||||
|
catch(ChannelException ce)
|
||||||
|
{
|
||||||
|
mLog.error("Error stopping channel [" + channel + "]", ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the specified channel
|
* Stops the specified channel
|
||||||
* @param channel to stop
|
* @param channel to stop
|
||||||
@@ -303,7 +379,7 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
source = mSourceManager.getSource(channel.getSourceConfiguration(),
|
source = mTunerManager.getSource(channel.getSourceConfiguration(),
|
||||||
channel.getDecodeConfiguration().getChannelSpecification());
|
channel.getDecodeConfiguration().getChannelSpecification());
|
||||||
}
|
}
|
||||||
catch(SourceException se)
|
catch(SourceException se)
|
||||||
@@ -439,8 +515,15 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
{
|
{
|
||||||
processingChain.start();
|
processingChain.start();
|
||||||
|
|
||||||
//This has to be done on the FX event thread when the playlist editor is constructed
|
if(GraphicsEnvironment.isHeadless())
|
||||||
Platform.runLater(() -> channel.setProcessing(true));
|
{
|
||||||
|
channel.setProcessing(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//This has to be done on the FX event thread when the playlist editor is constructed
|
||||||
|
Platform.runLater(() -> channel.setProcessing(true));
|
||||||
|
}
|
||||||
|
|
||||||
mChannelEventBroadcaster.broadcast(new ChannelEvent(channel, ChannelEvent.Event.NOTIFICATION_PROCESSING_START));
|
mChannelEventBroadcaster.broadcast(new ChannelEvent(channel, ChannelEvent.Event.NOTIFICATION_PROCESSING_START));
|
||||||
}
|
}
|
||||||
@@ -526,13 +609,20 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
*/
|
*/
|
||||||
private void stopProcessing(Channel channel) throws ChannelException
|
private void stopProcessing(Channel channel) throws ChannelException
|
||||||
{
|
{
|
||||||
//This has to be done on the FX event thread when the playlist editor is constructed
|
|
||||||
Platform.runLater(() -> channel.setProcessing(false));
|
|
||||||
|
|
||||||
ProcessingChain processingChain = removeProcessingChain(channel);
|
ProcessingChain processingChain = removeProcessingChain(channel);
|
||||||
|
|
||||||
if(processingChain != null)
|
if(processingChain != null)
|
||||||
{
|
{
|
||||||
|
if(GraphicsEnvironment.isHeadless())
|
||||||
|
{
|
||||||
|
channel.setProcessing(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//This has to be done on the FX event thread when the playlist editor is constructed
|
||||||
|
Platform.runLater(() -> channel.setProcessing(false));
|
||||||
|
}
|
||||||
|
|
||||||
//Since the processing chain's source will block on stop(), throw it to the thread pool to run
|
//Since the processing chain's source will block on stop(), throw it to the thread pool to run
|
||||||
ThreadPool.CACHED.submit(() -> {
|
ThreadPool.CACHED.submit(() -> {
|
||||||
try
|
try
|
||||||
@@ -558,10 +648,6 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ChannelException("Channel is not currently playing");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -736,7 +822,14 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
|
|||||||
|
|
||||||
if(toShutdown != null)
|
if(toShutdown != null)
|
||||||
{
|
{
|
||||||
mLog.warn("Channel source error detected - stopping channel [" + toShutdown.getName() + "]");
|
if(sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE)
|
||||||
|
{
|
||||||
|
mLog.warn("Channel source error detected - stopping channel [" + toShutdown.getName() + "]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLog.warn("Source event error - stopping channel [" + toShutdown.getName() + "]");
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* 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.controller.channel.event;
|
||||||
|
|
||||||
|
import io.github.dsheirer.module.ModuleEventBusMessage;
|
||||||
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to stop processing a channel for a specific tuner channel source
|
||||||
|
*/
|
||||||
|
public class ChannelStopProcessingRequest extends ModuleEventBusMessage
|
||||||
|
{
|
||||||
|
private TunerChannelSource mTunerChannelSource;
|
||||||
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param tunerChannelSource for the channel to stop
|
||||||
|
*/
|
||||||
|
public ChannelStopProcessingRequest(TunerChannelSource tunerChannelSource)
|
||||||
|
{
|
||||||
|
mTunerChannelSource = tunerChannelSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TunerChannelSource getTunerChannelSource()
|
||||||
|
{
|
||||||
|
return mTunerChannelSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,11 +21,13 @@ package io.github.dsheirer.dsp.filter.channelizer;
|
|||||||
import io.github.dsheirer.buffer.INativeBuffer;
|
import io.github.dsheirer.buffer.INativeBuffer;
|
||||||
import io.github.dsheirer.buffer.INativeBufferProvider;
|
import io.github.dsheirer.buffer.INativeBufferProvider;
|
||||||
import io.github.dsheirer.buffer.NativeBufferPoisonPill;
|
import io.github.dsheirer.buffer.NativeBufferPoisonPill;
|
||||||
|
import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest;
|
||||||
import io.github.dsheirer.dsp.filter.FilterFactory;
|
import io.github.dsheirer.dsp.filter.FilterFactory;
|
||||||
import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor;
|
import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor;
|
||||||
import io.github.dsheirer.dsp.filter.channelizer.output.OneChannelOutputProcessor;
|
import io.github.dsheirer.dsp.filter.channelizer.output.OneChannelOutputProcessor;
|
||||||
import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcessor;
|
import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcessor;
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
import io.github.dsheirer.eventbus.MyEventBus;
|
||||||
import io.github.dsheirer.sample.Broadcaster;
|
import io.github.dsheirer.sample.Broadcaster;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||||
@@ -37,10 +39,7 @@ import io.github.dsheirer.source.tuner.TunerController;
|
|||||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
import io.github.dsheirer.util.Dispatcher;
|
import io.github.dsheirer.util.Dispatcher;
|
||||||
import org.apache.commons.math3.util.FastMath;
|
import java.util.ArrayList;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -50,6 +49,9 @@ import java.util.SortedSet;
|
|||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polyphase Channel Manager is a DDC channel manager and complex buffer queue/processor for a tuner. This class
|
* Polyphase Channel Manager is a DDC channel manager and complex buffer queue/processor for a tuner. This class
|
||||||
@@ -84,6 +86,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
private NativeBufferReceiver mNativeBufferReceiver = new NativeBufferReceiver();
|
private NativeBufferReceiver mNativeBufferReceiver = new NativeBufferReceiver();
|
||||||
private Dispatcher mBufferDispatcher;
|
private Dispatcher mBufferDispatcher;
|
||||||
private Map<Integer,float[]> mOutputProcessorFilters = new HashMap<>();
|
private Map<Integer,float[]> mOutputProcessorFilters = new HashMap<>();
|
||||||
|
private boolean mRunning = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a polyphase channel manager instance.
|
* Creates a polyphase channel manager instance.
|
||||||
@@ -126,6 +129,18 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
this(tunerController, tunerController.getFrequency(), tunerController.getSampleRate());
|
this(tunerController, tunerController.getFrequency(), tunerController.getSampleRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopAllChannels()
|
||||||
|
{
|
||||||
|
mRunning = false;
|
||||||
|
|
||||||
|
List<TunerChannelSource> toStop = new ArrayList<>(mChannelSources);
|
||||||
|
|
||||||
|
for(TunerChannelSource tunerChannelSource: toStop)
|
||||||
|
{
|
||||||
|
MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals to all provisioned tuner channel sources that the source complex buffer provider has an error and can
|
* Signals to all provisioned tuner channel sources that the source complex buffer provider has an error and can
|
||||||
* no longer provide channels, so that the tuner channel source can notify the consumer of the error state.
|
* no longer provide channels, so that the tuner channel source can notify the consumer of the error state.
|
||||||
@@ -164,24 +179,27 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
{
|
{
|
||||||
PolyphaseChannelSource channelSource = null;
|
PolyphaseChannelSource channelSource = null;
|
||||||
|
|
||||||
List<Integer> polyphaseIndexes = mChannelCalculator.getChannelIndexes(tunerChannel);
|
if(mRunning)
|
||||||
|
|
||||||
IPolyphaseChannelOutputProcessor outputProcessor = getOutputProcessor(polyphaseIndexes);
|
|
||||||
|
|
||||||
if(outputProcessor != null)
|
|
||||||
{
|
{
|
||||||
long centerFrequency = mChannelCalculator.getCenterFrequencyForIndexes(polyphaseIndexes);
|
List<Integer> polyphaseIndexes = mChannelCalculator.getChannelIndexes(tunerChannel);
|
||||||
|
|
||||||
try
|
IPolyphaseChannelOutputProcessor outputProcessor = getOutputProcessor(polyphaseIndexes);
|
||||||
{
|
|
||||||
channelSource = new PolyphaseChannelSource(tunerChannel, outputProcessor, mChannelSourceEventListener,
|
|
||||||
mChannelCalculator.getChannelSampleRate(), centerFrequency);
|
|
||||||
|
|
||||||
mChannelSources.add(channelSource);
|
if(outputProcessor != null)
|
||||||
}
|
|
||||||
catch(FilterDesignException fde)
|
|
||||||
{
|
{
|
||||||
mLog.debug("Couldn't design final output low pass filter for polyphase channel source");
|
long centerFrequency = mChannelCalculator.getCenterFrequencyForIndexes(polyphaseIndexes);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
channelSource = new PolyphaseChannelSource(tunerChannel, outputProcessor, mChannelSourceEventListener,
|
||||||
|
mChannelCalculator.getChannelSampleRate(), centerFrequency);
|
||||||
|
|
||||||
|
mChannelSources.add(channelSource);
|
||||||
|
}
|
||||||
|
catch(FilterDesignException fde)
|
||||||
|
{
|
||||||
|
mLog.debug("Couldn't design final output low pass filter for polyphase channel source");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class DecimationFilterFactory
|
|||||||
*/
|
*/
|
||||||
public static int getDecimationRate(int requestedRate)
|
public static int getDecimationRate(int requestedRate)
|
||||||
{
|
{
|
||||||
if(requestedRate < 2)
|
if(requestedRate < 0)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Requested decimation rate must be greater than 2");
|
throw new IllegalArgumentException("Requested decimation rate must be greater than 2");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2021 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* 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.dsp.filter.fir.remez;
|
package io.github.dsheirer.dsp.filter.fir.remez;
|
||||||
|
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.dsp.filter.fir.remez;
|
package io.github.dsheirer.dsp.filter.fir.remez;
|
||||||
|
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.dsp.filter.fir.remez;
|
package io.github.dsheirer.dsp.filter.fir.remez;
|
||||||
|
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2021 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* SDR Trunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
package io.github.dsheirer.edac;
|
package io.github.dsheirer.edac;
|
||||||
|
|
||||||
import io.github.dsheirer.bits.BinaryMessage;
|
import io.github.dsheirer.bits.BinaryMessage;
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class FilterEditorPanel<T> extends JPanel
|
|||||||
List<IFilter<T>> filters = filterSet.getFilters();
|
List<IFilter<T>> filters = filterSet.getFilters();
|
||||||
|
|
||||||
/* sort the filters in alphabetical order by name */
|
/* sort the filters in alphabetical order by name */
|
||||||
filters.sort((Comparator<IFilter<?>>) (first, second) -> first.getName().compareTo(second.getName()));
|
filters.sort(Comparator.comparing(IFilter::getName));
|
||||||
|
|
||||||
for(IFilter<T> filter : filters)
|
for(IFilter<T> filter : filters)
|
||||||
{
|
{
|
||||||
@@ -98,7 +98,7 @@ public class FilterEditorPanel<T> extends JPanel
|
|||||||
{
|
{
|
||||||
List<FilterElement<?>> elements = filter.getFilterElements();
|
List<FilterElement<?>> elements = filter.getFilterElements();
|
||||||
|
|
||||||
elements.sort(Comparator.comparing(FilterElement::toString));
|
elements.sort(Comparator.comparing(FilterElement::getName));
|
||||||
|
|
||||||
for(FilterElement<?> element : elements)
|
for(FilterElement<?> element : elements)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,13 +46,14 @@ public class FilterSet<T> implements IFilter<T>
|
|||||||
{
|
{
|
||||||
for( IFilter<T> filter: mFilters )
|
for( IFilter<T> filter: mFilters )
|
||||||
{
|
{
|
||||||
if( filter.canProcess( t ) )
|
// Make sure to loop through all filters.
|
||||||
|
// Only return if true or all filters have been evaluated.
|
||||||
|
if( filter.canProcess( t ) && filter.passes( t ))
|
||||||
{
|
{
|
||||||
return filter.passes( t );
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,10 +41,7 @@ import io.github.dsheirer.jmbe.JmbeEditorRequest;
|
|||||||
import io.github.dsheirer.module.log.EventLogManager;
|
import io.github.dsheirer.module.log.EventLogManager;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.embed.swing.JFXPanel;
|
import javafx.embed.swing.JFXPanel;
|
||||||
@@ -79,6 +76,7 @@ public class JavaFxWindowManager extends Application
|
|||||||
private JmbeEditor mJmbeEditor;
|
private JmbeEditor mJmbeEditor;
|
||||||
private PlaylistEditor mPlaylistEditor;
|
private PlaylistEditor mPlaylistEditor;
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
|
private TunerManager mTunerManager;
|
||||||
private UserPreferences mUserPreferences;
|
private UserPreferences mUserPreferences;
|
||||||
private UserPreferencesEditor mUserPreferencesEditor;
|
private UserPreferencesEditor mUserPreferencesEditor;
|
||||||
|
|
||||||
@@ -91,9 +89,10 @@ public class JavaFxWindowManager extends Application
|
|||||||
/**
|
/**
|
||||||
* Constructs an instance. Note: this constructor is used for Swing applications.
|
* Constructs an instance. Note: this constructor is used for Swing applications.
|
||||||
*/
|
*/
|
||||||
public JavaFxWindowManager(UserPreferences userPreferences, PlaylistManager playlistManager)
|
public JavaFxWindowManager(UserPreferences userPreferences, TunerManager tunerManager, PlaylistManager playlistManager)
|
||||||
{
|
{
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
|
mTunerManager = tunerManager;
|
||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
@@ -106,12 +105,10 @@ public class JavaFxWindowManager extends Application
|
|||||||
{
|
{
|
||||||
mUserPreferences = new UserPreferences();
|
mUserPreferences = new UserPreferences();
|
||||||
AliasModel aliasModel = new AliasModel();
|
AliasModel aliasModel = new AliasModel();
|
||||||
TunerConfigurationModel tunerConfigurationModel = new TunerConfigurationModel();
|
|
||||||
TunerModel tunerModel = new TunerModel(tunerConfigurationModel);
|
|
||||||
SourceManager sourceManager = new SourceManager(tunerModel, new SettingsManager(tunerConfigurationModel),
|
|
||||||
mUserPreferences);
|
|
||||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||||
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconModel());
|
mTunerManager = new TunerManager(mUserPreferences);
|
||||||
|
mTunerManager.start();
|
||||||
|
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, new IconModel());
|
||||||
mPlaylistManager.init();
|
mPlaylistManager.init();
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
@@ -274,7 +271,7 @@ public class JavaFxWindowManager extends Application
|
|||||||
{
|
{
|
||||||
if(mPlaylistEditor == null)
|
if(mPlaylistEditor == null)
|
||||||
{
|
{
|
||||||
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mUserPreferences);
|
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mPlaylistEditor;
|
return mPlaylistEditor;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import io.github.dsheirer.audio.playback.AudioPlaybackManager;
|
|||||||
import io.github.dsheirer.controller.ControllerPanel;
|
import io.github.dsheirer.controller.ControllerPanel;
|
||||||
import io.github.dsheirer.controller.channel.Channel;
|
import io.github.dsheirer.controller.channel.Channel;
|
||||||
import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
|
import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
|
||||||
|
import io.github.dsheirer.controller.channel.ChannelException;
|
||||||
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
||||||
import io.github.dsheirer.eventbus.MyEventBus;
|
import io.github.dsheirer.eventbus.MyEventBus;
|
||||||
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
|
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
|
||||||
@@ -47,12 +48,11 @@ import io.github.dsheirer.properties.SystemProperties;
|
|||||||
import io.github.dsheirer.record.AudioRecordingManager;
|
import io.github.dsheirer.record.AudioRecordingManager;
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
|
||||||
import io.github.dsheirer.source.tuner.Tuner;
|
import io.github.dsheirer.source.tuner.Tuner;
|
||||||
import io.github.dsheirer.source.tuner.TunerEvent;
|
import io.github.dsheirer.source.tuner.TunerEvent;
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||||
import io.github.dsheirer.source.tuner.TunerSpectralDisplayManager;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
import io.github.dsheirer.source.tuner.ui.TunerSpectralDisplayManager;
|
||||||
import io.github.dsheirer.spectrum.ClearTunerMenuItem;
|
import io.github.dsheirer.spectrum.ClearTunerMenuItem;
|
||||||
import io.github.dsheirer.spectrum.ShowTunerMenuItem;
|
import io.github.dsheirer.spectrum.ShowTunerMenuItem;
|
||||||
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
|
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
|
||||||
@@ -68,11 +68,25 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JSeparator;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.MenuEvent;
|
import javax.swing.event.MenuEvent;
|
||||||
import javax.swing.event.MenuListener;
|
import javax.swing.event.MenuListener;
|
||||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||||
import java.awt.*;
|
import java.awt.AWTException;
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Robot;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
@@ -104,19 +118,24 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
private ControllerPanel mControllerPanel;
|
private ControllerPanel mControllerPanel;
|
||||||
private IconModel mIconModel = new IconModel();
|
private IconModel mIconModel = new IconModel();
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
private SourceManager mSourceManager;
|
|
||||||
private SettingsManager mSettingsManager;
|
private SettingsManager mSettingsManager;
|
||||||
private SpectralDisplayPanel mSpectralPanel;
|
private SpectralDisplayPanel mSpectralPanel;
|
||||||
private JFrame mMainGui = new JFrame();
|
private JFrame mMainGui;
|
||||||
private JideSplitPane mSplitPane;
|
private JideSplitPane mSplitPane;
|
||||||
private JavaFxWindowManager mJavaFxWindowManager;
|
private JavaFxWindowManager mJavaFxWindowManager;
|
||||||
private UserPreferences mUserPreferences = new UserPreferences();
|
private UserPreferences mUserPreferences = new UserPreferences();
|
||||||
|
private TunerManager mTunerManager;
|
||||||
private ApplicationLog mApplicationLog;
|
private ApplicationLog mApplicationLog;
|
||||||
|
|
||||||
private String mTitle;
|
private String mTitle;
|
||||||
|
|
||||||
public SDRTrunk()
|
public SDRTrunk()
|
||||||
{
|
{
|
||||||
|
if(!GraphicsEnvironment.isHeadless())
|
||||||
|
{
|
||||||
|
mMainGui = new JFrame();
|
||||||
|
}
|
||||||
|
|
||||||
mApplicationLog = new ApplicationLog(mUserPreferences);
|
mApplicationLog = new ApplicationLog(mUserPreferences);
|
||||||
mApplicationLog.start();
|
mApplicationLog.start();
|
||||||
|
|
||||||
@@ -154,16 +173,19 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
//Register FontAwesome so we can use the fonts in Swing windows
|
//Register FontAwesome so we can use the fonts in Swing windows
|
||||||
IconFontSwing.register(FontAwesome.getIconFont());
|
IconFontSwing.register(FontAwesome.getIconFont());
|
||||||
|
|
||||||
TunerConfigurationModel tunerConfigurationModel = new TunerConfigurationModel();
|
mTunerManager = new TunerManager(mUserPreferences);
|
||||||
TunerModel tunerModel = new TunerModel(tunerConfigurationModel);
|
mTunerManager.start();
|
||||||
|
|
||||||
mSettingsManager = new SettingsManager(tunerConfigurationModel);
|
mSettingsManager = new SettingsManager();
|
||||||
mSourceManager = new SourceManager(tunerModel, mSettingsManager, mUserPreferences);
|
|
||||||
|
|
||||||
AliasModel aliasModel = new AliasModel();
|
AliasModel aliasModel = new AliasModel();
|
||||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||||
mPlaylistManager = new PlaylistManager(mUserPreferences, mSourceManager, aliasModel, eventLogManager, mIconModel);
|
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, mIconModel);
|
||||||
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mPlaylistManager);
|
|
||||||
|
if(!GraphicsEnvironment.isHeadless())
|
||||||
|
{
|
||||||
|
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mTunerManager, mPlaylistManager);
|
||||||
|
}
|
||||||
|
|
||||||
CalibrationManager calibrationManager = CalibrationManager.getInstance(mUserPreferences);
|
CalibrationManager calibrationManager = CalibrationManager.getInstance(mUserPreferences);
|
||||||
final boolean calibrating = !calibrationManager.isCalibrated() &&
|
final boolean calibrating = !calibrationManager.isCalibrated() &&
|
||||||
@@ -190,32 +212,45 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
MapService mapService = new MapService(mIconModel);
|
MapService mapService = new MapService(mIconModel);
|
||||||
mPlaylistManager.getChannelProcessingManager().addDecodeEventListener(mapService);
|
mPlaylistManager.getChannelProcessingManager().addDecodeEventListener(mapService);
|
||||||
|
|
||||||
mControllerPanel = new ControllerPanel(mPlaylistManager, audioPlaybackManager, mIconModel, mapService,
|
if(!GraphicsEnvironment.isHeadless())
|
||||||
mSettingsManager, mSourceManager, mUserPreferences);
|
{
|
||||||
|
mControllerPanel = new ControllerPanel(mPlaylistManager, audioPlaybackManager, mIconModel, mapService,
|
||||||
|
mSettingsManager, mTunerManager, mUserPreferences);
|
||||||
|
}
|
||||||
|
|
||||||
mSpectralPanel = new SpectralDisplayPanel(mPlaylistManager, mSettingsManager, tunerModel);
|
mSpectralPanel = new SpectralDisplayPanel(mPlaylistManager, mSettingsManager, mTunerManager.getDiscoveredTunerModel());
|
||||||
|
|
||||||
TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
|
TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
|
||||||
mPlaylistManager, mSettingsManager, tunerModel);
|
mPlaylistManager, mSettingsManager, mTunerManager.getDiscoveredTunerModel());
|
||||||
tunerModel.addListener(tunerSpectralDisplayManager);
|
mTunerManager.getDiscoveredTunerModel().addListener(tunerSpectralDisplayManager);
|
||||||
tunerModel.addListener(this);
|
mTunerManager.getDiscoveredTunerModel().addListener(this);
|
||||||
|
|
||||||
mPlaylistManager.init();
|
mPlaylistManager.init();
|
||||||
|
|
||||||
mLog.info("starting main application gui");
|
if(GraphicsEnvironment.isHeadless())
|
||||||
|
{
|
||||||
|
mLog.info("starting main application headless");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLog.info("starting main application gui");
|
||||||
|
|
||||||
//Initialize the GUI
|
//Initialize the GUI
|
||||||
initGUI();
|
initGUI();
|
||||||
|
}
|
||||||
tunerModel.requestFirstTunerDisplay();
|
|
||||||
|
|
||||||
//Start the gui
|
//Start the gui
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mMainGui.setVisible(true);
|
if(!GraphicsEnvironment.isHeadless())
|
||||||
|
{
|
||||||
|
mMainGui.setVisible(true);
|
||||||
|
Tuner tuner = tunerSpectralDisplayManager.showFirstTuner();
|
||||||
|
updateTitle(tuner);
|
||||||
|
}
|
||||||
|
|
||||||
if(calibrating)
|
if(calibrating && !GraphicsEnvironment.isHeadless())
|
||||||
{
|
{
|
||||||
Platform.runLater(() ->
|
Platform.runLater(() ->
|
||||||
{
|
{
|
||||||
@@ -256,8 +291,25 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
|
|
||||||
if(channels.size() > 0)
|
if(channels.size() > 0)
|
||||||
{
|
{
|
||||||
ChannelAutoStartFrame autoStartFrame = new ChannelAutoStartFrame(mPlaylistManager.getChannelProcessingManager(),
|
if(GraphicsEnvironment.isHeadless())
|
||||||
channels);
|
{
|
||||||
|
for(Channel channel: channels)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mLog.info("Auto-starting channel " + channel.getName());
|
||||||
|
mPlaylistManager.getChannelProcessingManager().start(channel);
|
||||||
|
}
|
||||||
|
catch(ChannelException ce)
|
||||||
|
{
|
||||||
|
mLog.error("Channel: " + channel.getName() + " auto-start failed: " + ce.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new ChannelAutoStartFrame(mPlaylistManager.getChannelProcessingManager(), channels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +507,8 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
|
|
||||||
mLog.info("Stopping spectral display ...");
|
mLog.info("Stopping spectral display ...");
|
||||||
mSpectralPanel.clearTuner();
|
mSpectralPanel.clearTuner();
|
||||||
mSourceManager.shutdown();
|
mLog.info("Stopping tuners ...");
|
||||||
|
mTunerManager.stop();
|
||||||
mLog.info("Shutdown complete.");
|
mLog.info("Shutdown complete.");
|
||||||
mApplicationLog.stop();
|
mApplicationLog.stop();
|
||||||
}
|
}
|
||||||
@@ -572,7 +625,23 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
{
|
{
|
||||||
if(event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
|
if(event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
|
||||||
{
|
{
|
||||||
mMainGui.setTitle(mTitle + " - " + event.getTuner().getName());
|
updateTitle(event.getTuner());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the title bar with the tuner name
|
||||||
|
* @param tuner optional
|
||||||
|
*/
|
||||||
|
private void updateTitle(Tuner tuner)
|
||||||
|
{
|
||||||
|
if(tuner != null)
|
||||||
|
{
|
||||||
|
mMainGui.setTitle(mTitle + " - " + tuner.getPreferredName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mMainGui.setTitle(mTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,9 +691,9 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
{
|
{
|
||||||
removeAll();
|
removeAll();
|
||||||
|
|
||||||
for(Tuner tuner : mSourceManager.getTunerModel().getTuners())
|
for(DiscoveredTuner discoveredTuner: mTunerManager.getAvailableTuners())
|
||||||
{
|
{
|
||||||
add(new ShowTunerMenuItem(mSourceManager.getTunerModel(), tuner));
|
add(new ShowTunerMenuItem(mTunerManager.getDiscoveredTunerModel(), discoveredTuner.getTuner()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,17 +20,16 @@ package io.github.dsheirer.gui.channelizer;
|
|||||||
|
|
||||||
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
||||||
import io.github.dsheirer.buffer.INativeBuffer;
|
import io.github.dsheirer.buffer.INativeBuffer;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||||
import io.github.dsheirer.source.SourceEvent;
|
import io.github.dsheirer.source.SourceEvent;
|
||||||
import io.github.dsheirer.source.SourceException;
|
import io.github.dsheirer.source.SourceException;
|
||||||
|
import io.github.dsheirer.source.tuner.LoggingTunerErrorListener;
|
||||||
import io.github.dsheirer.source.tuner.Tuner;
|
import io.github.dsheirer.source.tuner.Tuner;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import io.github.dsheirer.source.tuner.test.TestTuner;
|
import io.github.dsheirer.source.tuner.test.TestTuner;
|
||||||
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||||
import io.github.dsheirer.spectrum.DFTSize;
|
import io.github.dsheirer.spectrum.DFTSize;
|
||||||
@@ -40,10 +39,16 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -57,7 +62,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
private static final int CHANNEL_BANDWIDTH = 12500;
|
private static final int CHANNEL_BANDWIDTH = 12500;
|
||||||
private static final int CHANNEL_FFT_FRAME_RATE = 20;
|
private static final int CHANNEL_FFT_FRAME_RATE = 20;
|
||||||
|
|
||||||
private SettingsManager mSettingsManager = new SettingsManager(new TunerConfigurationModel());
|
private SettingsManager mSettingsManager = new SettingsManager();
|
||||||
private JPanel mPrimaryPanel;
|
private JPanel mPrimaryPanel;
|
||||||
private JPanel mControlPanel;
|
private JPanel mControlPanel;
|
||||||
private JLabel mToneFrequencyLabel;
|
private JLabel mToneFrequencyLabel;
|
||||||
@@ -78,7 +83,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
*/
|
*/
|
||||||
public ChannelizerViewer(int channelsPerRow)
|
public ChannelizerViewer(int channelsPerRow)
|
||||||
{
|
{
|
||||||
mTestTuner = new TestTuner(new UserPreferences());
|
mTestTuner = new TestTuner(new LoggingTunerErrorListener());
|
||||||
mChannelCount = (int)(mTestTuner.getTunerController().getBandwidth() / CHANNEL_BANDWIDTH);
|
mChannelCount = (int)(mTestTuner.getTunerController().getBandwidth() / CHANNEL_BANDWIDTH);
|
||||||
mChannelsPerRow = channelsPerRow;
|
mChannelsPerRow = channelsPerRow;
|
||||||
|
|
||||||
@@ -518,7 +523,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TestTuner tuner = new TestTuner(new UserPreferences());
|
TestTuner tuner = new TestTuner(new LoggingTunerErrorListener());
|
||||||
|
|
||||||
List<TunerChannel> tunerChannels = getTunerChannels(tuner);
|
List<TunerChannel> tunerChannels = getTunerChannels(tuner);
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,17 @@ package io.github.dsheirer.gui.channelizer;
|
|||||||
|
|
||||||
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
||||||
import io.github.dsheirer.buffer.INativeBuffer;
|
import io.github.dsheirer.buffer.INativeBuffer;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||||
import io.github.dsheirer.source.SourceEvent;
|
import io.github.dsheirer.source.SourceEvent;
|
||||||
import io.github.dsheirer.source.SourceException;
|
import io.github.dsheirer.source.SourceException;
|
||||||
|
import io.github.dsheirer.source.tuner.LoggingTunerErrorListener;
|
||||||
import io.github.dsheirer.source.tuner.Tuner;
|
import io.github.dsheirer.source.tuner.Tuner;
|
||||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import io.github.dsheirer.source.tuner.test.TestTuner;
|
import io.github.dsheirer.source.tuner.test.TestTuner;
|
||||||
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||||
import io.github.dsheirer.spectrum.DFTSize;
|
import io.github.dsheirer.spectrum.DFTSize;
|
||||||
@@ -41,10 +40,18 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -56,7 +63,7 @@ public class ChannelizerViewer2 extends JFrame
|
|||||||
|
|
||||||
private static final int CHANNEL_BANDWIDTH = 12500;
|
private static final int CHANNEL_BANDWIDTH = 12500;
|
||||||
|
|
||||||
private SettingsManager mSettingsManager = new SettingsManager(new TunerConfigurationModel());
|
private SettingsManager mSettingsManager = new SettingsManager();
|
||||||
private JPanel mPrimaryPanel;
|
private JPanel mPrimaryPanel;
|
||||||
private JPanel mControlPanel;
|
private JPanel mControlPanel;
|
||||||
private JButton mTopFrameAddChannelButton;
|
private JButton mTopFrameAddChannelButton;
|
||||||
@@ -68,7 +75,7 @@ public class ChannelizerViewer2 extends JFrame
|
|||||||
private ChannelArrayPanel mBottomChannelArrayPanel;
|
private ChannelArrayPanel mBottomChannelArrayPanel;
|
||||||
private DFTSize mMainPanelDFTSize = DFTSize.FFT32768;
|
private DFTSize mMainPanelDFTSize = DFTSize.FFT32768;
|
||||||
private DFTSize mChannelPanelDFTSize = DFTSize.FFT04096;
|
private DFTSize mChannelPanelDFTSize = DFTSize.FFT04096;
|
||||||
private TestTuner mTestTuner = new TestTuner(new UserPreferences());
|
private TestTuner mTestTuner = new TestTuner(new LoggingTunerErrorListener());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GUI Test utility for researching polyphase channelizers.
|
* GUI Test utility for researching polyphase channelizers.
|
||||||
|
|||||||
@@ -20,18 +20,17 @@ package io.github.dsheirer.gui.channelizer;
|
|||||||
|
|
||||||
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
||||||
import io.github.dsheirer.buffer.INativeBuffer;
|
import io.github.dsheirer.buffer.INativeBuffer;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
|
||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||||
import io.github.dsheirer.source.SourceEvent;
|
import io.github.dsheirer.source.SourceEvent;
|
||||||
import io.github.dsheirer.source.SourceException;
|
import io.github.dsheirer.source.SourceException;
|
||||||
|
import io.github.dsheirer.source.tuner.LoggingTunerErrorListener;
|
||||||
import io.github.dsheirer.source.tuner.Tuner;
|
import io.github.dsheirer.source.tuner.Tuner;
|
||||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import io.github.dsheirer.source.tuner.test.TestTuner;
|
import io.github.dsheirer.source.tuner.test.TestTuner;
|
||||||
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||||
import io.github.dsheirer.spectrum.DFTSize;
|
import io.github.dsheirer.spectrum.DFTSize;
|
||||||
@@ -41,10 +40,16 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -58,7 +63,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
|||||||
private static final int CHANNEL_BANDWIDTH = 12500;
|
private static final int CHANNEL_BANDWIDTH = 12500;
|
||||||
private static final int CHANNEL_FFT_FRAME_RATE = 20;
|
private static final int CHANNEL_FFT_FRAME_RATE = 20;
|
||||||
|
|
||||||
private SettingsManager mSettingsManager = new SettingsManager(new TunerConfigurationModel());
|
private SettingsManager mSettingsManager = new SettingsManager();
|
||||||
private JPanel mPrimaryPanel;
|
private JPanel mPrimaryPanel;
|
||||||
private JPanel mControlPanel;
|
private JPanel mControlPanel;
|
||||||
private JLabel mToneFrequencyLabel;
|
private JLabel mToneFrequencyLabel;
|
||||||
@@ -77,7 +82,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
|||||||
*/
|
*/
|
||||||
public HeterodyneChannelizerViewer()
|
public HeterodyneChannelizerViewer()
|
||||||
{
|
{
|
||||||
mTestTuner = new TestTuner(new UserPreferences());
|
mTestTuner = new TestTuner(new LoggingTunerErrorListener());
|
||||||
mChannelCount = 5;
|
mChannelCount = 5;
|
||||||
mChannelsPerRow = 5;
|
mChannelsPerRow = 5;
|
||||||
init();
|
init();
|
||||||
@@ -516,7 +521,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TestTuner tuner = new TestTuner(new UserPreferences());
|
TestTuner tuner = new TestTuner(new LoggingTunerErrorListener());
|
||||||
|
|
||||||
List<TunerChannel> tunerChannels = getTunerChannels(tuner);
|
List<TunerChannel> tunerChannels = getTunerChannels(tuner);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import io.github.dsheirer.dsp.oscillator.OscillatorFactory;
|
|||||||
import io.github.dsheirer.sample.Listener;
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.settings.SettingsManager;
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||||
import io.github.dsheirer.spectrum.DFTSize;
|
import io.github.dsheirer.spectrum.DFTSize;
|
||||||
import io.github.dsheirer.spectrum.SpectrumPanel;
|
import io.github.dsheirer.spectrum.SpectrumPanel;
|
||||||
@@ -39,10 +38,15 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class SynthesizerViewer extends JFrame
|
public class SynthesizerViewer extends JFrame
|
||||||
@@ -54,7 +58,7 @@ public class SynthesizerViewer extends JFrame
|
|||||||
private static final int CHANNEL_FFT_FRAME_RATE = 20; //frames per second
|
private static final int CHANNEL_FFT_FRAME_RATE = 20; //frames per second
|
||||||
private static final int DATA_GENERATOR_FRAME_RATE = 50; //frames per second
|
private static final int DATA_GENERATOR_FRAME_RATE = 50; //frames per second
|
||||||
|
|
||||||
private SettingsManager mSettingsManager = new SettingsManager(new TunerConfigurationModel());
|
private SettingsManager mSettingsManager = new SettingsManager();
|
||||||
private JPanel mPrimaryPanel;
|
private JPanel mPrimaryPanel;
|
||||||
private PrimarySpectrumPanel mPrimarySpectrumPanel;
|
private PrimarySpectrumPanel mPrimarySpectrumPanel;
|
||||||
private ChannelPanel mChannel1Panel;
|
private ChannelPanel mChannel1Panel;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -14,7 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
* ****************************************************************************
|
||||||
|
*/
|
||||||
package io.github.dsheirer.gui.control;
|
package io.github.dsheirer.gui.control;
|
||||||
|
|
||||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||||
@@ -69,12 +70,6 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JFrequencyControl(long value)
|
|
||||||
{
|
|
||||||
this();
|
|
||||||
mFrequency = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
setLayout(new MigLayout("insets 0 0 0 0", "[]0[]", ""));
|
setLayout(new MigLayout("insets 0 0 0 0", "[]0[]", ""));
|
||||||
@@ -91,8 +86,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
}
|
}
|
||||||
catch(ParseException e)
|
catch(ParseException e)
|
||||||
{
|
{
|
||||||
mLog.error("JFrequencyControl - parse exception "
|
mLog.error("JFrequencyControl - parse exception constructing a digit - " + e);
|
||||||
+ "constructing a digit - " + e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(digit != null)
|
if(digit != null)
|
||||||
@@ -105,15 +99,11 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
|
|
||||||
if(x == 6)
|
if(x == 6)
|
||||||
{
|
{
|
||||||
JLabel period = new JLabel(".");
|
add(new JLabel(". "));
|
||||||
|
|
||||||
add(period);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add(new JLabel(" MHz"));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a blank cursor to use when the mouse is over the digits
|
* Create a blank cursor to use when the mouse is over the digits
|
||||||
*/
|
*/
|
||||||
@@ -123,11 +113,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
//Create image for cursor using empty array
|
//Create image for cursor using empty array
|
||||||
Image cursorImage = Toolkit.getDefaultToolkit().createImage(imageByte);
|
Image cursorImage = Toolkit.getDefaultToolkit().createImage(imageByte);
|
||||||
|
|
||||||
mBlankCursor = Toolkit.getDefaultToolkit()
|
mBlankCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImage, new Point(0, 0), "cursor");
|
||||||
.createCustomCursor(cursorImage, new Point(0, 0), "cursor");
|
|
||||||
|
|
||||||
setTooltip(false);
|
|
||||||
|
|
||||||
revalidate();
|
revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,26 +128,6 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTooltip(boolean locked)
|
|
||||||
{
|
|
||||||
String tooltip = null;
|
|
||||||
|
|
||||||
if(locked)
|
|
||||||
{
|
|
||||||
tooltip = "Frequency control is locked. Disable decoding channels to unlock.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tooltip = "Click on a frequency digit and type a frequency value, or click the upper/lower digits to " +
|
|
||||||
"change the value";
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Digit digit: mDigits.values())
|
|
||||||
{
|
|
||||||
digit.setToolTipText(tooltip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a frequency change event invoked by another control. We don't
|
* Receives a frequency change event invoked by another control. We don't
|
||||||
* rebroadcast this event, just set the control to indicate the new frequency.
|
* rebroadcast this event, just set the control to indicate the new frequency.
|
||||||
@@ -172,36 +138,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
switch(event.getEvent())
|
switch(event.getEvent())
|
||||||
{
|
{
|
||||||
case NOTIFICATION_FREQUENCY_CHANGE:
|
case NOTIFICATION_FREQUENCY_CHANGE:
|
||||||
EventQueue.invokeLater(new Runnable()
|
EventQueue.invokeLater(() -> setFrequency(event.getValue().longValue(), false));
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
setFrequency(event.getValue().longValue(), false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
|
|
||||||
EventQueue.invokeLater(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
setEnabled(false);
|
|
||||||
setTooltip(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
|
|
||||||
EventQueue.invokeLater(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
setEnabled(true);
|
|
||||||
setTooltip(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,11 +188,30 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the source event listener
|
||||||
|
* @param processor
|
||||||
|
*/
|
||||||
public void addListener(ISourceEventProcessor processor)
|
public void addListener(ISourceEventProcessor processor)
|
||||||
{
|
{
|
||||||
mProcessors.add(processor);
|
if(!mProcessors.contains(processor))
|
||||||
|
{
|
||||||
|
mProcessors.add(processor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all source event processors
|
||||||
|
*/
|
||||||
|
public void clearListeners()
|
||||||
|
{
|
||||||
|
mProcessors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the source event processor
|
||||||
|
* @param processor
|
||||||
|
*/
|
||||||
public void removeListener(ISourceEventProcessor processor)
|
public void removeListener(ISourceEventProcessor processor)
|
||||||
{
|
{
|
||||||
mProcessors.remove(processor);
|
mProcessors.remove(processor);
|
||||||
@@ -272,7 +228,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
super("0");
|
super("0");
|
||||||
|
|
||||||
mPower = position;
|
mPower = position;
|
||||||
|
setToolTipText(getTooltip(mPower));
|
||||||
Listener listener = new Listener();
|
Listener listener = new Listener();
|
||||||
|
|
||||||
this.addKeyListener(listener);
|
this.addKeyListener(listener);
|
||||||
@@ -280,6 +236,49 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
|||||||
this.addMouseWheelListener(listener);
|
this.addMouseWheelListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getTooltip(int power)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Center frequency ");
|
||||||
|
switch(power)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sb.append("1 Hertz");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sb.append("10 Hertz");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sb.append("100 Hertz");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
sb.append("1 Kilohertz");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
sb.append("10 Kilohertz");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
sb.append("100 Kilohertz");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
sb.append("1 Megahertz");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
sb.append("10 Megahertz");
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
sb.append("100 Megahertz");
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
sb.append("1 Gigahertz");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(" units. Type a number, use up/down arrows, or click the upper/lower digit control to adjust");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this digit to the value of the column in frequency that corresponds
|
* Sets this digit to the value of the column in frequency that corresponds
|
||||||
* to the power (ie column) set for this digit. Optionally, fires a
|
* to the power (ie column) set for this digit. Optionally, fires a
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
package io.github.dsheirer.gui.editor;
|
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class EmptyEditor<T> extends Editor<T>
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public EmptyEditor( String descriptor )
|
|
||||||
{
|
|
||||||
setLayout( new MigLayout( "insets 0 0 0 0", "[center]", "[grow]" ) );
|
|
||||||
add( new JLabel( "Please select " + descriptor ), "wrap" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmptyEditor()
|
|
||||||
{
|
|
||||||
this( "an item" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ******************************************************************************
|
* *****************************************************************************
|
||||||
* sdrtrunk
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
* Copyright (C) 2014-2019 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
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
* *****************************************************************************
|
* ****************************************************************************
|
||||||
*/
|
*/
|
||||||
package io.github.dsheirer.gui.instrument.decoder;
|
package io.github.dsheirer.gui.instrument.decoder;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
|||||||
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import io.github.dsheirer.util.TimeStamp;
|
import io.github.dsheirer.util.TimeStamp;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
@@ -65,6 +66,7 @@ public class PlaylistEditor extends BorderPane
|
|||||||
private static final Logger mLog = LoggerFactory.getLogger(PlaylistEditor.class);
|
private static final Logger mLog = LoggerFactory.getLogger(PlaylistEditor.class);
|
||||||
|
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
|
private TunerManager mTunerManager;
|
||||||
private UserPreferences mUserPreferences;
|
private UserPreferences mUserPreferences;
|
||||||
private MenuBar mMenuBar;
|
private MenuBar mMenuBar;
|
||||||
private TabPane mTabPane;
|
private TabPane mTabPane;
|
||||||
@@ -79,11 +81,13 @@ public class PlaylistEditor extends BorderPane
|
|||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager for alias and channel models
|
* @param playlistManager for alias and channel models
|
||||||
|
* @param tunerManager for tuners
|
||||||
* @param userPreferences for settings
|
* @param userPreferences for settings
|
||||||
*/
|
*/
|
||||||
public PlaylistEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public PlaylistEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
|
mTunerManager = tunerManager;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
|
|
||||||
//Throw a new runnable back onto the FX thread to lazy load the editor content after the editor has been
|
//Throw a new runnable back onto the FX thread to lazy load the editor content after the editor has been
|
||||||
@@ -240,7 +244,7 @@ public class PlaylistEditor extends BorderPane
|
|||||||
{
|
{
|
||||||
if(mChannelEditor == null)
|
if(mChannelEditor == null)
|
||||||
{
|
{
|
||||||
mChannelEditor = new ChannelEditor(mPlaylistManager, mUserPreferences);
|
mChannelEditor = new ChannelEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mChannelEditor;
|
return mChannelEditor;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
@@ -20,17 +20,12 @@
|
|||||||
package io.github.dsheirer.gui.playlist;
|
package io.github.dsheirer.gui.playlist;
|
||||||
|
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
|
||||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
|
||||||
import io.github.dsheirer.gui.JavaFxWindowManager;
|
import io.github.dsheirer.gui.JavaFxWindowManager;
|
||||||
import io.github.dsheirer.icon.IconModel;
|
import io.github.dsheirer.icon.IconModel;
|
||||||
import io.github.dsheirer.module.log.EventLogManager;
|
import io.github.dsheirer.module.log.EventLogManager;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.settings.SettingsManager;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.source.SourceManager;
|
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
|
||||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel;
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
@@ -43,6 +38,7 @@ public class PlaylistEditorApplication extends Application
|
|||||||
{
|
{
|
||||||
private Stage mStage;
|
private Stage mStage;
|
||||||
private Parent mPlaylistEditor;
|
private Parent mPlaylistEditor;
|
||||||
|
private TunerManager mTunerManager;
|
||||||
private UserPreferences mUserPreferences = new UserPreferences();
|
private UserPreferences mUserPreferences = new UserPreferences();
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
private JavaFxWindowManager mJavaFxWindowManager;
|
private JavaFxWindowManager mJavaFxWindowManager;
|
||||||
@@ -50,17 +46,13 @@ public class PlaylistEditorApplication extends Application
|
|||||||
public PlaylistEditorApplication()
|
public PlaylistEditorApplication()
|
||||||
{
|
{
|
||||||
AliasModel aliasModel = new AliasModel();
|
AliasModel aliasModel = new AliasModel();
|
||||||
BroadcastModel broadcastModel = new BroadcastModel(aliasModel, new IconModel(), mUserPreferences);
|
|
||||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
|
||||||
TunerConfigurationModel tunerConfigurationModel = new TunerConfigurationModel();
|
|
||||||
TunerModel tunerModel = new TunerModel(tunerConfigurationModel);
|
|
||||||
SourceManager sourceManager = new SourceManager(tunerModel, new SettingsManager(tunerConfigurationModel),
|
|
||||||
mUserPreferences);
|
|
||||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||||
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconModel());
|
mTunerManager = new TunerManager(mUserPreferences);
|
||||||
|
mTunerManager.start();
|
||||||
|
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, new IconModel());
|
||||||
|
|
||||||
mPlaylistManager.init();
|
mPlaylistManager.init();
|
||||||
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mPlaylistManager);
|
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mTunerManager, mPlaylistManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -77,7 +69,7 @@ public class PlaylistEditorApplication extends Application
|
|||||||
{
|
{
|
||||||
if(mPlaylistEditor == null)
|
if(mPlaylistEditor == null)
|
||||||
{
|
{
|
||||||
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mUserPreferences);
|
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mPlaylistEditor;
|
return mPlaylistEditor;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -34,6 +31,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@@ -59,11 +57,14 @@ public class AMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public AMConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public AMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getRecordPane());
|
getTitledPanesBox().getChildren().add(getRecordPane());
|
||||||
@@ -138,7 +139,7 @@ public class AMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
@@ -80,6 +80,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelConfigurationEditor.class);
|
private final static Logger mLog = LoggerFactory.getLogger(ChannelConfigurationEditor.class);
|
||||||
|
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
|
protected TunerManager mTunerManager;
|
||||||
protected UserPreferences mUserPreferences;
|
protected UserPreferences mUserPreferences;
|
||||||
protected EditorModificationListener mEditorModificationListener = new EditorModificationListener();
|
protected EditorModificationListener mEditorModificationListener = new EditorModificationListener();
|
||||||
private Button mPlayButton;
|
private Button mPlayButton;
|
||||||
@@ -100,9 +101,17 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
private IconNode mStopGraphicNode;
|
private IconNode mStopGraphicNode;
|
||||||
private ChannelProcessingMonitor mChannelProcessingMonitor = new ChannelProcessingMonitor();
|
private ChannelProcessingMonitor mChannelProcessingMonitor = new ChannelProcessingMonitor();
|
||||||
|
|
||||||
public ChannelConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
/**
|
||||||
|
* Constructs an instance
|
||||||
|
* @param playlistManager for playlists
|
||||||
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
|
*/
|
||||||
|
public ChannelConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
|
mTunerManager = tunerManager;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
|
|
||||||
setMaxWidth(Double.MAX_VALUE);
|
setMaxWidth(Double.MAX_VALUE);
|
||||||
@@ -236,11 +245,6 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
modifiedProperty().setValue(false);
|
modifiedProperty().setValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TunerModel getTunerModel()
|
|
||||||
{
|
|
||||||
return mPlaylistManager.getTunerModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save()
|
public void save()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -25,6 +22,7 @@ package io.github.dsheirer.gui.playlist.channel;
|
|||||||
import io.github.dsheirer.module.decode.DecoderType;
|
import io.github.dsheirer.module.decode.DecoderType;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -46,28 +44,28 @@ public class ChannelConfigurationEditorFactory
|
|||||||
* @return constructed editor
|
* @return constructed editor
|
||||||
*/
|
*/
|
||||||
public static ChannelConfigurationEditor getEditor(DecoderType decoderType, PlaylistManager playlistManager,
|
public static ChannelConfigurationEditor getEditor(DecoderType decoderType, PlaylistManager playlistManager,
|
||||||
UserPreferences userPreferences)
|
TunerManager tunerManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
switch(decoderType)
|
switch(decoderType)
|
||||||
{
|
{
|
||||||
case AM:
|
case AM:
|
||||||
return new AMConfigurationEditor(playlistManager, userPreferences);
|
return new AMConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case DMR:
|
case DMR:
|
||||||
return new DMRConfigurationEditor(playlistManager, userPreferences);
|
return new DMRConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case NBFM:
|
case NBFM:
|
||||||
return new NBFMConfigurationEditor(playlistManager, userPreferences);
|
return new NBFMConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case LTR_NET:
|
case LTR_NET:
|
||||||
return new LTRNetConfigurationEditor(playlistManager, userPreferences);
|
return new LTRNetConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case LTR:
|
case LTR:
|
||||||
return new LTRConfigurationEditor(playlistManager, userPreferences);
|
return new LTRConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case MPT1327:
|
case MPT1327:
|
||||||
return new MPT1327ConfigurationEditor(playlistManager, userPreferences);
|
return new MPT1327ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case PASSPORT:
|
case PASSPORT:
|
||||||
return new PassportConfigurationEditor(playlistManager, userPreferences);
|
return new PassportConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case P25_PHASE1:
|
case P25_PHASE1:
|
||||||
return new P25P1ConfigurationEditor(playlistManager, userPreferences);
|
return new P25P1ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
case P25_PHASE2:
|
case P25_PHASE2:
|
||||||
return new P25P2ConfigurationEditor(playlistManager, userPreferences);
|
return new P25P2ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
||||||
default:
|
default:
|
||||||
if(decoderType != null && !mLoggedUnrecognizedTypes.contains(decoderType))
|
if(decoderType != null && !mLoggedUnrecognizedTypes.contains(decoderType))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -28,6 +25,7 @@ import io.github.dsheirer.module.decode.DecoderFactory;
|
|||||||
import io.github.dsheirer.module.decode.DecoderType;
|
import io.github.dsheirer.module.decode.DecoderType;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -79,6 +77,7 @@ public class ChannelEditor extends SplitPane
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelEditor.class);
|
private final static Logger mLog = LoggerFactory.getLogger(ChannelEditor.class);
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
|
private TunerManager mTunerManager;
|
||||||
private UserPreferences mUserPreferences;
|
private UserPreferences mUserPreferences;
|
||||||
private TableView<Channel> mChannelTableView;
|
private TableView<Channel> mChannelTableView;
|
||||||
private Label mPlaceholderLabel;
|
private Label mPlaceholderLabel;
|
||||||
@@ -102,11 +101,12 @@ public class ChannelEditor extends SplitPane
|
|||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager containing playlists and channel configurations
|
* @param playlistManager containing playlists and channel configurations
|
||||||
*/
|
*/
|
||||||
public ChannelEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public ChannelEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
|
mTunerManager = tunerManager;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
mUnknownConfigurationEditor = new UnknownConfigurationEditor(mPlaylistManager, userPreferences);
|
mUnknownConfigurationEditor = new UnknownConfigurationEditor(mPlaylistManager, mTunerManager, userPreferences);
|
||||||
|
|
||||||
HBox channelsBox = new HBox();
|
HBox channelsBox = new HBox();
|
||||||
channelsBox.setSpacing(10.0);
|
channelsBox.setSpacing(10.0);
|
||||||
@@ -203,7 +203,7 @@ public class ChannelEditor extends SplitPane
|
|||||||
if(editor == null)
|
if(editor == null)
|
||||||
{
|
{
|
||||||
editor = ChannelConfigurationEditorFactory.getEditor(channelDecoderType, mPlaylistManager,
|
editor = ChannelConfigurationEditorFactory.getEditor(channelDecoderType, mPlaylistManager,
|
||||||
mUserPreferences);
|
mTunerManager, mUserPreferences);
|
||||||
|
|
||||||
if(editor != null)
|
if(editor != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -40,6 +37,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
@@ -96,11 +94,14 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public DMRConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public DMRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
@@ -240,7 +241,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel(),
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager,
|
||||||
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
||||||
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
||||||
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
DecodeConfigDMR.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -39,6 +36,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@@ -74,12 +72,14 @@ public class LTRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
* @param userPreferences
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public LTRConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public LTRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
@@ -210,7 +210,7 @@ public class LTRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -39,6 +36,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@@ -74,12 +72,13 @@ public class LTRNetConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
* @param userPreferences
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public LTRNetConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public LTRNetConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
@@ -210,7 +209,7 @@ public class LTRNetConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -40,6 +37,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
@@ -84,12 +82,14 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
* @param userPreferences
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public MPT1327ConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public MPT1327ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
@@ -195,7 +195,7 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel(),
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager,
|
||||||
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
||||||
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
||||||
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
DecodeConfigMPT1327.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -42,6 +39,7 @@ import io.github.dsheirer.protocol.Protocol;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
@@ -92,12 +90,14 @@ public class NBFMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
* @param userPreferences
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public NBFMConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public NBFMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
@@ -228,7 +228,7 @@ public class NBFMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -38,6 +35,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
@@ -80,12 +78,14 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param playlistManager
|
* @param playlistManager for playlists
|
||||||
* @param userPreferences
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public P25P1ConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public P25P1ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
@@ -191,7 +191,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel(),
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager,
|
||||||
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_MINIMUM_MS,
|
||||||
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_MAXIMUM_MS,
|
||||||
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
DecodeConfigP25Phase1.CHANNEL_ROTATION_DELAY_DEFAULT_MS);
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -39,6 +36,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@@ -73,9 +71,10 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param playlistManager
|
* @param playlistManager
|
||||||
* @param userPreferences
|
* @param userPreferences
|
||||||
*/
|
*/
|
||||||
public P25P2ConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public P25P2ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
@@ -179,7 +178,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -38,6 +35,7 @@ import io.github.dsheirer.preference.UserPreferences;
|
|||||||
import io.github.dsheirer.record.RecorderType;
|
import io.github.dsheirer.record.RecorderType;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TitledPane;
|
import javafx.scene.control.TitledPane;
|
||||||
@@ -69,9 +67,10 @@ public class PassportConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param playlistManager
|
* @param playlistManager
|
||||||
* @param userPreferences
|
* @param userPreferences
|
||||||
*/
|
*/
|
||||||
public PassportConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public PassportConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
@@ -155,7 +154,7 @@ public class PassportConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
{
|
{
|
||||||
if(mSourceConfigurationEditor == null)
|
if(mSourceConfigurationEditor == null)
|
||||||
{
|
{
|
||||||
mSourceConfigurationEditor = new FrequencyEditor(getTunerModel());
|
mSourceConfigurationEditor = new FrequencyEditor(mTunerManager);
|
||||||
|
|
||||||
//Add a listener so that we can push change notifications up to this editor
|
//Add a listener so that we can push change notifications up to this editor
|
||||||
mSourceConfigurationEditor.modifiedProperty()
|
mSourceConfigurationEditor.modifiedProperty()
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.channel;
|
package io.github.dsheirer.gui.playlist.channel;
|
||||||
@@ -30,6 +27,7 @@ import io.github.dsheirer.playlist.PlaylistManager;
|
|||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.scene.control.TitledPane;
|
import javafx.scene.control.TitledPane;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -46,9 +44,10 @@ public class UnknownConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param aliasModel
|
* @param aliasModel
|
||||||
*/
|
*/
|
||||||
public UnknownConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public UnknownConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(playlistManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences);
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
* Copyright (C) 2014-2022 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
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2022 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.gui.playlist.source;
|
package io.github.dsheirer.gui.playlist.source;
|
||||||
@@ -25,8 +22,8 @@ package io.github.dsheirer.gui.playlist.source;
|
|||||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||||
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
||||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
|
||||||
import io.github.dsheirer.source.tuner.channel.rotation.ChannelRotationMonitor;
|
import io.github.dsheirer.source.tuner.channel.rotation.ChannelRotationMonitor;
|
||||||
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -59,7 +56,7 @@ public class FrequencyEditor extends SourceConfigurationEditor<SourceConfigurati
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(FrequencyEditor.class);
|
private final static Logger mLog = LoggerFactory.getLogger(FrequencyEditor.class);
|
||||||
private static final String NONE = "(none) ";
|
private static final String NONE = "(none) ";
|
||||||
private TunerModel mTunerModel;
|
private TunerManager mTunerManager;
|
||||||
private FrequencyBox mPrimaryFrequencyBox;
|
private FrequencyBox mPrimaryFrequencyBox;
|
||||||
private ObservableList<FrequencyBox> mFrequencyBoxes = FXCollections.observableArrayList();
|
private ObservableList<FrequencyBox> mFrequencyBoxes = FXCollections.observableArrayList();
|
||||||
private ComboBox<String> mPreferredTunerComboBox;
|
private ComboBox<String> mPreferredTunerComboBox;
|
||||||
@@ -75,13 +72,13 @@ public class FrequencyEditor extends SourceConfigurationEditor<SourceConfigurati
|
|||||||
* define constraints for the channel rotation delay monitor, how long the monitor dwells on each frequency in a
|
* define constraints for the channel rotation delay monitor, how long the monitor dwells on each frequency in a
|
||||||
* multi-frequency configuration.
|
* multi-frequency configuration.
|
||||||
*
|
*
|
||||||
* @param tunerModel for accessing list of tuners to select a preferred tuner
|
* @param tunerManager for accessing list of tuners to select a preferred tuner
|
||||||
* @param minRotationDelay in milliseconds for channel/frequency dwell
|
* @param minRotationDelay in milliseconds for channel/frequency dwell
|
||||||
* @param maxRotationDelay in milliseconds for channel/frequency dwell
|
* @param maxRotationDelay in milliseconds for channel/frequency dwell
|
||||||
*/
|
*/
|
||||||
public FrequencyEditor(TunerModel tunerModel, int minRotationDelay, int maxRotationDelay, int defaultRotationDelay)
|
public FrequencyEditor(TunerManager tunerManager, int minRotationDelay, int maxRotationDelay, int defaultRotationDelay)
|
||||||
{
|
{
|
||||||
mTunerModel = tunerModel;
|
mTunerManager = tunerManager;
|
||||||
mAllowMultipleFrequencies = true;
|
mAllowMultipleFrequencies = true;
|
||||||
mFrequencyRotationMinimum = minRotationDelay;
|
mFrequencyRotationMinimum = minRotationDelay;
|
||||||
mFrequencyRotationMaximum = maxRotationDelay;
|
mFrequencyRotationMaximum = maxRotationDelay;
|
||||||
@@ -91,11 +88,11 @@ public class FrequencyEditor extends SourceConfigurationEditor<SourceConfigurati
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance with a default behavior of single frequency support only.
|
* Constructs an instance with a default behavior of single frequency support only.
|
||||||
* @param tunerModel for accessing list of tuners to select a preferred tuner
|
* @param tunerManager for accessing list of tuners to select a preferred tuner
|
||||||
*/
|
*/
|
||||||
public FrequencyEditor(TunerModel tunerModel)
|
public FrequencyEditor(TunerManager tunerManager)
|
||||||
{
|
{
|
||||||
mTunerModel = tunerModel;
|
mTunerManager = tunerManager;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,9 +330,9 @@ public class FrequencyEditor extends SourceConfigurationEditor<SourceConfigurati
|
|||||||
getPreferredTunerComboBox().getItems().clear();
|
getPreferredTunerComboBox().getItems().clear();
|
||||||
getPreferredTunerComboBox().getItems().add(NONE);
|
getPreferredTunerComboBox().getItems().add(NONE);
|
||||||
|
|
||||||
if(mTunerModel != null)
|
if(mTunerManager != null)
|
||||||
{
|
{
|
||||||
getPreferredTunerComboBox().getItems().addAll(mTunerModel.getTunerNames());
|
getPreferredTunerComboBox().getItems().addAll(mTunerManager.getPreferredTunerNames());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user