Compare commits

..

4 Commits

22 changed files with 592 additions and 386 deletions

2
.idea/misc.xml generated
View File

@@ -4,7 +4,7 @@
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="liberica-18.0.1-fx" project-jdk-type="JavaSDK"> <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>

View File

@@ -28,7 +28,7 @@ repositories {
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
} }
version = '0.5.0-beta5' 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,33 +56,33 @@ 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.13.2' 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'
@@ -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-18.0.1-full' String jdk_linux_aarch64 = jdk_base + 'linux-arm64/jdk-19.0.1-full'
String jdk_linux_x86_64 = jdk_base + 'linux-x64/jdk-18.0.1-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-18.0.1-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-18.0.1-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-18.0.1-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/18.0.1+12/bellsoft-jdk18.0.1+12-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/18.0.1+12/bellsoft-jdk18.0.1+12-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/18.0.1+12/bellsoft-jdk18.0.1+12-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/18.0.1+12/bellsoft-jdk18.0.1+12-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/18.0.1+12/bellsoft-jdk18.0.1+12-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

Binary file not shown.

View File

@@ -19,6 +19,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.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
View File

@@ -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
View File

@@ -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

View File

@@ -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,21 +14,20 @@
* *
* 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.module.log; package io.github.dsheirer.module.log;
import io.github.dsheirer.module.Module; import io.github.dsheirer.module.Module;
import io.github.dsheirer.util.TimeStamp; import io.github.dsheirer.util.TimeStamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.nio.file.Path; import java.nio.file.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class EventLogger extends Module public abstract class EventLogger extends Module
{ {
@@ -78,9 +77,6 @@ public abstract class EventLogger extends Module
sb.append(mFileNameSuffix); sb.append(mFileNameSuffix);
mLogFileName = sb.toString(); mLogFileName = sb.toString();
mLog.info("Creating log file:" + mLogFileName);
mLogFile = new OutputStreamWriter(new FileOutputStream(mLogFileName)); mLogFile = new OutputStreamWriter(new FileOutputStream(mLogFileName));
write(getHeader()); write(getHeader());

View File

@@ -1,26 +1,26 @@
/******************************************************************************* /*
* 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.settings; package io.github.dsheirer.settings;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.awt.Color;
import java.awt.*;
public class ColorSetting extends Setting public class ColorSetting extends Setting
{ {
@@ -91,7 +91,7 @@ public class ColorSetting extends Setting
return new Color(temp.getRed(), return new Color(temp.getRed(),
temp.getGreen(), temp.getGreen(),
temp.getBlue(), temp.getBlue(),
mAlpha); getColorSettingName().getTranslucency());
} }
public void setColor(Color color) public void setColor(Color color)
@@ -111,84 +111,81 @@ public class ColorSetting extends Setting
public enum ColorSettingName public enum ColorSettingName
{ {
CHANNEL_CONFIG(getTranslucent(Color.LIGHT_GRAY, CONFIG_TRANSLUCENCY), CHANNEL_CONFIG(Color.LIGHT_GRAY, CONFIG_TRANSLUCENCY, "Channel", "Channel Color"),
"Channel", "Channel Color"), CHANNEL_CONFIG_PROCESSING(Color.GREEN, CONFIG_TRANSLUCENCY, "Channel Processing", "Processing Channel Color"),
CHANNEL_CONFIG_PROCESSING(getTranslucent(Color.GREEN, CONFIG_TRANSLUCENCY), CHANNEL_CONFIG_SELECTED(Color.BLUE, CONFIG_TRANSLUCENCY, "Channel Selected", "Selected Channel Color"),
"Channel Processing", "Processing Channel Color"), CHANNEL_STATE_BACKGROUND(Color.BLACK, NO_TRANSLUCENCY, "Background", "Channel State Background"),
CHANNEL_CONFIG_SELECTED(getTranslucent(Color.BLUE, CONFIG_TRANSLUCENCY), CHANNEL_STATE_GRADIENT_TOP_CALL(Color.BLACK, NO_TRANSLUCENCY, "Call Gradient Top", "Channel Call State Gradient Top"),
"Channel Selected", "Selected Channel Color"), CHANNEL_STATE_GRADIENT_MIDDLE_CALL(Color.BLUE, NO_TRANSLUCENCY, "Call Gradient Middle", "Channel Call State Gradient Middle"),
CHANNEL_STATE_GRADIENT_TOP_CONTROL(Color.BLACK, NO_TRANSLUCENCY, "Control Gradient Top", "Channel Control State Gradient Top"),
CHANNEL_STATE_BACKGROUND(Color.BLACK, "Background", CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL(new Color(0xC64F00), NO_TRANSLUCENCY, "Control Gradient Middle", "Channel Control State Gradient Middle"),
"Channel State Background"), CHANNEL_STATE_GRADIENT_TOP_DATA(Color.BLACK, NO_TRANSLUCENCY, "Data Gradient Top", "Channel Data State Gradient Top"),
CHANNEL_STATE_GRADIENT_TOP_CALL(Color.BLACK, CHANNEL_STATE_GRADIENT_MIDDLE_DATA(new Color(0xCC00CC), NO_TRANSLUCENCY, "Data Gradient Middle", "Channel Data State Gradient Middle"),
"Call Gradient Top", "Channel Call State Gradient Top"), CHANNEL_STATE_GRADIENT_TOP_FADE(Color.BLACK, NO_TRANSLUCENCY, "Fade Gradient Top", "Channel Fade State Gradient Top"),
CHANNEL_STATE_GRADIENT_MIDDLE_CALL(Color.BLUE, CHANNEL_STATE_GRADIENT_MIDDLE_FADE(Color.DARK_GRAY, NO_TRANSLUCENCY, "Fade Gradient Middle", "Channel Fade State Gradient Middle"),
"Call Gradient Middle", "Channel Call State Gradient Middle"), CHANNEL_STATE_GRADIENT_TOP_IDLE(Color.BLACK, NO_TRANSLUCENCY, "Idle Gradient Top", "Channel Idle State Gradient Top"),
CHANNEL_STATE_GRADIENT_TOP_CONTROL(Color.BLACK, CHANNEL_STATE_GRADIENT_MIDDLE_IDLE(Color.DARK_GRAY, NO_TRANSLUCENCY, "Idle Gradient Middle", "Channel Idle State Gradient Middle"),
"Control Gradient Top", "Channel Control State Gradient Top"), CHANNEL_STATE_GRADIENT_TOP_NO_TUNER(Color.RED, NO_TRANSLUCENCY, "No Tuner Gradient Top", "Channel No Tuner State Gradient Top"),
CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL(new Color(0xC64F00), CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER(new Color(0x990000), NO_TRANSLUCENCY, "No Tuner Gradient Middle", "Channel No Tuner State Gradient Middle"),
"Control Gradient Middle", "Channel Control State Gradient Middle"), CHANNEL_STATE_LABEL_DETAILS(Color.LIGHT_GRAY, NO_TRANSLUCENCY, "Details", "Details Label Color"),
CHANNEL_STATE_GRADIENT_TOP_DATA(Color.BLACK, CHANNEL_STATE_LABEL_DECODER(Color.GREEN, NO_TRANSLUCENCY, "Decoder", "Decoder Label Color"),
"Data Gradient Top", "Channel Data State Gradient Top"), CHANNEL_STATE_LABEL_AUX_DECODER(Color.YELLOW, NO_TRANSLUCENCY, "Aux Decoder", "Aux Decoder Label Color"),
CHANNEL_STATE_GRADIENT_MIDDLE_DATA(new Color(0xCC00CC), CHANNEL_STATE_SELECTED_CHANNEL(Color.YELLOW, NO_TRANSLUCENCY, "Selected Channel Indicator", "Selected Channel Indicator Color"),
"Data Gradient Middle", "Channel Data State Gradient Middle"), SPECTRUM_BACKGROUND(Color.BLACK, NO_TRANSLUCENCY, "Background", "Spectrum Background Color"),
CHANNEL_STATE_GRADIENT_TOP_FADE(Color.BLACK, SPECTRUM_CURSOR(Color.ORANGE, NO_TRANSLUCENCY, "Cursor", "Spectrum Cursor Color"),
"Fade Gradient Top", "Channel Fade State Gradient Top"), SPECTRUM_GRADIENT_BOTTOM(Color.GREEN, SPECTRUM_TRANSLUCENCY, "Gradient Bottom", "Spectrum Gradient Bottom Color"),
CHANNEL_STATE_GRADIENT_MIDDLE_FADE(Color.DARK_GRAY, SPECTRUM_GRADIENT_TOP(Color.WHITE, SPECTRUM_TRANSLUCENCY, "Gradient Top", "Spectrum Gradient Top Color"),
"Fade Gradient Middle", "Channel Fade State Gradient Middle"), SPECTRUM_LINE(Color.LIGHT_GRAY, SPECTRUM_TRANSLUCENCY, "Line", "Spectrum Lines and Text Color"),
CHANNEL_STATE_GRADIENT_TOP_IDLE(Color.BLACK, UNKNOWN(Color.RED, NO_TRANSLUCENCY,"Unknown", "Unknown Setting Color");
"Idle Gradient Top", "Channel Idle State Gradient Top"),
CHANNEL_STATE_GRADIENT_MIDDLE_IDLE(Color.DARK_GRAY,
"Idle Gradient Middle", "Channel Idle State Gradient Middle"),
CHANNEL_STATE_GRADIENT_TOP_NO_TUNER(Color.RED,
"No Tuner Gradient Top", "Channel No Tuner State Gradient Top"),
CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER(new Color(0x990000),
"No Tuner Gradient Middle", "Channel No Tuner State Gradient Middle"),
CHANNEL_STATE_LABEL_DETAILS(Color.LIGHT_GRAY,
"Details", "Details Label Color"),
CHANNEL_STATE_LABEL_DECODER(Color.GREEN,
"Decoder", "Decoder Label Color"),
CHANNEL_STATE_LABEL_AUX_DECODER(Color.YELLOW,
"Aux Decoder", "Aux Decoder Label Color"),
CHANNEL_STATE_SELECTED_CHANNEL(Color.YELLOW,
"Selected Channel Indicator", "Selected Channel Indicator Color"),
SPECTRUM_BACKGROUND(Color.BLACK,
"Background", "Spectrum Background Color"),
SPECTRUM_CURSOR(Color.ORANGE,
"Cursor", "Spectrum Cursor Color"),
SPECTRUM_GRADIENT_BOTTOM(getTranslucent(Color.GREEN, SPECTRUM_TRANSLUCENCY),
"Gradient Bottom", "Spectrum Gradient Bottom Color"),
SPECTRUM_GRADIENT_TOP(getTranslucent(Color.WHITE, SPECTRUM_TRANSLUCENCY),
"Gradient Top", "Spectrum Gradient Top Color"),
SPECTRUM_LINE(getTranslucent(Color.LIGHT_GRAY, SPECTRUM_TRANSLUCENCY),
"Line", "Spectrum Lines and Text Color"),
UNKNOWN(Color.RED, "Unknown", "Unknown Setting Color");
private Color mDefaultColor; private Color mDefaultColor;
private int mTranslucency;
private String mLabel; private String mLabel;
private String mDialogTitle; private String mDialogTitle;
private ColorSettingName(Color defaultColor, /**
String label, * Enumeration of color names used in user interface, primarily in the spectral displays.
String dialogTitle) * @param defaultColor to use and for resets.
* @param translucency value for the color.
* @param label for menu items
* @param dialogTitle for selecting in the color chooser.
*/
ColorSettingName(Color defaultColor, int translucency, String label, String dialogTitle)
{ {
mDefaultColor = defaultColor; mDefaultColor = defaultColor;
mTranslucency = translucency;
mLabel = label; mLabel = label;
mDialogTitle = dialogTitle; mDialogTitle = dialogTitle;
} }
/**
* Default color to use when resetting to default.
*/
public Color getDefaultColor() public Color getDefaultColor()
{ {
return mDefaultColor; return mDefaultColor;
} }
/**
* Translucency to apply to the color
*/
public int getTranslucency()
{
return mTranslucency;
}
/**
* Label for the setting
*/
public String getLabel() public String getLabel()
{ {
return mLabel; return mLabel;
} }
/**
* Title to use in dialogs
* @return title
*/
public String getDialogTitle() public String getDialogTitle()
{ {
return mDialogTitle; return mDialogTitle;

View File

@@ -197,7 +197,7 @@ public class SourceEvent
/** /**
* Creates a new locked state change event * Creates a new locked state change event
*/ */
public static SourceEvent lockedState() public static SourceEvent lockedSampleRateState()
{ {
return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED, 1); return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED, 1);
} }
@@ -205,7 +205,7 @@ public class SourceEvent
/** /**
* Creates a new unlocked state change event * Creates a new unlocked state change event
*/ */
public static SourceEvent unlockedState() public static SourceEvent unlockedSampleRateState()
{ {
return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED, 0); return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED, 0);
} }

