mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 09:37:36 -05:00
Compare commits
26 Commits
v0.6.0-bet
...
v0.6.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09e19e1486 | ||
|
|
0f5478925c | ||
|
|
09dce0b0d1 | ||
|
|
ad98b1cb5e | ||
|
|
8effd97749 | ||
|
|
9dbed72c32 | ||
|
|
b4dd3692b8 | ||
|
|
030cbb856c | ||
|
|
511101e9b7 | ||
|
|
60dd2b2df7 | ||
|
|
218dc94e02 | ||
|
|
2440f578b1 | ||
|
|
09c87237cb | ||
|
|
3d974ddd91 | ||
|
|
1489c970ba | ||
|
|
9e0afca3d1 | ||
|
|
99eda4013e | ||
|
|
a62f81f890 | ||
|
|
66f0731731 | ||
|
|
dc239801c6 | ||
|
|
d4ba0988bc | ||
|
|
ad0f953b2a | ||
|
|
e1bc9eabd6 | ||
|
|
d3dc1a8667 | ||
|
|
bf278120de | ||
|
|
2f52f6e009 |
2
.github/workflows/gradle.yml
vendored
2
.github/workflows/gradle.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Set up JDK 20
|
- name: Set up JDK 20
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
47
.github/workflows/nightly.yml
vendored
Normal file
47
.github/workflows/nightly.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Create nightly release for Linux, Mac and Windows using the Linux runner.
|
||||||
|
name: Nightly Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
# Don't run nightly build for pull requests - uncomment to test changes to this action within scope of the PR review
|
||||||
|
# pull_request:
|
||||||
|
# branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nightly:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up JDK 20
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '20'
|
||||||
|
distribution: 'liberica'
|
||||||
|
java-package: 'jdk+fx'
|
||||||
|
|
||||||
|
- name: Build Linux and Mac releases with Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: runtimeZipOthers -PprojectVersion=nightly
|
||||||
|
|
||||||
|
- name: Build Windows release with Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: runtimeZipWindows -PprojectVersion=nightly
|
||||||
|
|
||||||
|
- name: Create Build Info file
|
||||||
|
run: |
|
||||||
|
echo -e "ref: $GITHUB_REF \ncommit: $GITHUB_SHA\nbuild: $(date +"%Y-%m-%dT%H:%M:%SZ")" > build/image/build_info.txt
|
||||||
|
|
||||||
|
- name: Add build artifacts to nightly release
|
||||||
|
uses: pyTooling/Actions/releaser@main
|
||||||
|
with:
|
||||||
|
tag: nightly
|
||||||
|
rm: false
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
files: |
|
||||||
|
build/image/*.zip
|
||||||
|
build/image/build_info.txt
|
||||||
@@ -1,8 +1,10 @@
|
|||||||

|

|
||||||
|

|
||||||
|
|
||||||
# sdrtrunk
|
# sdrtrunk
|
||||||
A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR).
|
A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR).
|
||||||
|
|
||||||
|
* [Help/Wiki Home Page](https://github.com/DSheirer/sdrtrunk/wiki)
|
||||||
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/Getting-Started)
|
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/Getting-Started)
|
||||||
* [User's Manual](https://github.com/DSheirer/sdrtrunk/wiki/User-Manual)
|
* [User's Manual](https://github.com/DSheirer/sdrtrunk/wiki/User-Manual)
|
||||||
* [Download](https://github.com/DSheirer/sdrtrunk/releases)
|
* [Download](https://github.com/DSheirer/sdrtrunk/releases)
|
||||||
@@ -18,6 +20,13 @@ All release versions of sdrtrunk are available from the [releases](https://githu
|
|||||||
* **(beta)** These versions are currently being tested for bugs and functionality prior to final release.
|
* **(beta)** These versions are currently being tested for bugs and functionality prior to final release.
|
||||||
* **(final)** These versions have been tested and are the current release version.
|
* **(final)** These versions have been tested and are the current release version.
|
||||||
|
|
||||||
|
## Download Nightly Software Build
|
||||||
|
The [nightly](https://github.com/DSheirer/sdrtrunk/releases/tag/nightly) release contains current builds of the software
|
||||||
|
for all supported operating systems. This version of the software may contain bugs and may not run correctly. However,
|
||||||
|
it let's you preview the most recent changes and fixes before the next software release. **Always backup your
|
||||||
|
playlist(s) before you use the nightly builds.** Note: the nightly release is updated each time code changes are
|
||||||
|
committed to the code base, so it's not really 'nightly' as much as it is 'current'.
|
||||||
|
|
||||||
## Minimum System Requirements
|
## Minimum System Requirements
|
||||||
* **Operating System:** Windows (~~32 or~~ 64-bit), Linux (~~32 or~~ 64-bit) or Mac/Linux (64-bit, 10.14 or higher)
|
* **Operating System:** Windows (~~32 or~~ 64-bit), Linux (~~32 or~~ 64-bit) or Mac/Linux (64-bit, 10.14 or higher)
|
||||||
* **CPU:** 4-core
|
* **CPU:** 4-core
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ repositories {
|
|||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
|
|
||||||
//Note: this should match the GitLab release tag.
|
//Version is defined in gradle.properties so that we can CLI override it for nightly builds.
|
||||||
version = '0.6.0-beta-3'
|
version = project.findProperty('projectVersion')
|
||||||
|
|
||||||
//Java 20 is required for this version of the Project Panama preview/incubator feature
|
//Java 20 is required for this version of the Project Panama preview/incubator feature
|
||||||
java {
|
java {
|
||||||
|
|||||||
29
gradle.properties
Normal file
29
gradle.properties
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
# Copyright (C) 2014-2023 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/>
|
||||||
|
# *****************************************************************************
|
||||||
|
#
|
||||||
|
|
||||||
|
# Version naming conventions:
|
||||||
|
# Alpha: maj.min.patch-alpha-build
|
||||||
|
# Beta: maj.min.patch-beta-build
|
||||||
|
# Release: maj.min.patch
|
||||||
|
#
|
||||||
|
# Note: this is so that the file names for the resultant release build products match the GitLab release asset
|
||||||
|
# tag name, specifically the dashes inserted before and after the alpha/beta labels.
|
||||||
|
# See: https://github.com/DSheirer/sdrtrunk/issues/1651
|
||||||
|
|
||||||
|
projectVersion=0.6.0-beta-4
|
||||||
@@ -232,6 +232,9 @@ public class RdioScannerBroadcaster extends AbstractAudioBroadcaster<RdioScanner
|
|||||||
String talkgroupLabel = getTalkgroupLabel(audioRecording);
|
String talkgroupLabel = getTalkgroupLabel(audioRecording);
|
||||||
String talkgroupGroup = getTalkgroupGroup(audioRecording);
|
String talkgroupGroup = getTalkgroupGroup(audioRecording);
|
||||||
String systemLabel = getSystemLabel(audioRecording);
|
String systemLabel = getSystemLabel(audioRecording);
|
||||||
|
String path = audioRecording.getPath().toString();
|
||||||
|
// Remove TEMPORARY_STREAM_FILE_SUFFIX
|
||||||
|
String audioName = path.substring(path.substring(0, path.lastIndexOf("_")).lastIndexOf("_") + 1);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -252,6 +255,7 @@ public class RdioScannerBroadcaster extends AbstractAudioBroadcaster<RdioScanner
|
|||||||
RdioScannerBuilder bodyBuilder = new RdioScannerBuilder();
|
RdioScannerBuilder bodyBuilder = new RdioScannerBuilder();
|
||||||
bodyBuilder.addPart(FormField.KEY, getBroadcastConfiguration().getApiKey())
|
bodyBuilder.addPart(FormField.KEY, getBroadcastConfiguration().getApiKey())
|
||||||
.addPart(FormField.SYSTEM, getBroadcastConfiguration().getSystemID())
|
.addPart(FormField.SYSTEM, getBroadcastConfiguration().getSystemID())
|
||||||
|
.addAudioName(audioName)
|
||||||
.addFile(audioBytes)
|
.addFile(audioBytes)
|
||||||
.addPart(FormField.DATE_TIME, timestampSeconds)
|
.addPart(FormField.DATE_TIME, timestampSeconds)
|
||||||
.addPart(FormField.TALKGROUP_ID, talkgroup)
|
.addPart(FormField.TALKGROUP_ID, talkgroup)
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ public class RdioScannerBuilder
|
|||||||
private static final String DASH_DASH = "--";
|
private static final String DASH_DASH = "--";
|
||||||
private static final String BOUNDARY = "--sdrtrunk-sdrtrunk-sdrtrunk";
|
private static final String BOUNDARY = "--sdrtrunk-sdrtrunk-sdrtrunk";
|
||||||
private List<Part> mParts = new ArrayList<>();
|
private List<Part> mParts = new ArrayList<>();
|
||||||
private byte[] audioBytes = null;
|
private byte[] audioBytes = null;
|
||||||
|
private String audioName = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
@@ -51,6 +52,15 @@ public class RdioScannerBuilder
|
|||||||
return BOUNDARY;
|
return BOUNDARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a Audio file name part to the call
|
||||||
|
*/
|
||||||
|
public RdioScannerBuilder addAudioName(String value)
|
||||||
|
{
|
||||||
|
audioName = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Audio bytes part to the call
|
* Adds a Audio bytes part to the call
|
||||||
*/
|
*/
|
||||||
@@ -110,7 +120,8 @@ public class RdioScannerBuilder
|
|||||||
}
|
}
|
||||||
StringBuilder sb= new StringBuilder();
|
StringBuilder sb= new StringBuilder();
|
||||||
sb.append(DASH_DASH).append(boundary).append("\r\n");
|
sb.append(DASH_DASH).append(boundary).append("\r\n");
|
||||||
sb.append("Content-Disposition: form-data; name=\"").append("audio").append("\"\r\n\r\n");
|
sb.append("Content-Disposition: form-data; filename =\"").append(audioName);
|
||||||
|
sb.append("\"; name=\"").append("audio").append("\"\r\n\r\n");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
*/
|
*/
|
||||||
private static final int PROCESSED_CHANNEL_RESULTS_THRESHOLD = 1024;
|
private static final int PROCESSED_CHANNEL_RESULTS_THRESHOLD = 1024;
|
||||||
|
|
||||||
//Sized to process 1/20th batch of 152 buffers a second, at 40 times per second
|
//Sized to process 40 times per second
|
||||||
private IFFTProcessorDispatcher mIFFTProcessorDispatcher = new IFFTProcessorDispatcher(152 / 20, 25);
|
private IFFTProcessorDispatcher mIFFTProcessorDispatcher = new IFFTProcessorDispatcher(25);
|
||||||
private FloatFFT_1D mFFT;
|
private FloatFFT_1D mFFT;
|
||||||
private float[] mInlineSamples;
|
private float[] mInlineSamples;
|
||||||
private float[] mInlineFilter;
|
private float[] mInlineFilter;
|
||||||
@@ -406,9 +406,9 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
*/
|
*/
|
||||||
public class IFFTProcessorDispatcher extends Dispatcher<List<float[]>>
|
public class IFFTProcessorDispatcher extends Dispatcher<List<float[]>>
|
||||||
{
|
{
|
||||||
public IFFTProcessorDispatcher(int batchSize, long interval)
|
public IFFTProcessorDispatcher(long interval)
|
||||||
{
|
{
|
||||||
super("sdrtrunk polyphase ifft processor", batchSize, interval);
|
super("sdrtrunk polyphase ifft processor", interval);
|
||||||
|
|
||||||
//We create a listener interface to receive the batched channel results arrays from the scheduled thread pool
|
//We create a listener interface to receive the batched channel results arrays from the scheduled thread pool
|
||||||
//dispatcher thread that is part of this continuous buffer processor. We perform an IFFT on each
|
//dispatcher thread that is part of this continuous buffer processor. We perform an IFFT on each
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
mChannelCalculator = new ChannelCalculator(sampleRate, channelCount, frequency, CHANNEL_OVERSAMPLING);
|
mChannelCalculator = new ChannelCalculator(sampleRate, channelCount, frequency, CHANNEL_OVERSAMPLING);
|
||||||
mBufferDispatcher = new Dispatcher("sdrtrunk polyphase buffer processor", 50, 10);
|
mBufferDispatcher = new Dispatcher("sdrtrunk polyphase buffer processor", 10);
|
||||||
mBufferDispatcher.setListener(mNativeBufferReceiver);
|
mBufferDispatcher.setListener(mNativeBufferReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
mInputChannelCount = inputChannelCount;
|
mInputChannelCount = inputChannelCount;
|
||||||
//Process 1/10th of the sample rate per second at a rate of 20 times a second (200% of anticipated rate)
|
//Process 1/10th of the sample rate per second at a rate of 20 times a second (200% of anticipated rate)
|
||||||
mHeartbeatManager = heartbeatManager;
|
mHeartbeatManager = heartbeatManager;
|
||||||
mChannelResultsDispatcher = new Dispatcher("sdrtrunk polyphase channel", (int)(sampleRate / 10),
|
mChannelResultsDispatcher = new Dispatcher("sdrtrunk polyphase channel",50, mHeartbeatManager);
|
||||||
50, mHeartbeatManager);
|
|
||||||
mChannelResultsDispatcher.setListener(floats -> {
|
mChannelResultsDispatcher.setListener(floats -> {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2023 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.control;
|
package io.github.dsheirer.gui.control;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.control.TextFormatter;
|
import javafx.scene.control.TextFormatter;
|
||||||
import javafx.util.converter.IntegerStringConverter;
|
import javafx.util.converter.IntegerStringConverter;
|
||||||
|
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text field control for integer values.
|
* Text field control for integer values.
|
||||||
*/
|
*/
|
||||||
@@ -52,7 +48,7 @@ public class IntegerTextField extends TextField
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
setTextFormatter(new TextFormatter<Integer>(new IntegerStringConverter(), 0, filter));
|
setTextFormatter(new TextFormatter<Integer>(new IntegerStringConverter(), null, filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +67,7 @@ public class IntegerTextField extends TextField
|
|||||||
//Do nothing ... we couldn't parse the value
|
//Do nothing ... we couldn't parse the value
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ public class AMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public AMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public AMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -38,6 +38,8 @@ 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.manager.TunerManager;
|
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -69,9 +71,6 @@ import org.controlsfx.control.ToggleSwitch;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel configuration editor
|
* Channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +99,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
private IconNode mPlayGraphicNode;
|
private IconNode mPlayGraphicNode;
|
||||||
private IconNode mStopGraphicNode;
|
private IconNode mStopGraphicNode;
|
||||||
private ChannelProcessingMonitor mChannelProcessingMonitor = new ChannelProcessingMonitor();
|
private ChannelProcessingMonitor mChannelProcessingMonitor = new ChannelProcessingMonitor();
|
||||||
|
private IFilterProcessor mFilterProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
@@ -108,11 +108,12 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public ChannelConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public ChannelConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
mTunerManager = tunerManager;
|
mTunerManager = tunerManager;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
|
mFilterProcessor = filterProcessor;
|
||||||
|
|
||||||
setMaxWidth(Double.MAX_VALUE);
|
setMaxWidth(Double.MAX_VALUE);
|
||||||
|
|
||||||
@@ -689,7 +690,16 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
|||||||
mSaveButton.setMaxWidth(Double.MAX_VALUE);
|
mSaveButton.setMaxWidth(Double.MAX_VALUE);
|
||||||
mSaveButton.disableProperty().bind(modifiedProperty().not());
|
mSaveButton.disableProperty().bind(modifiedProperty().not());
|
||||||
mSaveButton.setOnAction(event -> {
|
mSaveButton.setOnAction(event -> {
|
||||||
save();
|
if(mFilterProcessor != null)
|
||||||
|
{
|
||||||
|
mFilterProcessor.clearFilter();
|
||||||
|
save();
|
||||||
|
mFilterProcessor.restoreFilter();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
if(getItem().isProcessing())
|
if(getItem().isProcessing())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -23,11 +23,10 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to channel configuration editors for various decoder types.
|
* Provides access to channel configuration editors for various decoder types.
|
||||||
@@ -41,31 +40,35 @@ public class ChannelConfigurationEditorFactory
|
|||||||
* Constructs an editor for the specified decoder type
|
* Constructs an editor for the specified decoder type
|
||||||
* @param decoderType to create
|
* @param decoderType to create
|
||||||
* @param playlistManager for the editor
|
* @param playlistManager for the editor
|
||||||
|
* @param tunerManager for tuners
|
||||||
|
* @param userPreferences for preferences
|
||||||
|
* @param filterProcessor to be notified to clear and restore any applied filters.
|
||||||
* @return constructed editor
|
* @return constructed editor
|
||||||
*/
|
*/
|
||||||
public static ChannelConfigurationEditor getEditor(DecoderType decoderType, PlaylistManager playlistManager,
|
public static ChannelConfigurationEditor getEditor(DecoderType decoderType, PlaylistManager playlistManager,
|
||||||
TunerManager tunerManager, UserPreferences userPreferences)
|
TunerManager tunerManager, UserPreferences userPreferences,
|
||||||
|
IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
switch(decoderType)
|
switch(decoderType)
|
||||||
{
|
{
|
||||||
case AM:
|
case AM:
|
||||||
return new AMConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new AMConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case DMR:
|
case DMR:
|
||||||
return new DMRConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new DMRConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case NBFM:
|
case NBFM:
|
||||||
return new NBFMConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new NBFMConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case LTR_NET:
|
case LTR_NET:
|
||||||
return new LTRNetConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new LTRNetConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case LTR:
|
case LTR:
|
||||||
return new LTRConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new LTRConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case MPT1327:
|
case MPT1327:
|
||||||
return new MPT1327ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new MPT1327ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case PASSPORT:
|
case PASSPORT:
|
||||||
return new PassportConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new PassportConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case P25_PHASE1:
|
case P25_PHASE1:
|
||||||
return new P25P1ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new P25P1ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
case P25_PHASE2:
|
case P25_PHASE2:
|
||||||
return new P25P2ConfigurationEditor(playlistManager, tunerManager, userPreferences);
|
return new P25P2ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
default:
|
default:
|
||||||
if(decoderType != null && !mLoggedUnrecognizedTypes.contains(decoderType))
|
if(decoderType != null && !mLoggedUnrecognizedTypes.contains(decoderType))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,6 +26,12 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
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;
|
||||||
@@ -63,17 +69,10 @@ import org.controlsfx.control.textfield.TextFields;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JavaFX editor for managing channel configurations.
|
* JavaFX editor for managing channel configurations.
|
||||||
*/
|
*/
|
||||||
public class ChannelEditor extends SplitPane
|
public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelEditor.class);
|
private final static Logger mLog = LoggerFactory.getLogger(ChannelEditor.class);
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
@@ -106,7 +105,8 @@ public class ChannelEditor extends SplitPane
|
|||||||
mPlaylistManager = playlistManager;
|
mPlaylistManager = playlistManager;
|
||||||
mTunerManager = tunerManager;
|
mTunerManager = tunerManager;
|
||||||
mUserPreferences = userPreferences;
|
mUserPreferences = userPreferences;
|
||||||
mUnknownConfigurationEditor = new UnknownConfigurationEditor(mPlaylistManager, mTunerManager, userPreferences);
|
mUnknownConfigurationEditor = new UnknownConfigurationEditor(mPlaylistManager, mTunerManager,
|
||||||
|
userPreferences, this);
|
||||||
|
|
||||||
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,
|
||||||
mTunerManager, mUserPreferences);
|
mTunerManager, mUserPreferences, this);
|
||||||
|
|
||||||
if(editor != null)
|
if(editor != null)
|
||||||
{
|
{
|
||||||
@@ -374,6 +374,24 @@ public class ChannelEditor extends SplitPane
|
|||||||
mChannelFilteredList.setPredicate(mChannelListFilter);
|
mChannelFilteredList.setPredicate(mChannelListFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporarily clear the filter when the channel configuration editor is applying changes.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void clearFilter()
|
||||||
|
{
|
||||||
|
mChannelFilteredList.setPredicate(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the filter once the channel configuration editor has completed applying changes.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void restoreFilter()
|
||||||
|
{
|
||||||
|
mChannelFilteredList.setPredicate(mChannelListFilter);
|
||||||
|
}
|
||||||
|
|
||||||
private TableView<Channel> getChannelTableView()
|
private TableView<Channel> getChannelTableView()
|
||||||
{
|
{
|
||||||
if(mChannelTableView == null)
|
if(mChannelTableView == null)
|
||||||
@@ -449,6 +467,25 @@ public class ChannelEditor extends SplitPane
|
|||||||
nameColumn.setPrefWidth(200);
|
nameColumn.setPrefWidth(200);
|
||||||
|
|
||||||
TableColumn frequencyColumn = new TableColumn("Frequency");
|
TableColumn frequencyColumn = new TableColumn("Frequency");
|
||||||
|
frequencyColumn.setComparator((o1, o2) -> {
|
||||||
|
if(o1 instanceof Channel c1 && o2 instanceof Channel c2)
|
||||||
|
{
|
||||||
|
if(!c1.getFrequencyList().isEmpty() && !c2.getFrequencyList().isEmpty())
|
||||||
|
{
|
||||||
|
return Long.compare(c1.getFrequencyList().get(0), c2.getFrequencyList().get(0));
|
||||||
|
}
|
||||||
|
else if(!c1.getFrequencyList().isEmpty())
|
||||||
|
{
|
||||||
|
return Long.compare(c1.getFrequencyList().get(0), 0l);
|
||||||
|
}
|
||||||
|
else if(!c2.getFrequencyList().isEmpty())
|
||||||
|
{
|
||||||
|
return Long.compare(0l, c2.getFrequencyList().get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.compare(o1.hashCode(), o2.hashCode());
|
||||||
|
});
|
||||||
frequencyColumn.setCellValueFactory(new FrequencyCellValueFactory());
|
frequencyColumn.setCellValueFactory(new FrequencyCellValueFactory());
|
||||||
frequencyColumn.setPrefWidth(100);
|
frequencyColumn.setPrefWidth(100);
|
||||||
|
|
||||||
|
|||||||
@@ -99,9 +99,9 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public DMRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public DMRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* *****************************************************************************
|
||||||
|
* Copyright (C) 2014-2023 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.gui.playlist.channel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a processor that implements a filtering mechanism and can be commanded by an external controller to
|
||||||
|
* temporarily clear a filter and then restore the filter.
|
||||||
|
*/
|
||||||
|
public interface IFilterProcessor
|
||||||
|
{
|
||||||
|
void clearFilter();
|
||||||
|
void restoreFilter();
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -37,6 +37,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -50,9 +52,6 @@ import org.controlsfx.control.SegmentedButton;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LTR (standard) channel configuration editor
|
* LTR (standard) channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -77,9 +76,9 @@ public class LTRConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public LTRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public LTRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -37,6 +37,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -50,9 +52,6 @@ import org.controlsfx.control.SegmentedButton;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LTR-Net channel configuration editor
|
* LTR-Net channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -76,9 +75,10 @@ public class LTRNetConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param tunerManager for tuners
|
* @param tunerManager for tuners
|
||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public LTRNetConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
public LTRNetConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -38,6 +38,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
@@ -56,9 +58,6 @@ import javafx.scene.layout.VBox;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static io.github.dsheirer.module.decode.config.DecodeConfiguration.CALL_TIMEOUT_MAXIMUM;
|
import static io.github.dsheirer.module.decode.config.DecodeConfiguration.CALL_TIMEOUT_MAXIMUM;
|
||||||
import static io.github.dsheirer.module.decode.config.DecodeConfiguration.CALL_TIMEOUT_MINIMUM;
|
import static io.github.dsheirer.module.decode.config.DecodeConfiguration.CALL_TIMEOUT_MINIMUM;
|
||||||
|
|
||||||
@@ -87,9 +86,9 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public MPT1327ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public MPT1327ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import io.github.dsheirer.gui.playlist.eventlog.EventLogConfigurationEditor;
|
|||||||
import io.github.dsheirer.gui.playlist.source.FrequencyEditor;
|
import io.github.dsheirer.gui.playlist.source.FrequencyEditor;
|
||||||
import io.github.dsheirer.gui.playlist.source.SourceConfigurationEditor;
|
import io.github.dsheirer.gui.playlist.source.SourceConfigurationEditor;
|
||||||
import io.github.dsheirer.module.decode.DecoderType;
|
import io.github.dsheirer.module.decode.DecoderType;
|
||||||
import io.github.dsheirer.module.decode.analog.DecodeConfigAnalog;
|
|
||||||
import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration;
|
import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration;
|
||||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||||
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
||||||
@@ -41,6 +40,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -58,9 +59,6 @@ import javafx.scene.text.TextAlignment;
|
|||||||
import org.controlsfx.control.SegmentedButton;
|
import org.controlsfx.control.SegmentedButton;
|
||||||
import org.controlsfx.control.ToggleSwitch;
|
import org.controlsfx.control.ToggleSwitch;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Narrow-Band FM channel configuration editor
|
* Narrow-Band FM channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -95,9 +93,9 @@ public class NBFMConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public NBFMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public NBFMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -36,6 +36,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -54,9 +56,6 @@ import org.controlsfx.control.ToggleSwitch;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* P25 Phase 1 channel configuration editor
|
* P25 Phase 1 channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -83,9 +82,9 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences for preferences
|
* @param userPreferences for preferences
|
||||||
*/
|
*/
|
||||||
public P25P1ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public P25P1ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -37,6 +37,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -46,9 +48,6 @@ import javafx.scene.layout.VBox;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* P25 Phase 2 channel configuration editor
|
* P25 Phase 2 channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -72,9 +71,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences
|
* @param userPreferences
|
||||||
*/
|
*/
|
||||||
public P25P2ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public P25P2ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -36,6 +36,8 @@ 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 io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
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;
|
||||||
@@ -43,9 +45,6 @@ import javafx.scene.layout.VBox;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passport channel configuration editor
|
* Passport channel configuration editor
|
||||||
*/
|
*/
|
||||||
@@ -68,9 +67,9 @@ public class PassportConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param userPreferences
|
* @param userPreferences
|
||||||
*/
|
*/
|
||||||
public PassportConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public PassportConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 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
|
||||||
@@ -45,9 +45,9 @@ public class UnknownConfigurationEditor extends ChannelConfigurationEditor
|
|||||||
* @param aliasModel
|
* @param aliasModel
|
||||||
*/
|
*/
|
||||||
public UnknownConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
public UnknownConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||||
UserPreferences userPreferences)
|
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||||
{
|
{
|
||||||
super(playlistManager, tunerManager, userPreferences);
|
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* *****************************************************************************
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,6 +28,11 @@ import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyFeedConfigura
|
|||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import io.github.dsheirer.rrapi.type.UserFeedBroadcast;
|
import io.github.dsheirer.rrapi.type.UserFeedBroadcast;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -48,6 +53,7 @@ import javafx.scene.control.TabPane;
|
|||||||
import javafx.scene.control.TableCell;
|
import javafx.scene.control.TableCell;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
@@ -58,12 +64,6 @@ import jiconfont.javafx.IconNode;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor for broadcast audio stream configurations
|
* Editor for broadcast audio stream configurations
|
||||||
*/
|
*/
|
||||||
@@ -75,6 +75,7 @@ public class StreamingEditor extends SplitPane
|
|||||||
private TableView<ConfiguredBroadcast> mConfiguredBroadcastTableView;
|
private TableView<ConfiguredBroadcast> mConfiguredBroadcastTableView;
|
||||||
private MenuButton mNewButton;
|
private MenuButton mNewButton;
|
||||||
private Button mDeleteButton;
|
private Button mDeleteButton;
|
||||||
|
private Button mRefreshButton;
|
||||||
private TabPane mTabPane;
|
private TabPane mTabPane;
|
||||||
private Tab mConfigurationTab;
|
private Tab mConfigurationTab;
|
||||||
private Tab mAliasTab;
|
private Tab mAliasTab;
|
||||||
@@ -101,7 +102,7 @@ public class StreamingEditor extends SplitPane
|
|||||||
refreshBroadcastifyStreams();
|
refreshBroadcastifyStreams();
|
||||||
|
|
||||||
VBox buttonsBox = new VBox();
|
VBox buttonsBox = new VBox();
|
||||||
buttonsBox.getChildren().addAll(getNewButton(), getDeleteButton());
|
buttonsBox.getChildren().addAll(getNewButton(), getDeleteButton(), getRefreshButton());
|
||||||
buttonsBox.setPadding(new Insets(0, 0, 0, 10));
|
buttonsBox.setPadding(new Insets(0, 0, 0, 10));
|
||||||
buttonsBox.setSpacing(10);
|
buttonsBox.setSpacing(10);
|
||||||
|
|
||||||
@@ -231,21 +232,16 @@ public class StreamingEditor extends SplitPane
|
|||||||
{
|
{
|
||||||
if(mPlaylistManager.getRadioReference().availableProperty().get())
|
if(mPlaylistManager.getRadioReference().availableProperty().get())
|
||||||
{
|
{
|
||||||
ThreadPool.CACHED.submit(new Runnable()
|
ThreadPool.CACHED.submit(() -> {
|
||||||
{
|
try
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
{
|
||||||
try
|
List<UserFeedBroadcast> feeds = mPlaylistManager.getRadioReference().getService().getUserFeeds();
|
||||||
{
|
mBroadcastifyFeeds.clear();
|
||||||
List<UserFeedBroadcast> feeds = mPlaylistManager.getRadioReference().getService().getUserFeeds();
|
mBroadcastifyFeeds.addAll(feeds);
|
||||||
mBroadcastifyFeeds.clear();
|
}
|
||||||
mBroadcastifyFeeds.addAll(feeds);
|
catch(Throwable t)
|
||||||
}
|
{
|
||||||
catch(Throwable t)
|
mLog.error("Unable to refresh broadcastify stream configuration(s)");
|
||||||
{
|
|
||||||
mLog.error("Unable to refresh broadcastify stream configuration(s)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -348,6 +344,22 @@ public class StreamingEditor extends SplitPane
|
|||||||
return mNewButton;
|
return mNewButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh broadcastify feeds.
|
||||||
|
* @return button to refresh.
|
||||||
|
*/
|
||||||
|
private Button getRefreshButton()
|
||||||
|
{
|
||||||
|
if(mRefreshButton == null)
|
||||||
|
{
|
||||||
|
mRefreshButton = new Button("Refresh");
|
||||||
|
mRefreshButton.setTooltip(new Tooltip("Refresh streams available from Broadcastify"));
|
||||||
|
mRefreshButton.setOnAction(event -> refreshBroadcastifyStreams());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mRefreshButton;
|
||||||
|
}
|
||||||
|
|
||||||
private Button getDeleteButton()
|
private Button getDeleteButton()
|
||||||
{
|
{
|
||||||
if(mDeleteButton == null)
|
if(mDeleteButton == null)
|
||||||
|
|||||||
@@ -166,12 +166,12 @@ public class PatchGroup
|
|||||||
|
|
||||||
if(hasPatchedTalkgroups())
|
if(hasPatchedTalkgroups())
|
||||||
{
|
{
|
||||||
sb.append(getPatchedTalkgroupIdentifiers());
|
sb.append(" ").append(getPatchedTalkgroupIdentifiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasPatchedRadios())
|
if(hasPatchedRadios())
|
||||||
{
|
{
|
||||||
sb.append(getPatchedRadioIdentifiers());
|
sb.append(" ").append(getPatchedRadioIdentifiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2023 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,16 +14,13 @@
|
|||||||
*
|
*
|
||||||
* 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.properties;
|
package io.github.dsheirer.properties;
|
||||||
|
|
||||||
import io.github.dsheirer.gui.SDRTrunk;
|
import io.github.dsheirer.gui.SDRTrunk;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import org.slf4j.Logger;
|
import java.awt.Color;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -37,6 +34,8 @@ import java.util.Properties;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemProperties - provides an isolated instance of properties for the application
|
* SystemProperties - provides an isolated instance of properties for the application
|
||||||
@@ -48,6 +47,7 @@ public class SystemProperties
|
|||||||
private static String DEFAULT_APP_ROOT = "SDRTrunk";
|
private static String DEFAULT_APP_ROOT = "SDRTrunk";
|
||||||
private static String PROPERTIES_FILENAME = "SDRTrunk.properties";
|
private static String PROPERTIES_FILENAME = "SDRTrunk.properties";
|
||||||
private static String MANIFEST_VERSION = "Implementation-Version";
|
private static String MANIFEST_VERSION = "Implementation-Version";
|
||||||
|
private static String BUILD_TIMESTAMP = "Build-Timestamp";
|
||||||
|
|
||||||
private static SystemProperties INSTANCE;
|
private static SystemProperties INSTANCE;
|
||||||
private static Properties mProperties;
|
private static Properties mProperties;
|
||||||
@@ -208,11 +208,19 @@ public class SystemProperties
|
|||||||
if(manifest != null)
|
if(manifest != null)
|
||||||
{
|
{
|
||||||
String version = manifest.getMainAttributes().getValue(MANIFEST_VERSION);
|
String version = manifest.getMainAttributes().getValue(MANIFEST_VERSION);
|
||||||
|
String timestamp = manifest.getMainAttributes().getValue(BUILD_TIMESTAMP);
|
||||||
|
|
||||||
if(version != null)
|
if(version != null)
|
||||||
{
|
{
|
||||||
sb.append(" v");
|
if(version.contains("nightly") && timestamp != null)
|
||||||
sb.append(version);
|
{
|
||||||
|
sb.append( " nightly - ").append(timestamp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(" v");
|
||||||
|
sb.append(version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class BinaryRecorder extends Module implements IByteBufferListener
|
|||||||
private final static Logger mLog = LoggerFactory.getLogger(BinaryRecorder.class);
|
private final static Logger mLog = LoggerFactory.getLogger(BinaryRecorder.class);
|
||||||
private static final int MAX_RECORDING_BYTE_SIZE = 524288; //500 kB
|
private static final int MAX_RECORDING_BYTE_SIZE = 524288; //500 kB
|
||||||
|
|
||||||
private Dispatcher<ByteBuffer> mBufferProcessor = new Dispatcher<>("sdrtrunk binary recorder", 200, 250);
|
private Dispatcher<ByteBuffer> mBufferProcessor = new Dispatcher<>("sdrtrunk binary recorder", 250);
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
private Path mBaseRecordingPath;
|
private Path mBaseRecordingPath;
|
||||||
private String mRecordingIdentifier;
|
private String mRecordingIdentifier;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class ComplexSamplesWaveRecorder extends Module implements IComplexSample
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(ComplexSamplesWaveRecorder.class);
|
private final static Logger mLog = LoggerFactory.getLogger(ComplexSamplesWaveRecorder.class);
|
||||||
|
|
||||||
private Dispatcher<ComplexSamples> mBufferProcessor = new Dispatcher<>("sdrtrunk complex wave recorder", 100, 250);
|
private Dispatcher<ComplexSamples> mBufferProcessor = new Dispatcher<>("sdrtrunk complex wave recorder", 250);
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
private BufferWaveWriter mWriter;
|
private BufferWaveWriter mWriter;
|
||||||
private String mFilePrefix;
|
private String mFilePrefix;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class NativeBufferWaveRecorder extends Module implements Listener<INative
|
|||||||
private static final Logger mLog = LoggerFactory.getLogger(ComplexSamplesWaveRecorder.class);
|
private static final Logger mLog = LoggerFactory.getLogger(ComplexSamplesWaveRecorder.class);
|
||||||
private static final long STATUS_UPDATE_BYTE_INTERVAL = 1_048_576;
|
private static final long STATUS_UPDATE_BYTE_INTERVAL = 1_048_576;
|
||||||
private static final long MAX_RECORDING_SIZE = (long)Integer.MAX_VALUE * 2l;
|
private static final long MAX_RECORDING_SIZE = (long)Integer.MAX_VALUE * 2l;
|
||||||
private Dispatcher<INativeBuffer> mBufferProcessor = new Dispatcher<>("sdrtrunk native buffer wave recorder", 100, 250);
|
private Dispatcher<INativeBuffer> mBufferProcessor = new Dispatcher<>("sdrtrunk native buffer wave recorder", 250);
|
||||||
|
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
private NativeBufferWaveWriter mWriter;
|
private NativeBufferWaveWriter mWriter;
|
||||||
|
|||||||
@@ -74,8 +74,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
|||||||
mQDecimationFilter = DecimationFilterFactory.getRealDecimationFilter(decimation);
|
mQDecimationFilter = DecimationFilterFactory.getRealDecimationFilter(decimation);
|
||||||
|
|
||||||
//Set dispatcher to process 1/10 of estimated sample arrival rate, 20 times per second (up to 200% per interval)
|
//Set dispatcher to process 1/10 of estimated sample arrival rate, 20 times per second (up to 200% per interval)
|
||||||
mBufferDispatcher = new Dispatcher("sdrtrunk heterodyne channel " + tunerChannel.getFrequency(),
|
mBufferDispatcher = new Dispatcher("sdrtrunk heterodyne channel " + tunerChannel.getFrequency(), 50, getHeartbeatManager());
|
||||||
(int)(sampleRate / 10), 50, getHeartbeatManager());
|
|
||||||
mBufferDispatcher.setListener(new NativeBufferProcessor());
|
mBufferDispatcher.setListener(new NativeBufferProcessor());
|
||||||
|
|
||||||
//Setup the frequency mixer to the current source frequency
|
//Setup the frequency mixer to the current source frequency
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
|||||||
super(listener, tunerChannel);
|
super(listener, tunerChannel);
|
||||||
mTunerController = tunerController;
|
mTunerController = tunerController;
|
||||||
mBufferDispatcher = new Dispatcher<>("sdrtrunk pass-through channel " + tunerChannel.getFrequency(),
|
mBufferDispatcher = new Dispatcher<>("sdrtrunk pass-through channel " + tunerChannel.getFrequency(),
|
||||||
250, 50, getHeartbeatManager());
|
50, getHeartbeatManager());
|
||||||
mBufferDispatcher.setListener(new BufferProcessor());
|
mBufferDispatcher.setListener(new BufferProcessor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class SDRplay
|
|||||||
private static final Logger mLog = LoggerFactory.getLogger(SDRplay.class);
|
private static final Logger mLog = LoggerFactory.getLogger(SDRplay.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Foreign memory arenaallocation resource scope
|
* Foreign memory arena allocation resource scope
|
||||||
*/
|
*/
|
||||||
private final Arena mArena = Arena.openShared();
|
private final Arena mArena = Arena.openShared();
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ public enum Version
|
|||||||
V3_08(3.08f, true),
|
V3_08(3.08f, true),
|
||||||
V3_09(3.09f, true),
|
V3_09(3.09f, true),
|
||||||
V3_10(3.10f, true),
|
V3_10(3.10f, true),
|
||||||
V3_11(3.11f, true);
|
V3_11(3.11f, true),
|
||||||
|
V3_12(3.12f, true);
|
||||||
|
|
||||||
private float mValue;
|
private float mValue;
|
||||||
private boolean mSupported;
|
private boolean mSupported;
|
||||||
|
|||||||
@@ -37,24 +37,24 @@ public class CallbackFunctions
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a callback functions for single-tuner use.
|
* Constructs a callback functions for single-tuner use.
|
||||||
* @param arena for native memory allocation
|
* @param longLifecycleArena for native memory allocation for long lifecycle objects.
|
||||||
* @param deviceEventListener for device events
|
* @param deviceEventListener for device events
|
||||||
* @param streamListener for streaming samples
|
* @param streamListener for streaming samples
|
||||||
* @param streamCallbackListener for streaming events
|
* @param streamCallbackListener for streaming events
|
||||||
*/
|
*/
|
||||||
public CallbackFunctions(Arena arena, IDeviceEventListener deviceEventListener,
|
public CallbackFunctions(Arena longLifecycleArena, IDeviceEventListener deviceEventListener,
|
||||||
IStreamListener streamListener, IStreamCallbackListener streamCallbackListener)
|
IStreamListener streamListener, IStreamCallbackListener streamCallbackListener)
|
||||||
{
|
{
|
||||||
//Create the event callback function
|
//Create the event callback function
|
||||||
mDeviceEventAdapter = new DeviceEventAdapter(arena, deviceEventListener);
|
mDeviceEventAdapter = new DeviceEventAdapter(deviceEventListener);
|
||||||
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, arena.scope());
|
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, longLifecycleArena.scope());
|
||||||
|
|
||||||
//Create the stream A callback function
|
//Create the stream A callback function
|
||||||
mStreamACallbackAdapter = new StreamCallbackAdapter(arena, streamListener, streamCallbackListener);
|
mStreamACallbackAdapter = new StreamCallbackAdapter(streamListener, streamCallbackListener);
|
||||||
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, arena.scope());
|
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, longLifecycleArena.scope());
|
||||||
|
|
||||||
//Create the callback functions union and populate the callback functions
|
//Create the callback functions union and populate the callback functions
|
||||||
mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(arena);
|
mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(longLifecycleArena);
|
||||||
sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction);
|
sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction);
|
||||||
sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction);
|
sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction);
|
||||||
}
|
}
|
||||||
@@ -72,15 +72,15 @@ public class CallbackFunctions
|
|||||||
IStreamCallbackListener streamCallbackListener)
|
IStreamCallbackListener streamCallbackListener)
|
||||||
{
|
{
|
||||||
//Create the event callback function
|
//Create the event callback function
|
||||||
mDeviceEventAdapter = new DeviceEventAdapter(arena, deviceEventListener);
|
mDeviceEventAdapter = new DeviceEventAdapter(deviceEventListener);
|
||||||
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, arena.scope());
|
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, arena.scope());
|
||||||
|
|
||||||
//Create the stream A callback function
|
//Create the stream A callback function
|
||||||
mStreamACallbackAdapter = new StreamCallbackAdapter(arena, streamAListener, streamCallbackListener);
|
mStreamACallbackAdapter = new StreamCallbackAdapter(streamAListener, streamCallbackListener);
|
||||||
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, arena.scope());
|
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, arena.scope());
|
||||||
|
|
||||||
//Create the stream B callback function
|
//Create the stream B callback function
|
||||||
mStreamBCallbackAdapter = new StreamCallbackAdapter(arena, streamBListener, streamCallbackListener);
|
mStreamBCallbackAdapter = new StreamCallbackAdapter(streamBListener, streamCallbackListener);
|
||||||
MemorySegment streamBFunction = sdrplay_api_StreamCallback_t.allocate(mStreamBCallbackAdapter, arena.scope());
|
MemorySegment streamBFunction = sdrplay_api_StreamCallback_t.allocate(mStreamBCallbackAdapter, arena.scope());
|
||||||
|
|
||||||
//Create the callback functions union and populate the callback functions
|
//Create the callback functions union and populate the callback functions
|
||||||
|
|||||||
@@ -36,24 +36,14 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class DeviceEventAdapter implements sdrplay_api_EventCallback_t
|
public class DeviceEventAdapter implements sdrplay_api_EventCallback_t
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(DeviceEventAdapter.class);
|
private static final Logger mLog = LoggerFactory.getLogger(DeviceEventAdapter.class);
|
||||||
|
|
||||||
private Arena mArena;
|
|
||||||
private IDeviceEventListener mDeviceEventListener;
|
private IDeviceEventListener mDeviceEventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance.
|
* Constructs an instance.
|
||||||
* @param arena to use in creating foreign memory segments to access foreign structures.
|
|
||||||
* @param listener to receive translated device events.
|
* @param listener to receive translated device events.
|
||||||
*/
|
*/
|
||||||
public DeviceEventAdapter(Arena arena, IDeviceEventListener listener)
|
public DeviceEventAdapter(IDeviceEventListener listener)
|
||||||
{
|
{
|
||||||
if(arena == null)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Resource scope must be non-null");
|
|
||||||
}
|
|
||||||
|
|
||||||
mArena = arena;
|
|
||||||
|
|
||||||
setListener(listener);
|
setListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,35 +65,44 @@ public class DeviceEventAdapter implements sdrplay_api_EventCallback_t
|
|||||||
public void apply(int eventTypeId, int tunerSelectId, MemorySegment eventParametersPointer,
|
public void apply(int eventTypeId, int tunerSelectId, MemorySegment eventParametersPointer,
|
||||||
MemorySegment callbackContext)
|
MemorySegment callbackContext)
|
||||||
{
|
{
|
||||||
MemorySegment memorySegment = sdrplay_api_EventParamsT.ofAddress(eventParametersPointer, mArena.scope());
|
try(Arena arena = Arena.openConfined())
|
||||||
EventType eventType = EventType.fromValue(eventTypeId);
|
|
||||||
TunerSelect tunerSelect = TunerSelect.fromValue(tunerSelectId);
|
|
||||||
|
|
||||||
switch(eventType)
|
|
||||||
{
|
{
|
||||||
case GAIN_CHANGE -> {
|
MemorySegment memorySegment = sdrplay_api_EventParamsT.ofAddress(eventParametersPointer, arena.scope());
|
||||||
mDeviceEventListener.processGainChange(tunerSelect,
|
EventType eventType = EventType.fromValue(eventTypeId);
|
||||||
EventParametersFactory.createGainCallbackParameters(memorySegment));
|
TunerSelect tunerSelect = TunerSelect.fromValue(tunerSelectId);
|
||||||
}
|
|
||||||
case POWER_OVERLOAD_CHANGE -> {
|
switch(eventType)
|
||||||
mDeviceEventListener.processPowerOverload(tunerSelect,
|
{
|
||||||
EventParametersFactory.createPowerOverloadCallbackParameters(memorySegment));
|
case GAIN_CHANGE ->
|
||||||
}
|
{
|
||||||
case DEVICE_REMOVED -> {
|
mDeviceEventListener.processGainChange(tunerSelect,
|
||||||
mDeviceEventListener.processDeviceRemoval(tunerSelect);
|
EventParametersFactory.createGainCallbackParameters(memorySegment));
|
||||||
}
|
}
|
||||||
case RSP_DUO_MODE_CHANGE -> {
|
case POWER_OVERLOAD_CHANGE ->
|
||||||
mDeviceEventListener.processRspDuoModeChange(tunerSelect,
|
{
|
||||||
EventParametersFactory.createRspDuoModeCallbackParameters(memorySegment));
|
mDeviceEventListener.processPowerOverload(tunerSelect,
|
||||||
}
|
EventParametersFactory.createPowerOverloadCallbackParameters(memorySegment));
|
||||||
case UNKNOWN -> {
|
}
|
||||||
mLog.warn("Unknown device event callback ignored. Please contact the library developer as this may " +
|
case DEVICE_REMOVED ->
|
||||||
"indicate a change to the SDRPlay API change. Tuner:" + tunerSelect + " Event Type ID:" +
|
{
|
||||||
eventTypeId);
|
mDeviceEventListener.processDeviceRemoval(tunerSelect);
|
||||||
mDeviceEventListener.processEvent(eventType, tunerSelect);
|
}
|
||||||
}
|
case RSP_DUO_MODE_CHANGE ->
|
||||||
default -> {
|
{
|
||||||
throw new IllegalStateException("DeviceEventAdapter must be updated handle EventType." + eventType);
|
mDeviceEventListener.processRspDuoModeChange(tunerSelect,
|
||||||
|
EventParametersFactory.createRspDuoModeCallbackParameters(memorySegment));
|
||||||
|
}
|
||||||
|
case UNKNOWN ->
|
||||||
|
{
|
||||||
|
mLog.warn("Unknown device event callback ignored. Please contact the library developer as this may " +
|
||||||
|
"indicate a change to the SDRPlay API change. Tuner:" + tunerSelect + " Event Type ID:" +
|
||||||
|
eventTypeId);
|
||||||
|
mDeviceEventListener.processEvent(eventType, tunerSelect);
|
||||||
|
}
|
||||||
|
default ->
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("DeviceEventAdapter must be updated handle EventType." + eventType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,24 +35,16 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class StreamCallbackAdapter implements sdrplay_api_StreamCallback_t
|
public class StreamCallbackAdapter implements sdrplay_api_StreamCallback_t
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(StreamCallbackAdapter.class);
|
private static final Logger mLog = LoggerFactory.getLogger(StreamCallbackAdapter.class);
|
||||||
private Arena mArena;
|
|
||||||
private IStreamListener mStreamListener;
|
private IStreamListener mStreamListener;
|
||||||
private IStreamCallbackListener mStreamCallbackListener;
|
private IStreamCallbackListener mStreamCallbackListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance of the callback implementation
|
* Constructs an instance of the callback implementation
|
||||||
* @param arena for defining new foreign memory segments
|
|
||||||
* @param streamListener to receive transferred I/Q samples and event details
|
* @param streamListener to receive transferred I/Q samples and event details
|
||||||
* @param listener to receive callback parameters
|
* @param listener to receive callback parameters
|
||||||
*/
|
*/
|
||||||
public StreamCallbackAdapter(Arena arena, IStreamListener streamListener, IStreamCallbackListener listener)
|
public StreamCallbackAdapter(IStreamListener streamListener, IStreamCallbackListener listener)
|
||||||
{
|
{
|
||||||
if(arena == null)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Arena must be non-null");
|
|
||||||
}
|
|
||||||
|
|
||||||
mArena = arena;
|
|
||||||
mStreamCallbackListener = listener;
|
mStreamCallbackListener = listener;
|
||||||
setListener(streamListener);
|
setListener(streamListener);
|
||||||
}
|
}
|
||||||
@@ -81,24 +73,27 @@ public class StreamCallbackAdapter implements sdrplay_api_StreamCallback_t
|
|||||||
{
|
{
|
||||||
if(mStreamListener != null || mStreamCallbackListener != null)
|
if(mStreamListener != null || mStreamCallbackListener != null)
|
||||||
{
|
{
|
||||||
//Translate the callback parameters pointer to a memory segment and re-construct the parameters as a Java object
|
try(Arena arena = Arena.openConfined())
|
||||||
StreamCallbackParameters parameters = new StreamCallbackParameters(sdrplay_api_StreamCbParamsT
|
|
||||||
.ofAddress(parametersPointer, mArena.scope()));
|
|
||||||
|
|
||||||
if(mStreamCallbackListener != null)
|
|
||||||
{
|
{
|
||||||
mStreamCallbackListener.process(mStreamListener.getTunerSelect(), parameters, reset);
|
//Translate the callback parameters pointer to a memory segment and re-construct the parameters as a Java object
|
||||||
}
|
StreamCallbackParameters parameters = new StreamCallbackParameters(sdrplay_api_StreamCbParamsT
|
||||||
|
.ofAddress(parametersPointer, arena.scope()));
|
||||||
|
|
||||||
if(mStreamListener != null)
|
if(mStreamCallbackListener != null)
|
||||||
{
|
{
|
||||||
//Allocate memory segments from I/Q pointers, transfer from native to JVM array, and send to listener
|
mStreamCallbackListener.process(mStreamListener.getTunerSelect(), parameters, reset);
|
||||||
long arrayByteSize = ValueLayout.JAVA_SHORT.byteSize() * sampleCount;
|
}
|
||||||
MemorySegment iSamples = MemorySegment.ofAddress(iSamplesPointer.address(), arrayByteSize, mArena.scope());
|
|
||||||
MemorySegment qSamples = MemorySegment.ofAddress(qSamplesPointer.address(), arrayByteSize, mArena.scope());
|
if(mStreamListener != null)
|
||||||
short[] i = iSamples.toArray(ValueLayout.JAVA_SHORT);
|
{
|
||||||
short[] q = qSamples.toArray(ValueLayout.JAVA_SHORT);
|
//Allocate memory segments from I/Q pointers, transfer from native to JVM array, and send to listener
|
||||||
mStreamListener.processStream(i, q, parameters, Flag.evaluate(reset));
|
long arrayByteSize = ValueLayout.JAVA_SHORT.byteSize() * sampleCount;
|
||||||
|
MemorySegment iSamples = MemorySegment.ofAddress(iSamplesPointer.address(), arrayByteSize, arena.scope());
|
||||||
|
MemorySegment qSamples = MemorySegment.ofAddress(qSamplesPointer.address(), arrayByteSize, arena.scope());
|
||||||
|
short[] i = iSamples.toArray(ValueLayout.JAVA_SHORT);
|
||||||
|
short[] q = qSamples.toArray(ValueLayout.JAVA_SHORT);
|
||||||
|
mStreamListener.processStream(i, q, parameters, Flag.evaluate(reset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,46 +41,35 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class Dispatcher<E> implements Listener<E>
|
public class Dispatcher<E> implements Listener<E>
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(Dispatcher.class);
|
private final static Logger mLog = LoggerFactory.getLogger(Dispatcher.class);
|
||||||
private static final long OVERFLOW_LOG_EVENT_WAIT_PERIOD = TimeUnit.SECONDS.toMillis(10);
|
private final LinkedTransferQueue<E> mQueue = new LinkedTransferQueue<>();
|
||||||
private LinkedTransferQueue<E> mQueue = new LinkedTransferQueue<>();
|
|
||||||
private Listener<E> mListener;
|
private Listener<E> mListener;
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private final AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
private String mThreadName;
|
private final String mThreadName;
|
||||||
private ScheduledExecutorService mExecutorService;
|
private ScheduledExecutorService mExecutorService;
|
||||||
private ScheduledFuture<?> mScheduledFuture;
|
private ScheduledFuture<?> mScheduledFuture;
|
||||||
private int mBatchSize;
|
private final long mInterval;
|
||||||
private long mInterval;
|
|
||||||
private HeartbeatManager mHeartbeatManager;
|
private HeartbeatManager mHeartbeatManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance of a Dispatcher with integrated heartbeat support.
|
* Constructs an instance of a Dispatcher with integrated heartbeat support.
|
||||||
* @param threadName to name the dispatcher thread
|
* @param threadName to name the dispatcher thread
|
||||||
* @param batchSize is maximum number of elements to process from the queue per interval. This should be sized to
|
|
||||||
* the anticipated number of elements per second, divided by the number of intervals per second and increased by
|
|
||||||
* a factor of two. This serves to constrain how many elements are processed per interval when the queue starts
|
|
||||||
* to back up, so that the thread doesn't dominate CPU resources.
|
|
||||||
* @param interval for processing each batch in milliseconds.
|
* @param interval for processing each batch in milliseconds.
|
||||||
* @param heartbeatManager to receive a heartbeat command at each processing interval.
|
* @param heartbeatManager to receive a heartbeat command at each processing interval.
|
||||||
*/
|
*/
|
||||||
public Dispatcher(String threadName, int batchSize, long interval, HeartbeatManager heartbeatManager)
|
public Dispatcher(String threadName, long interval, HeartbeatManager heartbeatManager)
|
||||||
{
|
{
|
||||||
this(threadName, batchSize, interval);
|
this(threadName, interval);
|
||||||
mHeartbeatManager = heartbeatManager;
|
mHeartbeatManager = heartbeatManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param threadName to name the dispatcher thread
|
* @param threadName to name the dispatcher thread
|
||||||
* @param batchSize is maximum number of elements to process from the queue per interval. This should be sized to
|
|
||||||
* the anticipated number of elements per second, divided by the number of intervals per second and increased by
|
|
||||||
* a factor of two. This serves to constrain how many elements are processed per interval when the queue starts
|
|
||||||
* to back up, so that the thread doesn't dominate CPU resources.
|
|
||||||
* @param interval for processing each batch in milliseconds.
|
* @param interval for processing each batch in milliseconds.
|
||||||
*/
|
*/
|
||||||
public Dispatcher(String threadName, int batchSize, long interval)
|
public Dispatcher(String threadName, long interval)
|
||||||
{
|
{
|
||||||
mThreadName = threadName;
|
mThreadName = threadName;
|
||||||
mBatchSize = batchSize;
|
|
||||||
mInterval = interval;
|
mInterval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +160,7 @@ public class Dispatcher<E> implements Listener<E>
|
|||||||
{
|
{
|
||||||
List<E> elements = new ArrayList<>();
|
List<E> elements = new ArrayList<>();
|
||||||
|
|
||||||
mQueue.drainTo(elements, mBatchSize);
|
mQueue.drainTo(elements);
|
||||||
|
|
||||||
for(E element: elements)
|
for(E element: elements)
|
||||||
{
|
{
|
||||||
@@ -195,7 +184,7 @@ public class Dispatcher<E> implements Listener<E>
|
|||||||
*/
|
*/
|
||||||
class Processor implements Runnable
|
class Processor implements Runnable
|
||||||
{
|
{
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private final AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
@@ -214,7 +203,7 @@ public class Dispatcher<E> implements Listener<E>
|
|||||||
*/
|
*/
|
||||||
class ProcessorWithHeartbeat implements Runnable
|
class ProcessorWithHeartbeat implements Runnable
|
||||||
{
|
{
|
||||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
private final AtomicBoolean mRunning = new AtomicBoolean();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
|
|||||||
Reference in New Issue
Block a user