View File

@@ -36,11 +36,11 @@ import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.frequency.FrequencyController; import io.github.dsheirer.source.tuner.frequency.FrequencyController;
import io.github.dsheirer.source.tuner.frequency.FrequencyController.Tunable; import io.github.dsheirer.source.tuner.frequency.FrequencyController.Tunable;
import io.github.dsheirer.source.tuner.manager.FrequencyErrorCorrectionManager; import io.github.dsheirer.source.tuner.manager.FrequencyErrorCorrectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class TunerController implements Tunable, ISourceEventProcessor, ISourceEventListener, public abstract class TunerController implements Tunable, ISourceEventProcessor, ISourceEventListener,
INativeBufferProvider, Listener<INativeBuffer>, ITunerErrorListener INativeBufferProvider, Listener<INativeBuffer>, ITunerErrorListener
@@ -70,6 +70,17 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
mFrequencyErrorCorrectionManager = new FrequencyErrorCorrectionManager(this); mFrequencyErrorCorrectionManager = new FrequencyErrorCorrectionManager(this);
} }
/**
* Lock for the frequency controller. This should only be used by the channel source manager to lock access to the
* frequency controller while creating a channel source, to block multi-threaded access to the frequency controller
* which might put the center tuned frequency value in an indeterminant state.
* @return frequency controller lock
*/
public ReentrantLock getFrequencyControllerLock()
{
return mFrequencyController.getFrequencyControllerLock();
}
/** /**
* Frequency correction manager for this tuner controller. * Frequency correction manager for this tuner controller.
*/ */
@@ -182,29 +193,30 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
} }
/** /**
* Indicates if the frequency and sample rate controls are locked by another process. User interface controls * Indicates if the sample rate control is locked by another process. User interface controls should monitor source
* should monitor source events and check the locked state via this method to correctly render the enabled state * events and check the locked state via this method to correctly render the enabled state of the sample rate control.
* of the frequency and sample rate controls.
* *
* @return true if the tuner controller is locked. * @return true if the tuner controller is locked.
*/ */
public boolean isLocked() public boolean isLockedSampleRate()
{ {
return mFrequencyController.isLocked(); //Note: this access is not protected by the mFrequencyControllerLock
return mFrequencyController.isSampleRateLocked();
} }
/** /**
* Sets the frequency and sample rate locked state to the locked argument value. This should only be changed * Sets the sample rate locked state to the locked argument value. This should only be changed by a downstream
* by a downstream consumer of samples to prevent users or other processes from modifying the center frequency * consumer of samples to prevent users or other processes from modifying the sample rate of the tuner while
* and/or sample rate of the tuner while processing samples. * processing samples.
* *
* @param locked true to indicate the tuner controller is in a locked state, otherwise false. * @param locked true to indicate the tuner controller is in a locked state, otherwise false.
*/ */
public void setLocked(boolean locked) public void setLockedSampleRate(boolean locked)
{ {
try try
{ {
mFrequencyController.setLocked(locked); //Note: this access is not protected by the mFrequencyControllerLock
mFrequencyController.setSampleRateLocked(locked);
} }
catch(SourceException se) catch(SourceException se)
{ {
@@ -214,6 +226,7 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
public int getBandwidth() public int getBandwidth()
{ {
//Note: this access is not protected by the mFrequencyControllerLock
return mFrequencyController.getBandwidth(); return mFrequencyController.getBandwidth();
} }
@@ -225,7 +238,15 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public void setFrequency(long frequency) throws SourceException public void setFrequency(long frequency) throws SourceException
{ {
mFrequencyController.setFrequency(frequency); try
{
getFrequencyControllerLock().lock();
mFrequencyController.setFrequency(frequency);
}
finally
{
getFrequencyControllerLock().unlock();
}
} }
/** /**
@@ -235,28 +256,73 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public long getFrequency() public long getFrequency()
{ {
return mFrequencyController.getFrequency(); long frequency;
try
{
getFrequencyControllerLock().lock();
frequency = mFrequencyController.getFrequency();
}
finally
{
getFrequencyControllerLock().unlock();
}
return frequency;
} }
@Override @Override
public boolean canTune(long frequency) public boolean canTune(long frequency)
{ {
return mFrequencyController.canTune(frequency); boolean canTune;
try
{
getFrequencyControllerLock().lock();
canTune = mFrequencyController.canTune(frequency);
}
finally
{
getFrequencyControllerLock().unlock();
}
return canTune;
} }
public double getSampleRate() public double getSampleRate()
{ {
//Note: this access is not protected by the mFrequencyControllerLock
return mFrequencyController.getSampleRate(); return mFrequencyController.getSampleRate();
} }
public double getFrequencyCorrection() public double getFrequencyCorrection()
{ {
return mFrequencyController.getFrequencyCorrection(); double correction;
try
{
getFrequencyControllerLock().lock();
correction = mFrequencyController.getFrequencyCorrection();
}
finally
{
getFrequencyControllerLock().unlock();
}
return correction;
} }
public void setFrequencyCorrection(double correction) throws SourceException public void setFrequencyCorrection(double correction) throws SourceException
{ {
mFrequencyController.setFrequencyCorrection(correction); try
{
getFrequencyControllerLock().lock();
mFrequencyController.setFrequencyCorrection(correction);
}
finally
{
getFrequencyControllerLock().unlock();
}
} }
/** /**
@@ -265,7 +331,19 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public long getMinimumFrequency() public long getMinimumFrequency()
{ {
return mFrequencyController.getMinimumFrequency(); long minimum;
try
{
getFrequencyControllerLock().lock();
minimum = mFrequencyController.getMinimumFrequency();
}
finally
{
getFrequencyControllerLock().unlock();
}
return minimum;
} }
/** /**
@@ -274,7 +352,15 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public void setMinimumFrequency(long minimum) public void setMinimumFrequency(long minimum)
{ {
mFrequencyController.setMinimumFrequency(minimum); try
{
getFrequencyControllerLock().lock();
mFrequencyController.setMinimumFrequency(minimum);
}
finally
{
getFrequencyControllerLock().unlock();
}
} }
/** /**
@@ -283,7 +369,19 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public long getMaximumFrequency() public long getMaximumFrequency()
{ {
return mFrequencyController.getMaximumFrequency(); long maximum;
try
{
getFrequencyControllerLock().lock();
maximum = mFrequencyController.getMaximumFrequency();
}
finally
{
getFrequencyControllerLock().unlock();
}
return maximum;
} }
/** /**
@@ -292,17 +390,49 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public void setMaximumFrequency(long maximum) public void setMaximumFrequency(long maximum)
{ {
mFrequencyController.setMaximumFrequency(maximum); try
{
getFrequencyControllerLock().lock();
mFrequencyController.setMaximumFrequency(maximum);
}
finally
{
getFrequencyControllerLock().unlock();
}
} }
public long getMinTunedFrequency() throws SourceException public long getMinTunedFrequency() throws SourceException
{ {
return mFrequencyController.getFrequency() - (getUsableBandwidth() / 2); long minTuned;
try
{
getFrequencyControllerLock().lock();
minTuned = mFrequencyController.getFrequency() - (getUsableBandwidth() / 2);
}
finally
{
getFrequencyControllerLock().unlock();
}
return minTuned;
} }
public long getMaxTunedFrequency() throws SourceException public long getMaxTunedFrequency() throws SourceException
{ {
return mFrequencyController.getFrequency() + (getUsableBandwidth() / 2); long maxTuned;
try
{
getFrequencyControllerLock().lock();
maxTuned = mFrequencyController.getFrequency() + (getUsableBandwidth() / 2);
}
finally
{
getFrequencyControllerLock().unlock();
}
return maxTuned;
} }
/** /**
@@ -425,7 +555,7 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public void addListener( ISourceEventProcessor processor ) public void addListener( ISourceEventProcessor processor )
{ {
mFrequencyController.addListener(processor); mFrequencyController.addSourceEventProcessor(processor);
} }
/** /**
@@ -433,7 +563,7 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
*/ */
public void removeListener( ISourceEventProcessor processor ) public void removeListener( ISourceEventProcessor processor )
{ {
mFrequencyController.removeFrequencyChangeProcessor(processor); mFrequencyController.removeSourceEventProcessor(processor);
} }
/** /**

View File

@@ -25,6 +25,9 @@ import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
import io.github.dsheirer.source.tuner.manager.TunerManager; import io.github.dsheirer.source.tuner.manager.TunerManager;
import io.github.dsheirer.source.tuner.manager.TunerStatus; import io.github.dsheirer.source.tuner.manager.TunerStatus;
import io.github.dsheirer.source.tuner.ui.TunerEditor; import io.github.dsheirer.source.tuner.ui.TunerEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -40,9 +43,6 @@ import javax.swing.JSlider;
import javax.swing.SpinnerNumberModel; 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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
/** /**
* Airspy tuner editor/controller * Airspy tuner editor/controller
@@ -102,7 +102,7 @@ public class AirspyTunerEditor extends TunerEditor<AirspyTuner, AirspyTunerConfi
getTunerStatusLabel().setText(status); getTunerStatusLabel().setText(status);
getButtonPanel().updateControls(); getButtonPanel().updateControls();
getFrequencyPanel().updateControls(); getFrequencyPanel().updateControls();
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLocked()); getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getTunerInfoButton().setEnabled(hasTuner()); getTunerInfoButton().setEnabled(hasTuner());
updateGainComponents((hasTuner() && hasConfiguration()) ? getConfiguration().getGain() : null); updateGainComponents((hasTuner() && hasConfiguration()) ? getConfiguration().getGain() : null);
@@ -626,7 +626,7 @@ public class AirspyTunerEditor extends TunerEditor<AirspyTuner, AirspyTunerConfi
*/ */
private void updateSampleRateToolTip() private void updateSampleRateToolTip()
{ {
if(hasTuner() && getTuner().getController().isLocked()) if(hasTuner() && getTuner().getController().isLockedSampleRate())
{ {
mSampleRateCombo.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock."); mSampleRateCombo.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
} }

View File

@@ -22,12 +22,11 @@ import io.github.dsheirer.source.ISourceEventProcessor;
import io.github.dsheirer.source.InvalidFrequencyException; import io.github.dsheirer.source.InvalidFrequencyException;
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 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.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FrequencyController public class FrequencyController
{ {
@@ -40,8 +39,12 @@ public class FrequencyController
private long mMaximumFrequency = 0; private long mMaximumFrequency = 0;
private double mFrequencyCorrection = 0.0d; private double mFrequencyCorrection = 0.0d;
private double mSampleRate = 0.0d; private double mSampleRate = 0.0d;
private boolean mLocked = false; private boolean mSampleRateLocked = false;
private List<ISourceEventProcessor> mProcessors = new ArrayList<>(); private List<ISourceEventProcessor> mProcessors = new ArrayList<>();
/**
* Lock protecting access to frequency control plane, source event processor subscriptions and event broadcasting
*/
private ReentrantLock mLock = new ReentrantLock(); private ReentrantLock mLock = new ReentrantLock();
/** /**
@@ -53,6 +56,15 @@ public class FrequencyController
mTunable = tunable; mTunable = tunable;
} }
/**
* Lock for controlling access to frequency control plane, event processor subscriptions and source event broadcasts.
*/
public ReentrantLock getFrequencyControllerLock()
{
return mLock;
}
/** /**
* Prepare for disposal of this instance. * Prepare for disposal of this instance.
*/ */
@@ -63,36 +75,36 @@ public class FrequencyController
} }
/** /**
* Indicates if this frequency controller is locked by a remote process. A locked state indicates that neither * Indicates if the sample rate for this frequency controller is locked by a remote process. A locked state
* the frequency nor the sample rate should be changed. The remote process will typically be a downstream * indicates that the sample rate cannot be changed. The remote process will typically be a downstream
* consumer of the data produced by the device being controlled (ie polyphase channelizer) that does not want * consumer of the data produced by the device being controlled (ie polyphase channelizer) that does not want
* the sample rate or frequency to be changed while processing is ongoing. * the sample rate to be changed while processing (ie channels have been allocated) is ongoing.
* *
* @return true if locked or false if not locked. * @return true if locked or false if not locked.
*/ */
public boolean isLocked() public boolean isSampleRateLocked()
{ {
return mLocked; return mSampleRateLocked;
} }
/** /**
* Sets the lock state for this frequency controller. Set to true when a consumer process requires that the * Sets the lock state for this frequency controller. Set to true when a consumer process requires that the
* frequency and sample rate controls be locked so that only the singular consumer process makes changes. This * sample rate control be locked so that only the single consumer process makes changes to the sample rate. This
* is primarily to lock down user interface controls when the polyphase channelizer is producing channels. * is primarily to lock down user interface controls when the polyphase channelizer is producing channels.
* *
* @param locked state * @param sampleRateLocked state
*/ */
public void setLocked(boolean locked) throws SourceException public void setSampleRateLocked(boolean sampleRateLocked) throws SourceException
{ {
mLocked = locked; mSampleRateLocked = sampleRateLocked;
if(mLocked) if(mSampleRateLocked)
{ {
broadcast(SourceEvent.lockedState()); broadcast(SourceEvent.lockedSampleRateState());
} }
else else
{ {
broadcast(SourceEvent.unlockedState()); broadcast(SourceEvent.unlockedSampleRateState());
} }
} }
@@ -111,7 +123,7 @@ public class FrequencyController
{ {
if(sampleRate != mSampleRate) if(sampleRate != mSampleRate)
{ {
if(!mLocked) if(!mSampleRateLocked)
{ {
mSampleRate = sampleRate; mSampleRate = sampleRate;
@@ -284,7 +296,7 @@ public class FrequencyController
/** /**
* Adds listener to receive frequency change events * Adds listener to receive frequency change events
*/ */
public void addListener(ISourceEventProcessor processor) public void addSourceEventProcessor(ISourceEventProcessor processor)
{ {
mLock.lock(); mLock.lock();
@@ -304,7 +316,7 @@ public class FrequencyController
/** /**
* Removes listener from receiving frequency change events * Removes listener from receiving frequency change events
*/ */
public void removeFrequencyChangeProcessor(ISourceEventProcessor processor) public void removeSourceEventProcessor(ISourceEventProcessor processor)
{ {
mLock.lock(); mLock.lock();

View File

@@ -120,7 +120,7 @@ public class HackRFTunerEditor extends TunerEditor<HackRFTuner,HackRFTunerConfig
getTunerStatusLabel().setText(status); getTunerStatusLabel().setText(status);
getButtonPanel().updateControls(); getButtonPanel().updateControls();
getFrequencyPanel().updateControls(); getFrequencyPanel().updateControls();
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLocked()); getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
updateSampleRateToolTip(); updateSampleRateToolTip();
getTunerInfoButton().setEnabled(hasTuner()); getTunerInfoButton().setEnabled(hasTuner());
@@ -295,7 +295,7 @@ public class HackRFTunerEditor extends TunerEditor<HackRFTuner,HackRFTunerConfig
*/ */
private void updateSampleRateToolTip() private void updateSampleRateToolTip()
{ {
if(hasTuner() && getTuner().getController().isLocked()) if(hasTuner() && getTuner().getController().isLockedSampleRate())
{ {
mSampleRateCombo.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock."); mSampleRateCombo.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
} }

View File

@@ -93,38 +93,48 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
return null; return null;
} }
if(CenterFrequencyCalculator.canTune(tunerChannel, mTunerController, mTunerChannels)) TunerChannelSource source = null;
try
{ {
try mTunerController.getFrequencyControllerLock().lock();
if(CenterFrequencyCalculator.canTune(tunerChannel, mTunerController, mTunerChannels))
{ {
//Attempt to create the channel source first, in case we get a filter design exception try
HalfBandTunerChannelSource tunerChannelSource = new HalfBandTunerChannelSource(mChannelSourceEventProcessor, {
tunerChannel, mTunerController.getSampleRate(), channelSpecification); //Attempt to create the channel source first, in case we get a filter design exception
HalfBandTunerChannelSource tunerChannelSource = new HalfBandTunerChannelSource(mChannelSourceEventProcessor,
tunerChannel, mTunerController.getSampleRate(), channelSpecification);
//Add to the list of channel sources so that it will receive the tuner frequency change //Add to the list of channel sources so that it will receive the tuner frequency change
mChannelSources.add(tunerChannelSource); mChannelSources.add(tunerChannelSource);
//Set the current tuner frequency //Set the current tuner frequency
tunerChannelSource.setFrequency(mTunerController.getFrequency()); tunerChannelSource.setFrequency(mTunerController.getFrequency());
//Add to the channel list and update the tuner center frequency as needed //Add to the channel list and update the tuner center frequency as needed
mTunerChannels.add(tunerChannel); mTunerChannels.add(tunerChannel);
updateTunerFrequency(); updateTunerFrequency();
//Lock the tuner controller frequency and sample rate //Lock the tuner controller frequency and sample rate
mTunerController.setLocked(true); mTunerController.setLockedSampleRate(true);
broadcast(SourceEvent.channelCountChange(getTunerChannelCount())); broadcast(SourceEvent.channelCountChange(getTunerChannelCount()));
return tunerChannelSource; source = tunerChannelSource;
} }
catch(FilterDesignException fde) catch(FilterDesignException fde)
{ {
mLog.error("Error creating CIC tuner channel source - couldn't design cleanup filter", fde); mLog.error("Error creating CIC tuner channel source - couldn't design cleanup filter", fde);
}
} }
} }
finally
{
mTunerController.getFrequencyControllerLock().unlock();
}
return null; return source;
} }
@Override @Override
@@ -294,7 +304,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
//Unlock the tuner controller if there are no more channels //Unlock the tuner controller if there are no more channels
if(getTunerChannelCount() == 0) if(getTunerChannelCount() == 0)
{ {
mTunerController.setLocked(false); mTunerController.setLockedSampleRate(false);
} }
broadcast(SourceEvent.channelCountChange(getTunerChannelCount())); broadcast(SourceEvent.channelCountChange(getTunerChannelCount()));
} }

View File

@@ -82,18 +82,30 @@ public class PassThroughSourceManager extends ChannelSourceManager
@Override @Override
public TunerChannelSource getSource(TunerChannel tunerChannel, ChannelSpecification channelSpecification) public TunerChannelSource getSource(TunerChannel tunerChannel, ChannelSpecification channelSpecification)
{ {
if(!mRunning) if(!mRunning)
{ {
return null; return null;
} }
PassThroughChannelSource channelSource = new PassThroughChannelSource(new SourceEventProxy(), TunerChannelSource source = null;
mTunerController, tunerChannel);
mTunerChannels.add(tunerChannel); try
mTunerChannelSources.add(channelSource); {
mTunerController.getFrequencyControllerLock().lock();
PassThroughChannelSource channelSource = new PassThroughChannelSource(new SourceEventProxy(),
mTunerController, tunerChannel);
return channelSource; mTunerChannels.add(tunerChannel);
mTunerChannelSources.add(channelSource);
source = channelSource;
}
finally
{
mTunerController.getFrequencyControllerLock().unlock();
}
return source;
} }
@Override @Override

View File

@@ -25,12 +25,11 @@ import io.github.dsheirer.source.tuner.TunerController;
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 java.util.SortedSet;
import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.FastMath;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.SortedSet;
/** /**
* PolyphaseChannelSourceManager is responsible for managing the tuner's center tuned frequency and providing access to * PolyphaseChannelSourceManager is responsible for managing the tuner's center tuned frequency and providing access to
* polyphase tuner channel sources (ie DDCs). This class is responsible for determining IF a requested channel can * polyphase tuner channel sources (ie DDCs). This class is responsible for determining IF a requested channel can
@@ -416,48 +415,56 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager
@Override @Override
public TunerChannelSource getSource(TunerChannel tunerChannel, ChannelSpecification channelSpecification) public TunerChannelSource getSource(TunerChannel tunerChannel, ChannelSpecification channelSpecification)
{ {
if(isTunable(tunerChannel)) TunerChannelSource tunerChannelSource = null;
try
{ {
//Get a new set of currently tuned channels mTunerController.getFrequencyControllerLock().lock();
SortedSet<TunerChannel> tunerChannels = getTunerChannels(); if(isTunable(tunerChannel))
//Add the requested channel to the list
tunerChannels.add(tunerChannel);
if(canTune(tunerChannels))
{ {
long currentCenterFrequency = mTunerController.getFrequency(); //Get a new set of currently tuned channels
long updatedCenterFrequency = 0; SortedSet<TunerChannel> tunerChannels = getTunerChannels();
//Attempt to adjust the center frequency before we allocate the channel //Add the requested channel to the list
try tunerChannels.add(tunerChannel);
if(canTune(tunerChannels))
{ {
updatedCenterFrequency = getCenterFrequency(tunerChannels, currentCenterFrequency); long currentCenterFrequency = mTunerController.getFrequency();
long updatedCenterFrequency = 0;
if(updatedCenterFrequency != currentCenterFrequency && updatedCenterFrequency != 0) //Attempt to adjust the center frequency before we allocate the channel
try
{ {
mTunerController.setFrequency(updatedCenterFrequency); updatedCenterFrequency = getCenterFrequency(tunerChannels, currentCenterFrequency);
}
//If we're successful to here, allocate the channel if(updatedCenterFrequency != currentCenterFrequency && updatedCenterFrequency != 0)
return mPolyphaseChannelManager.getChannel(tunerChannel); {
} mTunerController.setFrequency(updatedCenterFrequency);
catch(SourceException se) }
{
//Tuner controller threw an error trying to tune to the updated frequency //If we're successful to here, allocate the channel
mLog.error("Error while updating tuner controller with new center frequency [" + tunerChannelSource = mPolyphaseChannelManager.getChannel(tunerChannel);
updatedCenterFrequency + "] - unable to allocate new tuner channel", se); }
} catch(SourceException se)
catch(IllegalArgumentException iae) {
{ //Tuner controller threw an error trying to tune to the updated frequency
//Center frequency calculation failed mLog.error("Error while updating tuner controller with new center frequency [" +
// mLog.debug("Couldn't calculate new tuner center frequency for new tuner channel [" + updatedCenterFrequency + "] - unable to allocate new tuner channel", se);
// tunerChannel + "] unable to allocate new tuner channel"); }
catch(IllegalArgumentException iae)
{
//Center frequency calculation failed
}
} }
} }
} }
finally
{
mTunerController.getFrequencyControllerLock().unlock();
}
return null; return tunerChannelSource;
} }
/** /**
@@ -474,7 +481,7 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager
broadcast(sourceEvent); broadcast(sourceEvent);
//Lock the frequency and sample rate controls on the tuner controller so users can't change them //Lock the frequency and sample rate controls on the tuner controller so users can't change them
//when the polyphase manager has channels allocated //when the polyphase manager has channels allocated
mTunerController.setLocked(getTunerChannelCount() > 0); mTunerController.setLockedSampleRate(getTunerChannelCount() > 0);
break; break;
case NOTIFICATION_MEASURED_FREQUENCY_ERROR_SYNC_LOCKED: case NOTIFICATION_MEASURED_FREQUENCY_ERROR_SYNC_LOCKED:
//Rebroadcast these frequency measurement errors to the tuner and tuner controller //Rebroadcast these frequency measurement errors to the tuner and tuner controller

View File

@@ -29,6 +29,8 @@ import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner.E4KGain;
import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner.E4KLNAGain; import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner.E4KLNAGain;
import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner.E4KMixerGain; import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner.E4KMixerGain;
import io.github.dsheirer.source.tuner.ui.TunerEditor; import io.github.dsheirer.source.tuner.ui.TunerEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -41,8 +43,6 @@ import javax.swing.JOptionPane;
import javax.swing.JSeparator; import javax.swing.JSeparator;
import javax.swing.SpinnerNumberModel; import javax.swing.SpinnerNumberModel;
import javax.usb.UsbException; import javax.usb.UsbException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** /**
* E4000 tuner editor * E4000 tuner editor
@@ -383,7 +383,7 @@ public class E4KTunerEditor extends TunerEditor<RTL2832Tuner, E4KTunerConfigurat
*/ */
private void updateSampleRateToolTip() private void updateSampleRateToolTip()
{ {
if(hasTuner() && getTuner().getTunerController().isLocked()) if(hasTuner() && getTuner().getTunerController().isLockedSampleRate())
{ {
getSampleRateCombo().setToolTipText("Sample Rate is locked. Disable decoding channels to unlock."); getSampleRateCombo().setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
} }

View File

@@ -416,7 +416,7 @@ public class R820TTunerEditor extends TunerEditor<RTL2832Tuner,R820TTunerConfigu
*/ */
private void updateSampleRateToolTip() private void updateSampleRateToolTip()
{ {
if(hasTuner() && getTuner().getTunerController().isLocked()) if(hasTuner() && getTuner().getTunerController().isLockedSampleRate())
{ {
getSampleRateCombo().setToolTipText("Sample Rate is locked. Disable decoding channels to unlock."); getSampleRateCombo().setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
} }

View File

@@ -25,10 +25,6 @@ import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
import io.github.dsheirer.source.tuner.manager.DiscoveredUSBTuner; import io.github.dsheirer.source.tuner.manager.DiscoveredUSBTuner;
import io.github.dsheirer.source.tuner.manager.IDiscoveredTunerStatusListener; import io.github.dsheirer.source.tuner.manager.IDiscoveredTunerStatusListener;
import io.github.dsheirer.source.tuner.manager.TunerStatus; import io.github.dsheirer.source.tuner.manager.TunerStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.table.AbstractTableModel;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
@@ -36,6 +32,10 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.table.AbstractTableModel;
/** /**
* Model for discovered tuners * Model for discovered tuners
@@ -449,7 +449,7 @@ public class DiscoveredTunerModel extends AbstractTableModel implements Listener
if(discoveredTuner.hasTuner()) if(discoveredTuner.hasTuner())
{ {
int channelCount = discoveredTuner.getTuner().getChannelSourceManager().getTunerChannelCount(); int channelCount = discoveredTuner.getTuner().getChannelSourceManager().getTunerChannelCount();
return channelCount + " (" + (discoveredTuner.getTuner().getTunerController().isLocked() ? "LOCKED)" : "UNLOCKED)"); return channelCount + " (" + (discoveredTuner.getTuner().getTunerController().isLockedSampleRate() ? "LOCKED)" : "UNLOCKED)");
} }
else else
{ {

View File

@@ -619,8 +619,8 @@ public abstract class TunerEditor<T extends Tuner,C extends TunerConfiguration>
{ {
getFrequencyControl().clearListeners(); getFrequencyControl().clearListeners();
getFrequencyControl().addListener(mFrequencyAndCorrectionChangeListener); getFrequencyControl().addListener(mFrequencyAndCorrectionChangeListener);
getFrequencyControl().setEnabled(hasTuner() && !getTuner().getTunerController().isLocked()); getFrequencyControl().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getTunerLockedStatusLabel().setVisible(hasTuner() && getTuner().getTunerController().isLocked()); getTunerLockedStatusLabel().setVisible(hasTuner() && getTuner().getTunerController().isLockedSampleRate());
getFrequencyCorrectionSpinner().setEnabled(hasTuner()); getFrequencyCorrectionSpinner().setEnabled(hasTuner());
getAutoPPMCheckBox().setEnabled(hasTuner()); getAutoPPMCheckBox().setEnabled(hasTuner());

View File

@@ -143,7 +143,7 @@ public class TunerViewPanel extends JPanel
if(selectedTuner != null && selectedTuner.hasTuner() && tunerEvent.getTuner() == selectedTuner.getTuner()) if(selectedTuner != null && selectedTuner.hasTuner() && tunerEvent.getTuner() == selectedTuner.getTuner())
{ {
mDiscoveredTunerEditor.setTunerLockState(selectedTuner.getTuner().getTunerController().isLocked()); mDiscoveredTunerEditor.setTunerLockState(selectedTuner.getTuner().getTunerController().isLockedSampleRate());
} }
} }
} }

View File

@@ -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/>
~ ****************************************************************************** ~ *****************************************************************************
--> -->
<configuration> <configuration>
<conversionRule conversionWord="memory_usage" converterClass="io.github.dsheirer.util.MemoryUsageLogger" /> <conversionRule conversionWord="memory_usage" converterClass="io.github.dsheirer.util.MemoryUsageLogger" />
@@ -24,7 +23,7 @@
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<pattern>%-12(%d{HH:mm:ss.SSS}) %-5level %logger{25} - %msg %memory_usage%n</pattern> <pattern>%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) %-5level %logger{25} - %msg %memory_usage%n</pattern>
</encoder> </encoder>
</appender> </appender>