mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-10 23:57:25 -05:00
Compare commits
290 Commits
v0.3.3-bet
...
v0.4.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fe070987a | ||
|
|
00d5610213 | ||
|
|
d3c1a605df | ||
|
|
85df151a96 | ||
|
|
8915797aac | ||
|
|
03a5d71a95 | ||
|
|
4158d4ac10 | ||
|
|
f934676bd0 | ||
|
|
d5b802e794 | ||
|
|
139227e46d | ||
|
|
2394d51a51 | ||
|
|
d9fa2bea5b | ||
|
|
0cb360eeed | ||
|
|
ea472f873f | ||
|
|
8cbdbd527e | ||
|
|
ff0d893bd9 | ||
|
|
7b924d0486 | ||
|
|
712eb07f4b | ||
|
|
d5c3ecc7df | ||
|
|
c4bf089667 | ||
|
|
378b03e06e | ||
|
|
34235382fb | ||
|
|
c05aff0768 | ||
|
|
f0c3e0fd1a | ||
|
|
d601cbda0e | ||
|
|
2653dc6b38 | ||
|
|
48cbbfc656 | ||
|
|
d6892b9203 | ||
|
|
59f0844fcc | ||
|
|
43b285a50a | ||
|
|
4e92a6e350 | ||
|
|
25d387f3cf | ||
|
|
52e3d9d20d | ||
|
|
1e37a63d34 | ||
|
|
e51f485a2e | ||
|
|
9378254a38 | ||
|
|
4ab37735e8 | ||
|
|
85ca66f656 | ||
|
|
d716b0be1c | ||
|
|
70444c1337 | ||
|
|
d90e149021 | ||
|
|
7510664e00 | ||
|
|
5481fb7d4d | ||
|
|
3a39ae76ba | ||
|
|
08ea5ab7cb | ||
|
|
3fa7401a2b | ||
|
|
fce10960fb | ||
|
|
10b6a08624 | ||
|
|
5960343637 | ||
|
|
347a71f097 | ||
|
|
5b5a1431b4 | ||
|
|
efd811407e | ||
|
|
b67d4d92dc | ||
|
|
735fca16d6 | ||
|
|
72fe72c833 | ||
|
|
4a4d1d4b2e | ||
|
|
2ed7074c0d | ||
|
|
b5a895c266 | ||
|
|
b57d7b5c0e | ||
|
|
cb12d314d0 | ||
|
|
eb79d9e037 | ||
|
|
d95c78c0f1 | ||
|
|
aee5ece8d2 | ||
|
|
ba358a7d48 | ||
|
|
09b209496b | ||
|
|
cc209683bd | ||
|
|
2771c28dba | ||
|
|
d752917073 | ||
|
|
28bc02e172 | ||
|
|
0f6044d48b | ||
|
|
58ecb83e2c | ||
|
|
9e1de922e4 | ||
|
|
84d0b827d8 | ||
|
|
a17132be0d | ||
|
|
dae68515a5 | ||
|
|
0aaec8ff54 | ||
|
|
001883edc2 | ||
|
|
335fb51456 | ||
|
|
e94b6ae172 | ||
|
|
785125da4f | ||
|
|
81b8f5a423 | ||
|
|
bf186a7408 | ||
|
|
43fc326f93 | ||
|
|
7cdbb75b42 | ||
|
|
96a56cab68 | ||
|
|
29d4b36cf7 | ||
|
|
b15a3e59a0 | ||
|
|
9950e46e5a | ||
|
|
570321da3e | ||
|
|
bb0bcd3198 | ||
|
|
cb54850f99 | ||
|
|
5bb8c46bd5 | ||
|
|
2a3fd2c5a3 | ||
|
|
d712feb45a | ||
|
|
fbb24a4c05 | ||
|
|
3992f8178c | ||
|
|
8642def77e | ||
|
|
38e6de6cb2 | ||
|
|
994e78f42b | ||
|
|
b8a46af836 | ||
|
|
1c6d19959a | ||
|
|
50bc3088b7 | ||
|
|
09356848eb | ||
|
|
316bfb19c2 | ||
|
|
c045c8f16d | ||
|
|
8946d789ff | ||
|
|
19399d9138 | ||
|
|
9acdf22b91 | ||
|
|
f963d821a1 | ||
|
|
ade0cef50b | ||
|
|
2044c2a2de | ||
|
|
1c312a50b6 | ||
|
|
54f6bd09e2 | ||
|
|
5f8f2ec330 | ||
|
|
d7e018f66e | ||
|
|
c2a232fdee | ||
|
|
c5d2dcd0cf | ||
|
|
8e4e4129ca | ||
|
|
9176ca610f | ||
|
|
97b31e4d9b | ||
|
|
a3e5520d3e | ||
|
|
8c456972cc | ||
|
|
35d81ab31d | ||
|
|
b90b06e600 | ||
|
|
04144ca677 | ||
|
|
d3c7a50918 | ||
|
|
0fd29fa35a | ||
|
|
c00b173064 | ||
|
|
2718367259 | ||
|
|
3f0c13096a | ||
|
|
71ba4adbd7 | ||
|
|
3908e29a2e | ||
|
|
0c47efea03 | ||
|
|
5c0d97d942 | ||
|
|
61ae0d2d83 | ||
|
|
68f2a8da2c | ||
|
|
0d69f11e65 | ||
|
|
b3d5daea8b | ||
|
|
fe34623c4a | ||
|
|
353747cecc | ||
|
|
a8c649ef64 | ||
|
|
8cf50e629e | ||
|
|
20a8f2bb3c | ||
|
|
8c237be682 | ||
|
|
2d5271b849 | ||
|
|
609a1e86c7 | ||
|
|
821e719015 | ||
|
|
104c4f72be | ||
|
|
9e7fa7618d | ||
|
|
ee09520181 | ||
|
|
fa12b840db | ||
|
|
183d7d6d19 | ||
|
|
e2550869ce | ||
|
|
e88944e53d | ||
|
|
0051a1d381 | ||
|
|
f7a873dd0c | ||
|
|
ad560db5ea | ||
|
|
6f1ce79461 | ||
|
|
df1bc1031e | ||
|
|
a621a31aa9 | ||
|
|
19fa256c60 | ||
|
|
7a830077bd | ||
|
|
f4793f3cfd | ||
|
|
2cd3b73633 | ||
|
|
18f50485d3 | ||
|
|
b410cf0dfe | ||
|
|
1fdcb623a6 | ||
|
|
9dda1f95a1 | ||
|
|
a5c8552937 | ||
|
|
e4209c8e4f | ||
|
|
a898be265f | ||
|
|
c13315f731 | ||
|
|
341e740e77 | ||
|
|
cbc228d798 | ||
|
|
488b2e02ce | ||
|
|
e395d737f8 | ||
|
|
7a9f705517 | ||
|
|
dfaf506e23 | ||
|
|
81c9a352a8 | ||
|
|
e6937764c3 | ||
|
|
5bfc5bf456 | ||
|
|
ce83273393 | ||
|
|
95aa9f8803 | ||
|
|
e971ad4582 | ||
|
|
ff9395e4b9 | ||
|
|
d023da9ead | ||
|
|
60ffb18cd9 | ||
|
|
c36f6901af | ||
|
|
bfaacb309d | ||
|
|
c3b405a752 | ||
|
|
3619b480f8 | ||
|
|
830b2a2d34 | ||
|
|
78bb5ffe43 | ||
|
|
5dd1664844 | ||
|
|
8868c1f954 | ||
|
|
646bd78037 | ||
|
|
5af4cb8706 | ||
|
|
45a6c5a0b6 | ||
|
|
b563f2d11b | ||
|
|
148ddd0bd5 | ||
|
|
a0630102e6 | ||
|
|
3d1ac30646 | ||
|
|
dda37a1198 | ||
|
|
eaf7c7d11e | ||
|
|
80c5ad1bc8 | ||
|
|
956bf2d76a | ||
|
|
1406d5576a | ||
|
|
03e39f3343 | ||
|
|
28f351287c | ||
|
|
54227703a2 | ||
|
|
bb078de0a9 | ||
|
|
ec30cd6305 | ||
|
|
5a88ac0200 | ||
|
|
05eea44f7e | ||
|
|
030fc1617c | ||
|
|
594a77a9d0 | ||
|
|
c2fcc9e85d | ||
|
|
28da8b2fa4 | ||
|
|
1c06c4382f | ||
|
|
28cb9d9407 | ||
|
|
96d9d6f750 | ||
|
|
85691edacb | ||
|
|
f2f2c92afe | ||
|
|
fcd3c2fd46 | ||
|
|
e78d2339ff | ||
|
|
673c8a2423 | ||
|
|
5a03a0038c | ||
|
|
e7f7d27a1f | ||
|
|
0cf964fa98 | ||
|
|
b6f282a85a | ||
|
|
32ab0598e8 | ||
|
|
5ae3cb38e1 | ||
|
|
78205bb1bf | ||
|
|
3d9b38bef5 | ||
|
|
d5b377b1af | ||
|
|
a7a0c26b38 | ||
|
|
d4761be00a | ||
|
|
05fa5c25fd | ||
|
|
69e9bed2af | ||
|
|
d2e7f008c8 | ||
|
|
ddad4b6fb0 | ||
|
|
b65dd7e414 | ||
|
|
b076587f30 | ||
|
|
336669f1d5 | ||
|
|
46cf7f4193 | ||
|
|
e9aeb09011 | ||
|
|
236df8f3f4 | ||
|
|
667c50174d | ||
|
|
1c71a37755 | ||
|
|
318e6f3586 | ||
|
|
f38184fd83 | ||
|
|
d2085052f6 | ||
|
|
441b595325 | ||
|
|
57fab2b7ca | ||
|
|
bf65e10286 | ||
|
|
a12aaf7cf3 | ||
|
|
b3e4bd6a9c | ||
|
|
5281679b7f | ||
|
|
a581da56a8 | ||
|
|
0181926fe3 | ||
|
|
2c3be02939 | ||
|
|
a00ec42230 | ||
|
|
14a3532030 | ||
|
|
3be65d5e9a | ||
|
|
c21f3fca23 | ||
|
|
99d81d247a | ||
|
|
27461df7f0 | ||
|
|
9983d2119d | ||
|
|
9e275b7d62 | ||
|
|
f461ed9cdb | ||
|
|
7c6b7494b8 | ||
|
|
ab31b40124 | ||
|
|
ac686f5f64 | ||
|
|
f7cd798f07 | ||
|
|
41d307cdad | ||
|
|
afae1654d5 | ||
|
|
ffc92a8f0e | ||
|
|
6d9e129087 | ||
|
|
0e1da8fb3b | ||
|
|
7d5371db4c | ||
|
|
131290fcd2 | ||
|
|
e2fe06638b | ||
|
|
17c16e16ee | ||
|
|
cd4eaedfcc | ||
|
|
fd748fec79 | ||
|
|
14b844f0bd | ||
|
|
99ef002d07 | ||
|
|
e868428c88 | ||
|
|
d2542d2560 | ||
|
|
9ca87299d5 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -17,7 +17,7 @@ out/
|
||||
*.class
|
||||
*.log
|
||||
# Package Files #
|
||||
*.jar
|
||||
#*.jar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -2,8 +2,10 @@
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel>
|
||||
<module name="sdr-trunk_main" target="1.8" />
|
||||
<module name="sdr-trunk_test" target="1.8" />
|
||||
<module name="sdr-trunk_main" target="11" />
|
||||
<module name="sdr-trunk_test" target="11" />
|
||||
<module name="sdrtrunk-sdr-trunk_main" target="11" />
|
||||
<module name="sdrtrunk-sdr-trunk_test" target="11" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
32
.idea/dictionaries/denny.xml
generated
Normal file
32
.idea/dictionaries/denny.xml
generated
Normal file
@@ -0,0 +1,32 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="denny">
|
||||
<words>
|
||||
<w>bahroo</w>
|
||||
<w>broadcastify</w>
|
||||
<w>correlator</w>
|
||||
<w>dinf</w>
|
||||
<w>esnid</w>
|
||||
<w>fleetsync</w>
|
||||
<w>heterdyned</w>
|
||||
<w>heterodynes</w>
|
||||
<w>icecast</w>
|
||||
<w>ident</w>
|
||||
<w>nutall</w>
|
||||
<w>overflowable</w>
|
||||
<w>polyphase</w>
|
||||
<w>qpsk</w>
|
||||
<w>remez</w>
|
||||
<w>resampler</w>
|
||||
<w>samplerate</w>
|
||||
<w>sdrtrunk</w>
|
||||
<w>sheirer</w>
|
||||
<w>shoutcast</w>
|
||||
<w>streamable</w>
|
||||
<w>talkgroup</w>
|
||||
<w>tgid</w>
|
||||
<w>ultravox</w>
|
||||
<w>wacn</w>
|
||||
<w>xtea</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
12
.idea/libraries/imports.xml
generated
Normal file
12
.idea/libraries/imports.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<component name="libraryTable">
|
||||
<library name="imports">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/imports/java-lame-3.98.4.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/imports/commons-math3-3.6.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/imports/libresample4j-0.1.3.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/imports/jmbe-api-1.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
4
.idea/modules.xml
generated
4
.idea/modules.xml
generated
@@ -2,9 +2,11 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdr-trunk.iml" filepath="$PROJECT_DIR$/.idea/modules/sdr-trunk.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdr-trunk.iml" filepath="$PROJECT_DIR$/.idea/modules/sdr-trunk.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdr-trunk_main.iml" filepath="$PROJECT_DIR$/.idea/modules/sdr-trunk_main.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdr-trunk_test.iml" filepath="$PROJECT_DIR$/.idea/modules/sdr-trunk_test.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdrtrunk-sdr-trunk_main.iml" filepath="$PROJECT_DIR$/.idea/modules/sdrtrunk-sdr-trunk_main.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/sdrtrunk-sdr-trunk_test.iml" filepath="$PROJECT_DIR$/.idea/modules/sdrtrunk-sdr-trunk_test.iml" group="sdr-trunk" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/vcs.xml
generated
10
.idea/vcs.xml
generated
@@ -1,5 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="IssueNavigationConfiguration">
|
||||
<option name="links">
|
||||
<list>
|
||||
<IssueNavigationLink>
|
||||
<option name="issueRegexp" value="#(\d+)" />
|
||||
<option name="linkRegexp" value="https://github.com/DSheirer/sdrtrunk/issues/$1" />
|
||||
</IssueNavigationLink>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
0.3.4 20180418
|
||||
- New P25 C4FM decoder that uses Differential QPSK decoder instead of FM demodulation with 4FSK.
|
||||
- Adds channel auto-start and ordering capability with startup dialog allowing user to invoke or bypass channel
|
||||
auto-start. Provides user with more control over startup configuration.
|
||||
- Adds preferred tuner attribute to channel configuration allowing user to select a preferred tuner for the channel
|
||||
|
||||
0.3.3 20171225
|
||||
- Changes build system from ant to gradle. Thanks to: Roman Tsypuk https://github.com/tsypuk
|
||||
- Adds LIST and ID3 metadata to wav audio recordings
|
||||
|
||||
62
README.md
62
README.md
@@ -1,17 +1,54 @@
|
||||
# sdrtrunk
|
||||
A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR).
|
||||
|
||||
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/GettingStarted)
|
||||
* [User's Manual Version 0.3.0](https://github.com/DSheirer/sdrtrunk/wiki/UserManual_Version0.3.0)
|
||||
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/GettingStarted_V0.3.0)
|
||||
* [User's Manual Version 0.3.0](https://github.com/DSheirer/sdrtrunk/wiki/UserManual_V0.3.0)
|
||||
* [Download](https://github.com/DSheirer/sdrtrunk/releases)
|
||||
* [Support](https://groups.google.com/forum/#!forum/sdrtrunk)
|
||||
|
||||

|
||||

|
||||
**Figure 1:** sdrtrunk **Version 0.3.0** Application Screenshot
|
||||
|
||||
# Instructions:
|
||||
# End User Instructions:
|
||||
|
||||
If you simply want to download and run the program, please follow these instructions.
|
||||
|
||||
## Install Java 8 (or newer)
|
||||
|
||||
## Download the latest sdrtrunk release
|
||||
|
||||
All release versions of sdrtrunk are available from the [releases](https://github.com/DSheirer/sdrtrunk/releases) tab.
|
||||
|
||||
**(final)** These versions have been tested and are the current release version.
|
||||
|
||||
**(alpha)** These versions are under development feature previews and likely to contain bugs and unexpected behavior.
|
||||
|
||||
**(beta)** These versions are currently being tested for bugs and functionality.
|
||||
|
||||
## Run the application
|
||||
|
||||
Either double-click on the downloaded file (if supported on your operating system) or open a terminal/command window
|
||||
and change to the directory where you downloaded the release file and type:
|
||||
|
||||
```
|
||||
java -jar downloaded-jar-filename
|
||||
```
|
||||
|
||||
Note: replace _downloaded-jar-filename_ with the actual name of the sdrtrunk release version that you downloaded
|
||||
|
||||
## Optional - P25 Audio
|
||||
If you're using sdrtrunk with a P25 trunked radio system, the [JMBE](https://github.com/DSheirer/sdrtrunk/wiki/JMBE) wiki page contains instructions
|
||||
for downloading the JMBE audio library source code and compiling the JMBE library. Copy the resulting JMBE audio library
|
||||
jar file to the same folder containing the sdrtrunk application to use the library with sdrtrunk.
|
||||
|
||||
# Developer Instructions:
|
||||
|
||||
If you're interested in modifying and/or compiling the source code, please follow these instructions to use gradle to compile the code.
|
||||
|
||||
## Build the project
|
||||
Project uses gradle as build system. You can build it with locally installed gradle or if you do not have/want install gradle you can use preconfigured linux/windows wrapper.
|
||||
sdrtrunk uses gradle as the build system. You can build it with locally installed gradle or if you do not have/want
|
||||
to install gradle you can use preconfigured linux/windows wrapper.
|
||||
|
||||
### Build with locally installed gradle 4.3.1
|
||||
```
|
||||
gradle clean buildSdr
|
||||
@@ -23,7 +60,7 @@ Linux
|
||||
```
|
||||
Windows
|
||||
```
|
||||
gradle.bat clean buildSdr
|
||||
gradlew.bat clean buildSdr
|
||||
```
|
||||
This would add gradle, download all project dependencies and build JAR
|
||||
|
||||
@@ -35,20 +72,9 @@ version = '0.3.2'
|
||||
```
|
||||
|
||||
## Run SDRTrunk
|
||||
SDRTrunk is packed into single uber-jar file. There is need to have folders with dependecies and
|
||||
SDRTrunk is packed into single uber-jar file. There is need to have folders with dependencies and
|
||||
adding them with classpath. Just run with java.
|
||||
### Use Java8
|
||||
```
|
||||
java -jar build/libs/sdr-trunk-all-0.3.2.jar
|
||||
```
|
||||
|
||||
## TODO ITEMS
|
||||
|
||||
- [x] Move project to gradle build
|
||||
- [x] Changed folders structure, based on java project
|
||||
- [x] Dependencies are moved to gradle and versions are updated
|
||||
- [x] Create uberJAR with all dependencies
|
||||
- [ ] Some dependencies left in imports folder. Find them and include into gradle
|
||||
- [ ] Move images into resources of project
|
||||
- [ ] Add tests to project. This would guarantee that after refactoring part of functionality is not broken
|
||||
- [ ] Create modular OOP system (radio-module, gui, web-ui, etc). This would allow to use RADIO modules to call from CLI, GUI or Web UI. And use SDRTrunk as dependency for other projects.
|
||||
250
build.gradle
250
build.gradle
@@ -1,28 +1,91 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
}
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
plugins {
|
||||
id 'application'
|
||||
id 'java'
|
||||
id 'idea'
|
||||
id 'org.openjfx.javafxplugin' version '0.0.6'
|
||||
id 'org.beryx.runtime' version '1.8.0'
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
version = '0.3.3-beta.2'
|
||||
sourceCompatibility = 1.8
|
||||
version = '0.4.0-beta.1'
|
||||
sourceCompatibility = '11'
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs 'src/main'
|
||||
test.java.srcDirs 'src/test'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.assertj:assertj-core:3.8.0'
|
||||
compile fileTree(dir: 'imports', include: '*.jar')
|
||||
compile 'ch.qos.logback:logback-core:1.2.3'
|
||||
compile 'ch.qos.logback:logback-classic:1.2.3'
|
||||
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
||||
compile 'com.fazecast:jSerialComm:2.5.0'
|
||||
compile 'com.github.jiconfont:jiconfont-font_awesome:4.7.0.1'
|
||||
compile 'com.github.jiconfont:jiconfont-javafx:1.0.0'
|
||||
compile 'com.github.jiconfont:jiconfont-swing:1.0.1'
|
||||
compile 'com.github.wendykierp:JTransforms:3.1'
|
||||
compile 'com.google.guava:guava:27.0.1-jre'
|
||||
compile 'com.jidesoft:jide-oss:3.6.18'
|
||||
compile 'com.miglayout:miglayout-swing:5.2'
|
||||
compile 'eu.hansolo:charts:1.0.5'
|
||||
compile 'io.github.dsheirer:radio-reference-api:15.0.1'
|
||||
compile 'javax.usb:usb-api:1.0.2'
|
||||
compile 'net.coderazzi:tablefilter-swing:5.4.0'
|
||||
compile 'org.apache.commons:commons-lang3:3.8.1'
|
||||
compile 'org.apache.commons:commons-io:1.3.2'
|
||||
compile 'org.apache.mina:mina-core:2.0.19'
|
||||
compile 'org.apache.mina:mina-http:2.0.19'
|
||||
compile "org.openjfx:javafx-base:11:win"
|
||||
compile "org.openjfx:javafx-base:11:linux"
|
||||
compile "org.openjfx:javafx-base:11:mac"
|
||||
compile "org.openjfx:javafx-controls:11.0.2:win"
|
||||
compile "org.openjfx:javafx-controls:11.0.2:linux"
|
||||
compile "org.openjfx:javafx-controls:11.0.2:mac"
|
||||
compile "org.openjfx:javafx-graphics:11.0.2:win"
|
||||
compile "org.openjfx:javafx-graphics:11.0.2:linux"
|
||||
compile "org.openjfx:javafx-graphics:11.0.2:mac"
|
||||
compile "org.openjfx:javafx-swing:11.0.2:win"
|
||||
compile "org.openjfx:javafx-swing:11.0.2:linux"
|
||||
compile "org.openjfx:javafx-swing:11.0.2:mac"
|
||||
compile 'org.slf4j:slf4j-api:1.7.25'
|
||||
compile 'org.usb4java:libusb4java:1.3.0'
|
||||
compile 'org.usb4java:usb4java:1.3.0'
|
||||
compile 'org.usb4java:usb4java-javax:1.3.0'
|
||||
compile 'pl.edu.icm:JLargeArrays:1.6'
|
||||
}
|
||||
|
||||
application {
|
||||
mainClassName = "io.github.dsheirer.gui.SDRTrunk"
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
downloadJavadoc = true
|
||||
@@ -30,44 +93,135 @@ idea {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.assertj:assertj-core:3.8.0'
|
||||
compile fileTree(dir: 'imports', include: '*.jar')
|
||||
compile 'org.apache.commons:commons-lang3:3.7'
|
||||
compile 'org.apache.commons:commons-io:1.3.2'
|
||||
compile 'org.slf4j:slf4j-api:1.7.25'
|
||||
compile 'ch.qos.logback:logback-core:1.2.3'
|
||||
compile 'ch.qos.logback:logback-classic:1.2.3'
|
||||
compile 'com.miglayout:miglayout-swing:5.0'
|
||||
|
||||
compile 'org.usb4java:usb4java-javax:1.2.0'
|
||||
compile 'org.usb4java:usb4java:1.2.0'
|
||||
compile 'org.usb4java:libusb4java:1.2.0'
|
||||
compile 'javax.usb:usb-api:1.0.2'
|
||||
compile 'com.github.wendykierp:JTransforms:3.1'
|
||||
compile 'pl.edu.icm:JLargeArrays:1.6'
|
||||
compile 'net.coderazzi:tablefilter-swing:5.3.1'
|
||||
compile 'com.jidesoft:jide-oss:3.4.3'
|
||||
compile 'org.apache.mina:mina-core:2.0.16'
|
||||
compile 'org.apache.mina:mina-http:2.0.16'
|
||||
compile 'org.apache.axis:axis-jaxrpc:1.4'
|
||||
compile 'org.apache.axis:axis:1.4'
|
||||
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.3'
|
||||
javafx {
|
||||
modules = ['javafx.base', 'javafx.controls', 'javafx.graphics', 'javafx.swing']
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '4.3.1'
|
||||
}
|
||||
|
||||
task buildSdr(type: Jar) {
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Implementation-Title': 'SdrTrunk project',
|
||||
'Implementation-Version': version,
|
||||
'Main-Class': 'io.github.dsheirer.gui.SDRTrunk',
|
||||
'Class-Path': 'jmbe-0.3.2.jar jmbe-0.3.3.jar'
|
||||
attributes (
|
||||
'Implementation-Title' : 'sdrtrunk project',
|
||||
'Implementation-Version' : archiveVersion,
|
||||
'Class-Path' : 'jmbe-1.0.0.jar',
|
||||
'Created-By' : "Gradle ${gradle.gradleVersion}",
|
||||
'Build-Timestamp' : new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
|
||||
'Build-JDK' : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']}",
|
||||
'Build-OS' : "${System.properties['os.name']} (${System.properties['os.arch']} ${System.properties['os.version']}"
|
||||
)
|
||||
}
|
||||
baseName = project.name + '-all'
|
||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
with jar
|
||||
}
|
||||
|
||||
/**
|
||||
* Java Development Kit (JDK) locations. These paths must point to the 'bin' directory
|
||||
* within a JDK for each of the specified architectures. These JDKs are used by the
|
||||
* runtime and runtimeZip tasks to produce platform-specific builds
|
||||
*/
|
||||
def jdkLinux_x64 = '/media/denny/WD250GB/java/bellsoft/linux-x64/jdk-13.0.1'
|
||||
def jdkLinux_x86 = '/media/denny/WD250GB/java/bellsoft/linux-x86/jdk-13.0.1'
|
||||
def jdkOsx_x64 = '/media/denny/WD250GB/java/bellsoft/osx-x64/jdk-13.0.1.jdk'
|
||||
def jdkWindows_x64 = '/media/denny/WD250GB/java/bellsoft/windows-x64/jdk-13.0.1'
|
||||
def jdkWindows_x86 = '/media/denny/WD250GB/java/bellsoft/windows-x86/jdk-13.0.1'
|
||||
//def jdkLinux_aarch64 = '/media/denny/WD250GB/java/bellsoft/linux-aarch64/jdk-11.0.2'
|
||||
//def jdkLinux_arm32 = '/media/denny/WD250GB/java/bellsoft/linux-arm32/jdk-11.0.2'
|
||||
//def jfxLinux_arm32 = '/media/denny/WD250GB/java/bellsoft/linux-arm32/armv6hf-sdk/lib'
|
||||
|
||||
runtime {
|
||||
targetPlatform('linux-x64', jdkLinux_x64)
|
||||
targetPlatform('linux-x86', jdkLinux_x86)
|
||||
targetPlatform('osx-x64', jdkOsx_x64)
|
||||
targetPlatform('windows-x64', jdkWindows_x64)
|
||||
targetPlatform('windows-x86', jdkWindows_x86)
|
||||
// targetPlatform('linux-aarch64', jdkLinux_aarch64)
|
||||
// targetPlatform('linux-arm32', jdkLinux_arm32)
|
||||
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
|
||||
modules = ['java.desktop', 'java.naming', 'jdk.unsupported', 'jdk.unsupported.desktop']
|
||||
imageZip = file("$buildDir/image/sdr-trunk-" + version + ".zip")
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for existence of JDK folders for each supported platform before creating runtime images
|
||||
*/
|
||||
tasks.runtime.doFirst {
|
||||
def linux_x64 = new File(jdkLinux_x64)
|
||||
|
||||
if(!linux_x64.exists())
|
||||
{
|
||||
println("Linux x64 JDK was not found at " + jdkLinux_x64)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for linux-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
}
|
||||
|
||||
def linux_x86 = new File(jdkLinux_x86)
|
||||
|
||||
if(!linux_x86.exists())
|
||||
{
|
||||
println("Linux x86 JDK was not found at " + jdkLinux_x86)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for linux-x86 32-bit architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
}
|
||||
|
||||
def osx_x64 = new File(jdkOsx_x64)
|
||||
|
||||
if(!osx_x64.exists())
|
||||
{
|
||||
println("OSX x64 JDK was not found at " + jdkOsx_x64);
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for osx-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
}
|
||||
|
||||
def windows_x64 = new File(jdkWindows_x64)
|
||||
|
||||
if(!windows_x64.exists())
|
||||
{
|
||||
println("Windows x64 JDK was not found at " + jdkWindows_x64)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for windows-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
}
|
||||
|
||||
def windows_x86 = new File(jdkWindows_x86)
|
||||
|
||||
if(!windows_x86.exists())
|
||||
{
|
||||
println("Windows x86 32-bit JDK was not found at " + jdkWindows_x86)
|
||||
throw new GradleException("Cannot find Java Development Kit (JDK) for windows-x64 architecture. " +
|
||||
"Please update the build.gradle script to provide the correct path")
|
||||
}
|
||||
|
||||
// def linux_aarch64 = new File(jdkLinux_aarch64)
|
||||
//
|
||||
// if(!linux_aarch64.exists())
|
||||
// {
|
||||
// println("Linux aarch64 JDK was not found at " + jdkLinux_aarch64)
|
||||
// throw new GradleException("Cannot find Java Development Kit (JDK) for linux-aarch64 architecture. " +
|
||||
// "Please update the build.gradle script to provide the correct path")
|
||||
// }
|
||||
//
|
||||
// def linux_arm32 = new File(jdkLinux_arm32)
|
||||
//
|
||||
// if(!linux_arm32.exists())
|
||||
// {
|
||||
// println("Linux arm32 JDK was not found at " + jdkLinux_arm32)
|
||||
// throw new GradleException("Cannot find Java Development Kit (JDK) for linux-arm32 architecture. " +
|
||||
// "Please update the build.gradle script to provide the correct path")
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we have to list each of the platform-specific JavaFX libraries as dependencies,
|
||||
* remove them from each build image
|
||||
*/
|
||||
tasks.runtime.doLast {
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x64/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-linux-x86/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-osx-x64/lib').include { it.name ==~ /javafx.*-(win|linux)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x64/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
delete(fileTree('build/image/sdr-trunk-windows-x86/lib').include { it.name ==~ /javafx.*-(linux|mac)\.jar/ })
|
||||
|
||||
// delete(fileTree('build/image/sdr-trunk-linux-aarch64/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
// delete(fileTree('build/image/sdr-trunk-linux-arm32/lib').include { it.name ==~ /javafx.*-(win|mac)\.jar/ })
|
||||
// copy {
|
||||
// from(jfxLinux_arm32).exclude("src.zip")
|
||||
// into 'build/image/sdr-trunk-linux-arm32/lib'
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
******************************************************************************/
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
26
gradle/wrapper/gradle-wrapper.properties
vendored
26
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,27 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
|
||||
#
|
||||
# /*
|
||||
# * ******************************************************************************
|
||||
# * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
# *
|
||||
# * This program is free software: you can redistribute it and/or modify
|
||||
# * it under the terms of the GNU General Public License as published by
|
||||
# * the Free Software Foundation, either version 3 of the License, or
|
||||
# * (at your option) any later version.
|
||||
# *
|
||||
# * This program is distributed in the hope that it will be useful,
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# * GNU General Public License for more details.
|
||||
# *
|
||||
# * You should have received a copy of the GNU General Public License
|
||||
# * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
# * *****************************************************************************
|
||||
# */
|
||||
#
|
||||
#
|
||||
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
2
gradlew
vendored
2
gradlew
vendored
@@ -28,7 +28,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
BIN
imports/commons-math3-3.6.1.jar
Normal file
BIN
imports/commons-math3-3.6.1.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
imports/libresample4j-0.1.3.jar
Normal file
BIN
imports/libresample4j-0.1.3.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
929
sdr-trunk.ipr
Normal file
929
sdr-trunk.ipr
Normal file
@@ -0,0 +1,929 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions>
|
||||
<entry name=".+\.(properties|xml|html|dtd|tld)" />
|
||||
<entry name=".+\.(gif|png|jpeg|jpg)" />
|
||||
</resourceExtensions>
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.groovy" />
|
||||
</wildcardResourcePatterns>
|
||||
<bytecodeTargetLevel target="11">
|
||||
<module name="sdr-trunk_main" target="11" />
|
||||
<module name="sdr-trunk_test" target="11" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
<component name="CopyrightManager" default="sdrtrunk">
|
||||
<copyright>
|
||||
<option name="notice" value="sdr-trunk Copyright (C) 2014-&#36;today.year 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/> " />
|
||||
<option name="myName" value="sdrtrunk" />
|
||||
</copyright>
|
||||
<LanguageOptions name="JAVA">
|
||||
<option name="fileTypeOverride" value="3" />
|
||||
<option name="separateBefore" value="true" />
|
||||
<option name="separateAfter" value="true" />
|
||||
</LanguageOptions>
|
||||
</component>
|
||||
<component name="DependencyValidationManager">
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</component>
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$USER_HOME$/gradle/gradle-2.12" />
|
||||
<option name="gradleJvm" value="11" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="useAutoImport" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
<component name="GradleUISettings">
|
||||
<setting name="root" />
|
||||
</component>
|
||||
<component name="GradleUISettings2">
|
||||
<setting name="root" />
|
||||
</component>
|
||||
<component name="IdProvider" IDEtalkID="11DA1DB66DD62DDA1ED602B7079FE97C" />
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
</profile>
|
||||
<version value="1.0" />
|
||||
</component>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
<option name="OPTION_INDEX" value="true" />
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true" />
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true" />
|
||||
<option name="OTHER_OPTIONS" value="" />
|
||||
<option name="HEAP_SIZE" />
|
||||
<option name="LOCALE" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
</component>
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Denny">
|
||||
<words>
|
||||
<w>baseband</w>
|
||||
<w>costas</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/sdr-trunk.iml" filepath="$PROJECT_DIR$/sdr-trunk.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sdr-trunk_main.iml" filepath="$PROJECT_DIR$/sdr-trunk_main.iml" group="sdr-trunk" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sdr-trunk_test.iml" filepath="$PROJECT_DIR$/sdr-trunk_test.iml" group="sdr-trunk" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="SvnBranchConfigurationManager">
|
||||
<option name="mySupportsUserInfoFilter" value="true" />
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
<component name="libraryTable">
|
||||
<library name="Gradle: ch.qos.logback:logback-classic:1.2.3">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/7c4f3c474fb2c041d8028740440937705ebb473a/logback-classic-1.2.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/99b0433b7d86044643b7d677f22d2c793d31d416/logback-classic-1.2.3-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/cfd5385e0c5ed1c8a5dce57d86e79cf357153a64/logback-classic-1.2.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: ch.qos.logback:logback-core:1.2.3">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.2.3/864344400c3d4d92dfeb0a305dc87d953677c03c/logback-core-1.2.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.2.3/c978d4afd24d32991c8aa31a9c8a1119f19a1cb4/logback-core-1.2.3-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.2.3/3ebabe69eba0196af9ad3a814f723fb720b9101e/logback-core-1.2.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.jackson.core:jackson-annotations:2.9.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.9.0/7c10d545325e3a6e72e06381afe469fd40eb701/jackson-annotations-2.9.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.9.0/9978adad2c78154ca4aca7cd2a71941e1278f724/jackson-annotations-2.9.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.9.0/a0ad4e203304ccab7e01266fa814115850edb8a9/jackson-annotations-2.9.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.jackson.core:jackson-core:2.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.9.8/f5a654e4675769c716e5b387830d19b501ca191/jackson-core-2.9.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.9.8/acc65b3b6e07784dc1760fa4e460238eb2a9073a/jackson-core-2.9.8-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.9.8/ecaea301e166a0b48f11615864246de739b6619b/jackson-core-2.9.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.jackson.core:jackson-databind:2.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.9.8/11283f21cc480aa86c4df7a0a3243ec508372ed2/jackson-databind-2.9.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.9.8/a1dea243882227fc27c350a5b25ca76ef4ecb7d7/jackson-databind-2.9.8-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.9.8/f66792d499a6fea6c7a743558f940e0ebf775ce3/jackson-databind-2.9.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.9.8/6a068ddeeafe736da35fba3a7f64462081b562c9/jackson-dataformat-xml-2.9.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.9.8/ba3a439d041b333550de55e34c370d9221011911/jackson-dataformat-xml-2.9.8-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.9.8/2d48d64536472ff6138cab6ba731b29247fdb0fb/jackson-dataformat-xml-2.9.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.9.8/da08815ba1c7f7b435e7df02b7bf98327bad2fd4/jackson-module-jaxb-annotations-2.9.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.9.8/575e1a2a77b830cd3c369931b71b653114314a43/jackson-module-jaxb-annotations-2.9.8-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.9.8/b68061d95e61cc7c4a574f449cd9db7bad66d75b/jackson-module-jaxb-annotations-2.9.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fasterxml.woodstox:woodstox-core:5.0.3">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.woodstox/woodstox-core/5.0.3/10aa199207fda142eff01cd61c69244877d71770/woodstox-core-5.0.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.woodstox/woodstox-core/5.0.3/7f5316fa0b4e68daa353bb2df3c546bfd854d54f/woodstox-core-5.0.3-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fasterxml.woodstox/woodstox-core/5.0.3/f38482e8b060d9e5354c10103f4c4db53c58db7d/woodstox-core-5.0.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.fazecast:jSerialComm:2.5.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fazecast/jSerialComm/2.5.0/df146deefea578aa38de43a0658f06ac297acb6f/jSerialComm-2.5.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fazecast/jSerialComm/2.5.0/1aa3e4d710396f7bc56661b23a6d125bf5d3749/jSerialComm-2.5.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.fazecast/jSerialComm/2.5.0/b9e6222384a17cb10474b7f25768edf4b742ec16/jSerialComm-2.5.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.jiconfont:jiconfont-font_awesome:4.7.0.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-font_awesome/4.7.0.1/121d019023f631af04a1357e637dd05a2cc91f7b/jiconfont-font_awesome-4.7.0.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-font_awesome/4.7.0.1/278c25d163a2e2eec5b2e93669b73936365cea69/jiconfont-font_awesome-4.7.0.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-font_awesome/4.7.0.1/8c79f5ccd872310c6dfd4f89f7fe3f748fba94a4/jiconfont-font_awesome-4.7.0.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.jiconfont:jiconfont-javafx:1.0.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-javafx/1.0.0/233530f110ab0c3ff845aa52799c43645a11f1c8/jiconfont-javafx-1.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-javafx/1.0.0/8cf9282bff0c0cf56cab9ba18f74943019f9a979/jiconfont-javafx-1.0.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-javafx/1.0.0/687e090ac5e1b4d20a242995a80631043d4ee78d/jiconfont-javafx-1.0.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.jiconfont:jiconfont-swing:1.0.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-swing/1.0.1/14621054d72340b4a664cce4710ba974a3882a19/jiconfont-swing-1.0.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-swing/1.0.1/55df548424fa5159247b05f02eb712719ce75d5/jiconfont-swing-1.0.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont-swing/1.0.1/cae76b75041118062159ffa0a7e2109cc7f88fad/jiconfont-swing-1.0.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.jiconfont:jiconfont:1.0.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont/1.0.0/e17d93321975b6735ebc283f6832fa0350614d3a/jiconfont-1.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont/1.0.0/8dc32616a97fe4b54380821a6aab9d8930262262/jiconfont-1.0.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.jiconfont/jiconfont/1.0.0/e79316fba9458423ce944fba6da101262549464/jiconfont-1.0.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.wendykierp:JTransforms:3.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.wendykierp/JTransforms/3.1/f1f6d3c9c9bc04f848e38bdb77dea01e8764a01f/JTransforms-3.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.wendykierp/JTransforms/3.1/30208ebb430bee1b2e48e28478853bc9628c0e54/JTransforms-3.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.wendykierp/JTransforms/3.1/fc9cbab6459c03db12a643bc5dc1b1475a3f0b52/JTransforms-3.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.google.code.findbugs:jsr305:3.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/3.0.2/25ea2e8b0c338a877313bd4672d3fe056ea78f0d/jsr305-3.0.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/3.0.2/7cb5b4e91eb0741882c8fefb2fd0338eff9857c/jsr305-3.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/3.0.2/b19b5927c2c25b6c70f093767041e641ae0b1b35/jsr305-3.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.google.errorprone:error_prone_annotations:2.2.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.2.0/88e3c593e9b3586e1c6177f89267da6fc6986f0c/error_prone_annotations-2.2.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.2.0/959f406f238a0e047ed2a227479ff9db28173be9/error_prone_annotations-2.2.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.2.0/a8cd7823aa1dcd2fd6677c0c5988fdde9d1fb0a3/error_prone_annotations-2.2.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.google.guava:failureaccess:1.0.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/failureaccess/1.0.1/1dcf1de382a0bf95a3d8b0849546c88bac1292c9/failureaccess-1.0.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/failureaccess/1.0.1/a9aadb2d577ff54ba3115ee7357cbe65bd2a470f/failureaccess-1.0.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/failureaccess/1.0.1/1d064e61aad6c51cc77f9b59dc2cccc78e792f5a/failureaccess-1.0.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.google.guava:guava:27.0.1-jre">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/27.0.1-jre/bd41a290787b5301e63929676d792c507bbc00ae/guava-27.0.1-jre.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/27.0.1-jre/7515204e130bb73fea9f6df11e58559e6be2dcf0/guava-27.0.1-jre-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/27.0.1-jre/cb5c1119df8d41a428013289b193eba3ccaf5f60/guava-27.0.1-jre-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/b421526c5f297295adef1c886e5246c39d4ac629/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: com.google.j2objc:j2objc-annotations:1.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/976d8d30bebc251db406f2bdb3eb01962b5685b3/j2objc-annotations-1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/2e1e0c8db5be95ec85d19d456186f8989ea263fa/j2objc-annotations-1.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/dcd31de68a90e41e336f6b7afce0d39285c433d7/j2objc-annotations-1.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.jidesoft:jide-oss:3.6.18">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jidesoft/jide-oss/3.6.18/2a0b8ef9ed1f18607b70f1e627d862fb8e595373/jide-oss-3.6.18.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jidesoft/jide-oss/3.6.18/814e47763c22729f665a4232da421824831ea734/jide-oss-3.6.18-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jidesoft/jide-oss/3.6.18/b9cadcf869c0bdd032756228315252516856ad56/jide-oss-3.6.18-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.miglayout:miglayout-core:5.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-core/5.2/c1234205bde8fa72a420ecc5f63b9f269edccbfb/miglayout-core-5.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-core/5.2/43595a2a4d2da858dfe1163f0d0ce769b7fbb11/miglayout-core-5.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-core/5.2/4b3f0bfa2312173be31f87caa3cc58b617eea1df/miglayout-core-5.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.miglayout:miglayout-swing:5.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-swing/5.2/53e2fc5586a120797e3af0ff4cf9adb3b403ab14/miglayout-swing-5.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-swing/5.2/9ca06755a629747815fa91b3cd480bfb40fbb0e1/miglayout-swing-5.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.miglayout/miglayout-swing/5.2/df798d1660b3106a0304efa9e04dfd1a1a2e6025/miglayout-swing-5.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: commons-io:commons-io:1.3.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/1.3.2/b6dde38349ba9bb5e6ea6320531eae969985dae5/commons-io-1.3.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/1.3.2/6927a72f39651d8d57070a35c3ba669c2314a47c/commons-io-1.3.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/1.3.2/b41a5f39fa90007a6c247175933555ba5f166d70/commons-io-1.3.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: eu.hansolo:charts:1.0.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/eu.hansolo/charts/1.0.5/2bb9d233ac3e5f678920ff04effd57c0ba21d860/charts-1.0.5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/eu.hansolo/charts/1.0.5/d65ed2f94c0d5579cf87eea01c5d14fa8196d235/charts-1.0.5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/eu.hansolo/charts/1.0.5/aa26011a2c525ddf86cb92ed23558b18c0174fa4/charts-1.0.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: io.github.dsheirer:radio-reference-api:15.0.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.github.dsheirer/radio-reference-api/15.0.1/8af16506c26025517f0bc971ba35485e96130c9a/radio-reference-api-15.0.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.github.dsheirer/radio-reference-api/15.0.1/219528429b3ed73f285a8c2c4ded40d8eae61fc0/radio-reference-api-15.0.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.github.dsheirer/radio-reference-api/15.0.1/b699a9821030b54fbb7f472f97fcc634afb114fb/radio-reference-api-15.0.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: javax.usb:usb-api:1.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.usb/usb-api/1.0.2/f0ae0d322a99811cf79d508d37f3dc2d82753070/usb-api-1.0.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.usb/usb-api/1.0.2/c0bc03446978d12d8b5b3e8a136a181936f61015/usb-api-1.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.usb/usb-api/1.0.2/4b6337e574535ac803bbc05f3f22808d8bdba0d0/usb-api-1.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: junit:junit:4.12">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/941a8be4506c65f0a9001c08812fb7da1e505e21/junit-4.12-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/a6c32b40bf3d76eca54e3c601e5d1470c86fcdfa/junit-4.12-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: net.coderazzi:tablefilter-swing:5.4.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.coderazzi/tablefilter-swing/5.4.0/ba7415b409712bf1988b2f03eda7730deba26c10/tablefilter-swing-5.4.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.coderazzi/tablefilter-swing/5.4.0/3bc5c263fc43180f4137a41bd0848851830761ff/tablefilter-swing-5.4.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.coderazzi/tablefilter-swing/5.4.0/298121afccdf36281e234aaf478f97ddbe8aecf3/tablefilter-swing-5.4.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.apache.commons:commons-lang3:3.8.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.8.1/6505a72a097d9270f7a9e7bf42c4238283247755/commons-lang3-3.8.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.8.1/e7e19f37a0e712862967e39558b888fb59ee5b6a/commons-lang3-3.8.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.8.1/e9748d7783594da3735ad9724390a10e7cebc01d/commons-lang3-3.8.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.apache.commons:commons-math3:3.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.5/13af68e9a11576953f5c4b09436f8207be9d3a27/commons-math3-3.5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.5/e6106a9927c5ee66d0e647ad116af26c9b6b5f06/commons-math3-3.5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.5/1d3f412d28c8bff0e8f048240b08bcd21cfa432e/commons-math3-3.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.apache.mina:mina-core:2.0.19">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-core/2.0.19/b6ba5d8c6d1dd38a1151c590018e4e5edd6c4cfa/mina-core-2.0.19.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-core/2.0.19/b50fe4a0802588c70fa9f23ae6dcefe54a688bca/mina-core-2.0.19-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-core/2.0.19/a070a03134f7c4f5c9ad79b094423d48f3e9551b/mina-core-2.0.19-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.apache.mina:mina-http:2.0.19">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-http/2.0.19/b42328dbaeed685376821fe704f70ad36f4de24/mina-http-2.0.19.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-http/2.0.19/3d6ce6d25fc14d858486f50a96213872ca7ae467/mina-http-2.0.19-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.mina/mina-http/2.0.19/ce16dff76ec41be9f9c21df8bb8c271a3bb709cb/mina-http-2.0.19-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.assertj:assertj-core:3.8.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/3.8.0/b209d90ff2e279bee3e02547ee7b11349c52d0e3/assertj-core-3.8.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/3.8.0/a2958ce39a3fd0ccdb52502e3a839edec50b6a98/assertj-core-3.8.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/3.8.0/85dab3e124fb391b10196df9bfdb43640deabb09/assertj-core-3.8.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.checkerframework:checker-qual:2.5.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.checkerframework/checker-qual/2.5.2/cea74543d5904a30861a61b4643a5f2bb372efc4/checker-qual-2.5.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.checkerframework/checker-qual/2.5.2/bfab5d13a888ce75ba0104fdb310808e445ff67d/checker-qual-2.5.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.checkerframework/checker-qual/2.5.2/ebb8ebccd42218434674f3e1d9022c13df1c19f8/checker-qual-2.5.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.codehaus.mojo:animal-sniffer-annotations:1.17">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.17/f97ce6decaea32b36101e37979f8b647f00681fb/animal-sniffer-annotations-1.17.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.17/c67d33bf1588c89f633cf6b5a629d0e1dc1b02c4/animal-sniffer-annotations-1.17-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.17/8fb5b5ad9c9723951b9fccaba5bb657fa6064868/animal-sniffer-annotations-1.17-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.codehaus.woodstox:stax2-api:3.1.4">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.woodstox/stax2-api/3.1.4/ac19014b1e6a7c08aad07fe114af792676b685b7/stax2-api-3.1.4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.woodstox/stax2-api/3.1.4/819aa74f907d379c6afc2e0376808ca9feadcbb1/stax2-api-3.1.4-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.woodstox/stax2-api/3.1.4/b40604d61c01cc081a4a7bdfc562aa9847ee8857/stax2-api-3.1.4-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.hamcrest:hamcrest-core:1.3">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/ad09811315f1d4f5756986575b0ea16b99cd686f/hamcrest-core-1.3-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b/hamcrest-core-1.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-base:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/7fb2e4a8528ec9e434a9ac9ee98b39af79e6dcb8/javafx-base-11.0.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/f0dfede8adbd1b28d1b5084bd2812ace69ebe673/javafx-base-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/c082cdf645f9833408dcd960bf68344c9384f569/javafx-base-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-base:linux:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/8db178adb1085d455e5ef643a48c34959c8771c1/javafx-base-11.0.2-linux.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/f0dfede8adbd1b28d1b5084bd2812ace69ebe673/javafx-base-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/c082cdf645f9833408dcd960bf68344c9384f569/javafx-base-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-base:mac:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/b774922e5da6a56afee221d1a288d179a1342aa9/javafx-base-11.0.2-mac.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/f0dfede8adbd1b28d1b5084bd2812ace69ebe673/javafx-base-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/c082cdf645f9833408dcd960bf68344c9384f569/javafx-base-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-base:win:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/1852e57b8cf9a9b6488c33605bccd5d06ff210e1/javafx-base-11.0.2-win.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/f0dfede8adbd1b28d1b5084bd2812ace69ebe673/javafx-base-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/c082cdf645f9833408dcd960bf68344c9384f569/javafx-base-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-controls:linux:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/5f6929050a744aab39ebfc1e8e5dd03bcd2ad47b/javafx-controls-11.0.2-linux.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/baa088249ee757119688e78d9c3a256928189902/javafx-controls-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/1535a8b57f01a712405a739a0d69e09ab99dbb6b/javafx-controls-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-controls:mac:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/996371d2868035845572cdb19179dca2bfd1139f/javafx-controls-11.0.2-mac.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/baa088249ee757119688e78d9c3a256928189902/javafx-controls-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/1535a8b57f01a712405a739a0d69e09ab99dbb6b/javafx-controls-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-controls:win:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/6c763707769c18adce406904c771c2ad1fcc370b/javafx-controls-11.0.2-win.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/baa088249ee757119688e78d9c3a256928189902/javafx-controls-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/1535a8b57f01a712405a739a0d69e09ab99dbb6b/javafx-controls-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-graphics:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/e522eb4ea422eceeee207b1c266ba3db19b2343a/javafx-graphics-11.0.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/b7ae1857e54ed7d8ca0e30e01d12fae2b75ba400/javafx-graphics-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/15eadef01f327a851a6d3af0ac89d56292076b13/javafx-graphics-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-graphics:linux:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/ef4c34f0ca77cd99100b76c2ccf1dce383572bb1/javafx-graphics-11.0.2-linux.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/b7ae1857e54ed7d8ca0e30e01d12fae2b75ba400/javafx-graphics-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/15eadef01f327a851a6d3af0ac89d56292076b13/javafx-graphics-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-graphics:mac:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/c1d99ae5bc48e7173f4514a941d27d8f8c972c71/javafx-graphics-11.0.2-mac.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/b7ae1857e54ed7d8ca0e30e01d12fae2b75ba400/javafx-graphics-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/15eadef01f327a851a6d3af0ac89d56292076b13/javafx-graphics-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-graphics:win:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/20459ea2cf714942bcbeb78a7f70ba3531dc1a44/javafx-graphics-11.0.2-win.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/b7ae1857e54ed7d8ca0e30e01d12fae2b75ba400/javafx-graphics-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/15eadef01f327a851a6d3af0ac89d56292076b13/javafx-graphics-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-swing:linux:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/cb57db3e5bd1e2b62b17c8a504858bfc26fa54b1/javafx-swing-11.0.2-linux.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/336999871b9a7e88179a76e2251c73f47e3d5cb6/javafx-swing-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/bcc8c0a402ff01a89a50888c9dc26824a9f3f2cc/javafx-swing-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-swing:mac:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/47efd914c1ebdeda8789a779c8341266340c743/javafx-swing-11.0.2-mac.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/336999871b9a7e88179a76e2251c73f47e3d5cb6/javafx-swing-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/bcc8c0a402ff01a89a50888c9dc26824a9f3f2cc/javafx-swing-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.openjfx:javafx-swing:win:11.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/9b5728e61148142fae8c47f6295c84d7a8d6c89/javafx-swing-11.0.2-win.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/336999871b9a7e88179a76e2251c73f47e3d5cb6/javafx-swing-11.0.2-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-swing/11.0.2/bcc8c0a402ff01a89a50888c9dc26824a9f3f2cc/javafx-swing-11.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.slf4j:slf4j-api:1.7.25">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.25/da76ca59f6a57ee3102f8f9bd9cee742973efa8a/slf4j-api-1.7.25.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.25/f003e89ddebdbaca5cf3fc7cc0c67c88c2ca1a3c/slf4j-api-1.7.25-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.25/962153db4a9ea71b79d047dfd1b2a0d80d8f4739/slf4j-api-1.7.25-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:darwin-x86-64:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/1fdaa8ec7cfad158be58fbc8e2867d05f2b5fe63/libusb4java-1.3.0-darwin-x86-64.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:linux-aarch64:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/bb5924dfb86c27ca5d91ccc975c11da2caa3c82d/libusb4java-1.3.0-linux-aarch64.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:linux-arm:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/504de50cc979b1f19b76ba1154d298632ff1be4e/libusb4java-1.3.0-linux-arm.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:linux-x86-64:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/9514c818fc97f831277873f082dcefd5394045e4/libusb4java-1.3.0-linux-x86-64.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:linux-x86:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/7abf7240bcd7c26cb1ea5265eec5e6d703b71b4e/libusb4java-1.3.0-linux-x86.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:win32-x86-64:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/8cd521a203404d65f4bc59c2a8a38eb4dcd302da/libusb4java-1.3.0-win32-x86-64.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:libusb4java:win32-x86:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/libusb4java/1.3.0/9cb97c4b8317d8dae0401f80438fde5bfd910b2c/libusb4java-1.3.0-win32-x86.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:usb4java-javax:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java-javax/1.3.0/b68f4617513a61e889fbf81926daba9c9accc96d/usb4java-javax-1.3.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java-javax/1.3.0/76268e0268e00cace559a5d3284b065d64044a76/usb4java-javax-1.3.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java-javax/1.3.0/684ff71e8ca72e5536116390909dd37fcb590690/usb4java-javax-1.3.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.usb4java:usb4java:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java/1.3.0/2d5487fdf303642d480b199a9da0c5a0d2bb0e82/usb4java-1.3.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java/1.3.0/e688082c68718dfbd6f566beb2eebf31cc225036/usb4java-1.3.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.usb4java/usb4java/1.3.0/e6f73cf21dbbc0ecf85417f311e13d8eb278d14a/usb4java-1.3.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: pl.edu.icm:JLargeArrays:1.6">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/pl.edu.icm/JLargeArrays/1.6/be888269f87ebf21f49d979925a07551f6e795ff/JLargeArrays-1.6.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/pl.edu.icm/JLargeArrays/1.6/80bc6536d3d1183ed46bf8a3fccfe8da9a65d34e/JLargeArrays-1.6-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/pl.edu.icm/JLargeArrays/1.6/20a1c4e9de9d8d4943ecdf723bed6a7f843ac20e/JLargeArrays-1.6-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ArtifactsStructureConfigurable.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl />
|
||||
</splitter-proportions>
|
||||
<settings />
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="Copyright.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl />
|
||||
</splitter-proportions>
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</SplitterProportionsDataImpl>
|
||||
</splitter-proportions>
|
||||
<last-edited>1.6</last-edited>
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="ScopeChooserConfigurable.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl />
|
||||
</splitter-proportions>
|
||||
<settings />
|
||||
</UIState>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,20 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@@ -24,10 +26,10 @@ import io.github.dsheirer.alias.action.AliasAction;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -187,7 +189,7 @@ public class Alias
|
||||
* Returns the priority level of this alias, if defined, or the default priority
|
||||
*/
|
||||
@JsonIgnore
|
||||
public int getCallPriority()
|
||||
public int getPlaybackPriority()
|
||||
{
|
||||
for(AliasID id : mAliasIDs)
|
||||
{
|
||||
@@ -245,27 +247,39 @@ public class Alias
|
||||
{
|
||||
for(AliasID id : getId())
|
||||
{
|
||||
if(id.getType() == AliasIDType.NON_RECORDABLE)
|
||||
if(id.getType() == AliasIDType.RECORD)
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or removes the non-recordable alias ID for this alias.
|
||||
* Sets or removes the record alias ID for this alias.
|
||||
*/
|
||||
public void setRecordable(boolean recordable)
|
||||
{
|
||||
if(recordable)
|
||||
{
|
||||
for(AliasID id : getId())
|
||||
{
|
||||
if(id.getType() == AliasIDType.RECORD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addAliasID(new Record());
|
||||
}
|
||||
else
|
||||
{
|
||||
AliasID toRemove = null;
|
||||
|
||||
for(AliasID id : getId())
|
||||
{
|
||||
if(id.getType() == AliasIDType.NON_RECORDABLE)
|
||||
if(id.getType() == AliasIDType.RECORD)
|
||||
{
|
||||
toRemove = id;
|
||||
break;
|
||||
@@ -277,18 +291,6 @@ public class Alias
|
||||
removeAliasID(toRemove);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(AliasID id : getId())
|
||||
{
|
||||
if(id.getType() == AliasIDType.NON_RECORDABLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addAliasID(new NonRecordable());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,34 +1,67 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import net.coderazzi.filters.gui.AutoChoices;
|
||||
import net.coderazzi.filters.gui.TableFilterHeader;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AliasController extends JPanel
|
||||
implements ActionListener, ListSelectionListener
|
||||
public class AliasController extends JPanel implements ActionListener, ListSelectionListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TABLE_PREFERENCE_KEY = "alias.controller";
|
||||
private AliasModel mAliasModel;
|
||||
private JTable mAliasTable;
|
||||
private TableFilterHeader mTableFilterHeader;
|
||||
private AliasEditor mAliasEditor;
|
||||
private MultipleAliasEditor mMultipleAliasEditor;
|
||||
private JideSplitPane mSplitPane;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private static final String NEW_ALIAS = "New";
|
||||
private static final String COPY_ALIAS = "Copy";
|
||||
@@ -39,15 +72,16 @@ public class AliasController extends JPanel
|
||||
private JButton mDeleteButton = new JButton(DELETE_ALIAS);
|
||||
|
||||
private IconCellRenderer mIconCellRenderer;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
|
||||
public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager)
|
||||
public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
|
||||
mAliasEditor = new AliasEditor(mAliasModel, broadcastModel, iconManager);
|
||||
mMultipleAliasEditor = new MultipleAliasEditor(mAliasModel, broadcastModel, iconManager);
|
||||
|
||||
mIconCellRenderer = new IconCellRenderer(iconManager);
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
|
||||
@@ -56,9 +90,7 @@ public class AliasController extends JPanel
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0",
|
||||
"[grow,fill]",
|
||||
"[grow,fill]"));
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
//System Configuration View and Editor
|
||||
mAliasTable = new JTable(mAliasModel);
|
||||
@@ -66,11 +98,11 @@ public class AliasController extends JPanel
|
||||
mAliasTable.getSelectionModel().addListSelectionListener(this);
|
||||
mAliasTable.setAutoCreateRowSorter(true);
|
||||
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR)
|
||||
.setCellRenderer(new ColorCellRenderer());
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR).setCellRenderer(new ColorCellRenderer());
|
||||
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON)
|
||||
.setCellRenderer(mIconCellRenderer);
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON).setCellRenderer(mIconCellRenderer);
|
||||
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mAliasTable, TABLE_PREFERENCE_KEY);
|
||||
|
||||
mTableFilterHeader = new TableFilterHeader(mAliasTable, AutoChoices.ENABLED);
|
||||
mTableFilterHeader.setFilterOnUpdates(true);
|
||||
@@ -79,8 +111,8 @@ public class AliasController extends JPanel
|
||||
|
||||
JPanel buttonsPanel = new JPanel();
|
||||
|
||||
buttonsPanel.setLayout(
|
||||
new MigLayout("insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]"));
|
||||
buttonsPanel.setLayout(new MigLayout("insets 0 0 0 0",
|
||||
"[grow,fill][grow,fill][grow,fill]", "[]"));
|
||||
|
||||
mNewButton.addActionListener(this);
|
||||
mNewButton.setToolTipText("Adds a new alias");
|
||||
@@ -98,8 +130,8 @@ public class AliasController extends JPanel
|
||||
|
||||
JPanel listAndButtonsPanel = new JPanel();
|
||||
|
||||
listAndButtonsPanel.setLayout(
|
||||
new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill][]"));
|
||||
listAndButtonsPanel.setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]",
|
||||
"[grow,fill][]"));
|
||||
|
||||
listAndButtonsPanel.add(tableScroller, "wrap");
|
||||
listAndButtonsPanel.add(buttonsPanel);
|
||||
@@ -212,18 +244,11 @@ public class AliasController extends JPanel
|
||||
*/
|
||||
private void addAlias(Alias alias)
|
||||
{
|
||||
//HACK: when inserting a row to the model, the JTable gets
|
||||
//notified and attempts to tell the coderazzi table filter
|
||||
//adaptive choices filter to refresh before the table filter is
|
||||
//notified of the row additions, causing an index out of bounds
|
||||
//exception. We turn off adaptive choices temporarily, add the
|
||||
//channel, and turn on adaptive choices again.
|
||||
mTableFilterHeader.setAdaptiveChoices(false);
|
||||
//Remove any column headers so that the newly added alias shows correctly.
|
||||
mTableFilterHeader.resetFilter();
|
||||
|
||||
int index = mAliasModel.addAlias(alias);
|
||||
|
||||
mTableFilterHeader.setAdaptiveChoices(true);
|
||||
|
||||
if(index >= 0)
|
||||
{
|
||||
int translatedIndex = mAliasTable.convertRowIndexToView(index);
|
||||
|
||||
@@ -31,8 +31,7 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class AliasEditor extends Editor<Alias>
|
||||
implements ActionListener, Listener<AliasEvent>
|
||||
public class AliasEditor extends Editor<Alias> implements ActionListener, Listener<AliasEvent>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
******************************************************************************/
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import io.github.dsheirer.alias.action.AliasAction;
|
||||
@@ -31,274 +33,289 @@ import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannelEditor;
|
||||
import io.github.dsheirer.alias.id.esn.ESNEditor;
|
||||
import io.github.dsheirer.alias.id.esn.Esn;
|
||||
import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.fleetsync.FleetsyncIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncIDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200IDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327IDEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordableEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupIDEditor;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackIDEditor;
|
||||
import io.github.dsheirer.alias.id.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.mdc.MDC1200IDEditor;
|
||||
import io.github.dsheirer.alias.id.mobileID.MINEditor;
|
||||
import io.github.dsheirer.alias.id.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.mpt1327.MPT1327IDEditor;
|
||||
import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.nonrecordable.NonRecordableEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.MINEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.priority.PriorityEditor;
|
||||
import io.github.dsheirer.alias.id.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.siteID.SiteIDEditor;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.record.RecordEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteIDEditor;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.status.StatusIDEditor;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupIDEditor;
|
||||
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.uniqueID.UniqueIDEditor;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupEditor;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRangeEditor;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueIDEditor;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
|
||||
public class AliasFactory
|
||||
{
|
||||
public static AliasID copyOf( AliasID id )
|
||||
{
|
||||
switch( id.getType() )
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
BroadcastChannel originalBroadcast = (BroadcastChannel)id;
|
||||
BroadcastChannel copyBroadcast = new BroadcastChannel();
|
||||
copyBroadcast.setChannelName(originalBroadcast.getChannelName());
|
||||
return copyBroadcast;
|
||||
case ESN:
|
||||
Esn originalESN = (Esn)id;
|
||||
Esn copyESN = new Esn();
|
||||
copyESN.setEsn( originalESN.getEsn() );
|
||||
return copyESN;
|
||||
case FLEETSYNC:
|
||||
FleetsyncID originalFleetsyncID = (FleetsyncID)id;
|
||||
FleetsyncID copyFleetsyncID = new FleetsyncID();
|
||||
copyFleetsyncID.setIdent( originalFleetsyncID.getIdent() );
|
||||
return copyFleetsyncID;
|
||||
case LTR_NET_UID:
|
||||
UniqueID originalUniqueID = (UniqueID)id;
|
||||
UniqueID copyUniqueID = new UniqueID();
|
||||
copyUniqueID.setUid( originalUniqueID.getUid() );
|
||||
return copyUniqueID;
|
||||
case LOJACK:
|
||||
LoJackFunctionAndID originalLoJackFunctionAndID = (LoJackFunctionAndID)id;
|
||||
LoJackFunctionAndID copyLoJackFunctionAndID = new LoJackFunctionAndID();
|
||||
copyLoJackFunctionAndID.setFunction( originalLoJackFunctionAndID.getFunction() );
|
||||
copyLoJackFunctionAndID.setID( originalLoJackFunctionAndID.getID() );
|
||||
return copyLoJackFunctionAndID;
|
||||
case MDC1200:
|
||||
MDC1200ID originalMDC1200ID = (MDC1200ID)id;
|
||||
MDC1200ID copyMDC1200ID = new MDC1200ID();
|
||||
copyMDC1200ID.setIdent( originalMDC1200ID.getIdent() );
|
||||
return copyMDC1200ID;
|
||||
case MIN:
|
||||
Min originalMin = (Min)id;
|
||||
Min copyMin = new Min();
|
||||
copyMin.setMin( originalMin.getMin() );
|
||||
return copyMin;
|
||||
case MPT1327:
|
||||
MPT1327ID originalMPT1327ID = (MPT1327ID)id;
|
||||
MPT1327ID copyMPT1327ID = new MPT1327ID();
|
||||
copyMPT1327ID.setIdent( originalMPT1327ID.getIdent() );
|
||||
return copyMPT1327ID;
|
||||
case NON_RECORDABLE:
|
||||
return new NonRecordable();
|
||||
case PRIORITY:
|
||||
Priority originalPriority = (Priority)id;
|
||||
Priority copyPriority = new Priority();
|
||||
copyPriority.setPriority( originalPriority.getPriority() );
|
||||
return copyPriority;
|
||||
case SITE:
|
||||
SiteID originalSiteID = (SiteID)id;
|
||||
SiteID copySiteID = new SiteID();
|
||||
copySiteID.setSite( originalSiteID.getSite() );
|
||||
return copySiteID;
|
||||
case TALKGROUP:
|
||||
TalkgroupID originalTalkgroupID = (TalkgroupID)id;
|
||||
TalkgroupID copyTalkgroupID = new TalkgroupID();
|
||||
copyTalkgroupID.setTalkgroup( originalTalkgroupID.getTalkgroup() );
|
||||
return copyTalkgroupID;
|
||||
case STATUS:
|
||||
StatusID originalStatusID = (StatusID)id;
|
||||
StatusID copyStatusID = new StatusID();
|
||||
copyStatusID.setStatus( originalStatusID.getStatus() );
|
||||
return copyStatusID;
|
||||
default:
|
||||
}
|
||||
public static AliasID copyOf(AliasID id)
|
||||
{
|
||||
switch(id.getType())
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
BroadcastChannel originalBroadcast = (BroadcastChannel)id;
|
||||
BroadcastChannel copyBroadcast = new BroadcastChannel();
|
||||
copyBroadcast.setChannelName(originalBroadcast.getChannelName());
|
||||
return copyBroadcast;
|
||||
case ESN:
|
||||
Esn originalESN = (Esn)id;
|
||||
Esn copyESN = new Esn();
|
||||
copyESN.setEsn(originalESN.getEsn());
|
||||
return copyESN;
|
||||
case LTR_NET_UID:
|
||||
UniqueID originalUniqueID = (UniqueID)id;
|
||||
UniqueID copyUniqueID = new UniqueID();
|
||||
copyUniqueID.setUid(originalUniqueID.getUid());
|
||||
return copyUniqueID;
|
||||
case LOJACK:
|
||||
LoJackFunctionAndID originalLoJackFunctionAndID = (LoJackFunctionAndID)id;
|
||||
LoJackFunctionAndID copyLoJackFunctionAndID = new LoJackFunctionAndID();
|
||||
copyLoJackFunctionAndID.setFunction(originalLoJackFunctionAndID.getFunction());
|
||||
copyLoJackFunctionAndID.setID(originalLoJackFunctionAndID.getID());
|
||||
return copyLoJackFunctionAndID;
|
||||
case MIN:
|
||||
Min originalMin = (Min)id;
|
||||
Min copyMin = new Min();
|
||||
copyMin.setMin(originalMin.getMin());
|
||||
return copyMin;
|
||||
case PRIORITY:
|
||||
Priority originalPriority = (Priority)id;
|
||||
Priority copyPriority = new Priority();
|
||||
copyPriority.setPriority(originalPriority.getPriority());
|
||||
return copyPriority;
|
||||
case RECORD:
|
||||
return new Record();
|
||||
case SITE:
|
||||
SiteID originalSiteID = (SiteID)id;
|
||||
SiteID copySiteID = new SiteID();
|
||||
copySiteID.setSite(originalSiteID.getSite());
|
||||
return copySiteID;
|
||||
case STATUS:
|
||||
StatusID originalStatusID = (StatusID)id;
|
||||
StatusID copyStatusID = new StatusID();
|
||||
copyStatusID.setStatus(originalStatusID.getStatus());
|
||||
return copyStatusID;
|
||||
case TALKGROUP:
|
||||
Talkgroup originalTalkgroup = (Talkgroup)id;
|
||||
Talkgroup copyTalkgroup = new Talkgroup(originalTalkgroup.getProtocol(), originalTalkgroup.getValue());
|
||||
return copyTalkgroup;
|
||||
case TALKGROUP_RANGE:
|
||||
TalkgroupRange originalRange = (TalkgroupRange)id;
|
||||
TalkgroupRange copyRange = new TalkgroupRange(originalRange.getProtocol(), originalRange.getMinTalkgroup(),
|
||||
originalRange.getMaxTalkgroup());
|
||||
return copyRange;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static AliasAction copyOf( AliasAction action )
|
||||
{
|
||||
if( action instanceof BeepAction )
|
||||
{
|
||||
return new BeepAction();
|
||||
}
|
||||
else if( action instanceof ClipAction)
|
||||
{
|
||||
ClipAction originalClip = (ClipAction)action;
|
||||
ClipAction copyClip = new ClipAction();
|
||||
copyClip.setInterval( originalClip.getInterval() );
|
||||
copyClip.setPath( originalClip.getPath() );
|
||||
copyClip.setPeriod( originalClip.getPeriod() );
|
||||
return copyClip;
|
||||
}
|
||||
else if( action instanceof ScriptAction )
|
||||
{
|
||||
ScriptAction originalScript = (ScriptAction)action;
|
||||
ScriptAction copyScript = new ScriptAction();
|
||||
copyScript.setInterval( originalScript.getInterval() );
|
||||
copyScript.setPeriod( originalScript.getPeriod() );
|
||||
copyScript.setScript( originalScript.getScript() );
|
||||
return copyScript;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Alias copyOf( Alias original )
|
||||
{
|
||||
Alias copy = new Alias( original.getName() );
|
||||
copy.setList( original.getList() );
|
||||
copy.setGroup( original.getGroup() );
|
||||
copy.setColor( original.getColor() );
|
||||
copy.setIconName( original.getIconName() );
|
||||
|
||||
for( AliasID id: original.getId() )
|
||||
{
|
||||
AliasID copyID = copyOf( id );
|
||||
|
||||
if( copyID != null )
|
||||
{
|
||||
copy.addAliasID( copyID );
|
||||
}
|
||||
}
|
||||
//Legacy identifiers ... not supported
|
||||
case FLEETSYNC:
|
||||
case LEGACY_TALKGROUP:
|
||||
case MDC1200:
|
||||
case MPT1327:
|
||||
case NON_RECORDABLE:
|
||||
default:
|
||||
}
|
||||
|
||||
for( AliasAction action: original.getAction() )
|
||||
{
|
||||
AliasAction copyAction = copyOf( action );
|
||||
|
||||
if( copyAction != null )
|
||||
{
|
||||
copy.addAliasAction( copyAction );
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static AliasAction copyOf(AliasAction action)
|
||||
{
|
||||
if(action instanceof BeepAction)
|
||||
{
|
||||
return new BeepAction();
|
||||
}
|
||||
else if(action instanceof ClipAction)
|
||||
{
|
||||
ClipAction originalClip = (ClipAction)action;
|
||||
ClipAction copyClip = new ClipAction();
|
||||
copyClip.setInterval(originalClip.getInterval());
|
||||
copyClip.setPath(originalClip.getPath());
|
||||
copyClip.setPeriod(originalClip.getPeriod());
|
||||
return copyClip;
|
||||
}
|
||||
else if(action instanceof ScriptAction)
|
||||
{
|
||||
ScriptAction originalScript = (ScriptAction)action;
|
||||
ScriptAction copyScript = new ScriptAction();
|
||||
copyScript.setInterval(originalScript.getInterval());
|
||||
copyScript.setPeriod(originalScript.getPeriod());
|
||||
copyScript.setScript(originalScript.getScript());
|
||||
return copyScript;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Alias copyOf(Alias original)
|
||||
{
|
||||
Alias copy = new Alias(original.getName());
|
||||
copy.setList(original.getList());
|
||||
copy.setGroup(original.getGroup());
|
||||
copy.setColor(original.getColor());
|
||||
copy.setIconName(original.getIconName());
|
||||
|
||||
for(AliasID id : original.getId())
|
||||
{
|
||||
AliasID copyID = copyOf(id);
|
||||
|
||||
if(copyID != null)
|
||||
{
|
||||
copy.addAliasID(copyID);
|
||||
}
|
||||
}
|
||||
|
||||
for(AliasAction action : original.getAction())
|
||||
{
|
||||
AliasAction copyAction = copyOf(action);
|
||||
|
||||
if(copyAction != null)
|
||||
{
|
||||
copy.addAliasAction(copyAction);
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static Editor<AliasID> getEditor(AliasID aliasID, BroadcastModel broadcastModel)
|
||||
{
|
||||
if(aliasID != null)
|
||||
{
|
||||
switch(aliasID.getType())
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
return new BroadcastChannelEditor(aliasID, broadcastModel);
|
||||
case ESN:
|
||||
return new ESNEditor(aliasID);
|
||||
case LTR_NET_UID:
|
||||
return new UniqueIDEditor(aliasID);
|
||||
case LOJACK:
|
||||
return new LoJackIDEditor(aliasID);
|
||||
case MIN:
|
||||
return new MINEditor(aliasID);
|
||||
case PRIORITY:
|
||||
return new PriorityEditor(aliasID);
|
||||
case RECORD:
|
||||
return new RecordEditor(aliasID);
|
||||
case SITE:
|
||||
return new SiteIDEditor(aliasID);
|
||||
case STATUS:
|
||||
return new StatusIDEditor(aliasID);
|
||||
case TALKGROUP:
|
||||
return new TalkgroupEditor(aliasID);
|
||||
case TALKGROUP_RANGE:
|
||||
return new TalkgroupRangeEditor(aliasID);
|
||||
|
||||
case FLEETSYNC:
|
||||
return new FleetsyncIDEditor(aliasID);
|
||||
case LEGACY_TALKGROUP:
|
||||
return new LegacyTalkgroupIDEditor(aliasID);
|
||||
case MDC1200:
|
||||
return new MDC1200IDEditor(aliasID);
|
||||
case MPT1327:
|
||||
return new MPT1327IDEditor(aliasID);
|
||||
case NON_RECORDABLE:
|
||||
return new NonRecordableEditor(aliasID);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyEditor<AliasID>();
|
||||
}
|
||||
|
||||
public static Editor<AliasAction> getEditor(AliasAction aliasAction)
|
||||
{
|
||||
if(aliasAction != null)
|
||||
{
|
||||
switch(aliasAction.getType())
|
||||
{
|
||||
case BEEP:
|
||||
return new BeepActionEditor(aliasAction);
|
||||
case CLIP:
|
||||
return new ClipActionEditor(aliasAction);
|
||||
case SCRIPT:
|
||||
return new ScriptActionEditor(aliasAction);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyEditor<AliasAction>();
|
||||
}
|
||||
|
||||
public static AliasID getAliasID(AliasIDType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
return new BroadcastChannel();
|
||||
case ESN:
|
||||
return new Esn();
|
||||
case FLEETSYNC:
|
||||
return new FleetsyncID();
|
||||
case LTR_NET_UID:
|
||||
return new UniqueID();
|
||||
case LOJACK:
|
||||
return new LoJackFunctionAndID();
|
||||
case MDC1200:
|
||||
return new MDC1200ID();
|
||||
case MIN:
|
||||
return new Min();
|
||||
case MPT1327:
|
||||
return new MPT1327ID();
|
||||
case NON_RECORDABLE:
|
||||
return new NonRecordable();
|
||||
case PRIORITY:
|
||||
return new Priority();
|
||||
case RECORD:
|
||||
return new Record();
|
||||
case TALKGROUP:
|
||||
return new Talkgroup();
|
||||
case TALKGROUP_RANGE:
|
||||
return new TalkgroupRange();
|
||||
case SITE:
|
||||
return new SiteID();
|
||||
case STATUS:
|
||||
return new StatusID();
|
||||
case LEGACY_TALKGROUP:
|
||||
return new LegacyTalkgroupID();
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized Alias ID type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public static AliasAction getAliasAction(AliasActionType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case BEEP:
|
||||
return new BeepAction();
|
||||
case CLIP:
|
||||
return new ClipAction();
|
||||
case SCRIPT:
|
||||
return new ScriptAction();
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized Alias Action type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public static Editor<AliasID> getEditor( AliasID aliasID, BroadcastModel broadcastModel )
|
||||
{
|
||||
if( aliasID != null )
|
||||
{
|
||||
switch( aliasID.getType() )
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
return new BroadcastChannelEditor(aliasID, broadcastModel);
|
||||
case ESN:
|
||||
return new ESNEditor( aliasID );
|
||||
case FLEETSYNC:
|
||||
return new FleetsyncIDEditor( aliasID );
|
||||
case LTR_NET_UID:
|
||||
return new UniqueIDEditor( aliasID );
|
||||
case LOJACK:
|
||||
return new LoJackIDEditor( aliasID );
|
||||
case MDC1200:
|
||||
return new MDC1200IDEditor( aliasID );
|
||||
case MIN:
|
||||
return new MINEditor( aliasID );
|
||||
case MPT1327:
|
||||
return new MPT1327IDEditor( aliasID );
|
||||
case NON_RECORDABLE:
|
||||
return new NonRecordableEditor( aliasID );
|
||||
case PRIORITY:
|
||||
return new PriorityEditor( aliasID );
|
||||
case SITE:
|
||||
return new SiteIDEditor( aliasID );
|
||||
case STATUS:
|
||||
return new StatusIDEditor( aliasID );
|
||||
case TALKGROUP:
|
||||
return new TalkgroupIDEditor( aliasID );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyEditor<AliasID>();
|
||||
}
|
||||
|
||||
public static Editor<AliasAction> getEditor( AliasAction aliasAction )
|
||||
{
|
||||
if( aliasAction != null )
|
||||
{
|
||||
switch( aliasAction.getType() )
|
||||
{
|
||||
case BEEP:
|
||||
return new BeepActionEditor( aliasAction );
|
||||
case CLIP:
|
||||
return new ClipActionEditor( aliasAction );
|
||||
case SCRIPT:
|
||||
return new ScriptActionEditor( aliasAction );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyEditor<AliasAction>();
|
||||
}
|
||||
|
||||
public static AliasID getAliasID( AliasIDType type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case BROADCAST_CHANNEL:
|
||||
return new BroadcastChannel();
|
||||
case ESN:
|
||||
return new Esn();
|
||||
case FLEETSYNC:
|
||||
return new FleetsyncID();
|
||||
case LTR_NET_UID:
|
||||
return new UniqueID();
|
||||
case LOJACK:
|
||||
return new LoJackFunctionAndID();
|
||||
case MDC1200:
|
||||
return new MDC1200ID();
|
||||
case MIN:
|
||||
return new Min();
|
||||
case MPT1327:
|
||||
return new MPT1327ID();
|
||||
case NON_RECORDABLE:
|
||||
return new NonRecordable();
|
||||
case PRIORITY:
|
||||
return new Priority();
|
||||
case SITE:
|
||||
return new SiteID();
|
||||
case STATUS:
|
||||
return new StatusID();
|
||||
case TALKGROUP:
|
||||
return new TalkgroupID();
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized Alias ID type: " + type );
|
||||
}
|
||||
}
|
||||
|
||||
public static AliasAction getAliasAction( AliasActionType type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case BEEP:
|
||||
return new BeepAction();
|
||||
case CLIP:
|
||||
return new ClipAction();
|
||||
case SCRIPT:
|
||||
return new ScriptAction();
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized Alias Action type: " + type );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,24 +15,27 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.WildcardID;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.esn.Esn;
|
||||
import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
|
||||
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.module.decode.lj1200.LJ1200Message;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.esn.ESNIdentifier;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroup;
|
||||
import io.github.dsheirer.identifier.patch.PatchGroupIdentifier;
|
||||
import io.github.dsheirer.identifier.status.UnitStatusIdentifier;
|
||||
import io.github.dsheirer.identifier.status.UserStatusIdentifier;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -39,34 +43,18 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
|
||||
public static final String WILDCARD = "*";
|
||||
public static final String REGEX_WILDCARD = ".";
|
||||
|
||||
private Map<String,Alias> mESN = new HashMap<>();
|
||||
private Map<String,Alias> mFleetsync = new HashMap<>();
|
||||
private Map<LoJackFunctionAndID,Alias> mLoJack = new HashMap<>();
|
||||
private Map<String,Alias> mMDC1200 = new HashMap<>();
|
||||
private Map<String,Alias> mMobileID = new HashMap<>();
|
||||
private Map<String,Alias> mMPT1327 = new HashMap<>();
|
||||
private Map<String,Alias> mSiteID = new HashMap<>();
|
||||
private Map<Integer,Alias> mStatus = new HashMap<>();
|
||||
private Map<String,Alias> mTalkgroup = new HashMap<>();
|
||||
private Map<Integer,Alias> mUniqueID = new HashMap<>();
|
||||
|
||||
private List<WildcardID> mESNWildcards = new ArrayList<>();
|
||||
private List<WildcardID> mMobileIDWildcards = new ArrayList<>();
|
||||
private List<WildcardID> mFleetsyncWildcards = new ArrayList<>();
|
||||
private List<WildcardID> mMDC1200Wildcards = new ArrayList<>();
|
||||
private List<WildcardID> mMPT1327Wildcards = new ArrayList<>();
|
||||
private List<WildcardID> mSiteWildcards = new ArrayList<>();
|
||||
private List<WildcardID> mTalkgroupWildcards = new ArrayList<>();
|
||||
|
||||
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new HashMap<>();
|
||||
private Map<String,Alias> mESNMap = new HashMap<>();
|
||||
private Map<Integer,Alias> mStatusMap = new HashMap<>();
|
||||
private boolean mHasAliasActions = false;
|
||||
private String mName;
|
||||
|
||||
/**
|
||||
@@ -92,6 +80,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
addAliasID(aliasID, alias);
|
||||
}
|
||||
}
|
||||
|
||||
if(alias.hasActions())
|
||||
{
|
||||
mHasAliasActions = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,120 +98,42 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
switch(id.getType())
|
||||
{
|
||||
case TALKGROUP:
|
||||
Talkgroup talkgroup = (Talkgroup)id;
|
||||
|
||||
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
||||
|
||||
if(talkgroupAliasList == null)
|
||||
{
|
||||
talkgroupAliasList = new TalkgroupAliasList();
|
||||
mTalkgroupProtocolMap.put(talkgroup.getProtocol(), talkgroupAliasList);
|
||||
}
|
||||
|
||||
talkgroupAliasList.add(talkgroup, alias);
|
||||
break;
|
||||
case TALKGROUP_RANGE:
|
||||
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
||||
|
||||
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
||||
|
||||
if(talkgroupRangeAliasList == null)
|
||||
{
|
||||
talkgroupRangeAliasList = new TalkgroupAliasList();
|
||||
mTalkgroupProtocolMap.put(talkgroupRange.getProtocol(), talkgroupRangeAliasList);
|
||||
}
|
||||
|
||||
talkgroupRangeAliasList.add(talkgroupRange, alias);
|
||||
break;
|
||||
case ESN:
|
||||
String esn = ((Esn) id).getEsn();
|
||||
|
||||
if(esn != null)
|
||||
if(esn != null && !esn.isEmpty())
|
||||
{
|
||||
if(esn.contains(WILDCARD))
|
||||
{
|
||||
mESNWildcards.add(new WildcardID(esn));
|
||||
Collections.sort(mESNWildcards);
|
||||
}
|
||||
|
||||
mESN.put(esn, alias);
|
||||
}
|
||||
break;
|
||||
case FLEETSYNC:
|
||||
String fleetsync = ((FleetsyncID) id).getIdent();
|
||||
|
||||
if(fleetsync != null)
|
||||
{
|
||||
if(fleetsync.contains(WILDCARD))
|
||||
{
|
||||
mFleetsyncWildcards.add(new WildcardID(fleetsync));
|
||||
Collections.sort(mFleetsyncWildcards);
|
||||
}
|
||||
|
||||
mFleetsync.put(fleetsync, alias);
|
||||
}
|
||||
break;
|
||||
case LOJACK:
|
||||
mLoJack.put((LoJackFunctionAndID) id, alias);
|
||||
break;
|
||||
case MDC1200:
|
||||
String mdc = ((MDC1200ID) id).getIdent();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
if(mdc.contains(WILDCARD))
|
||||
{
|
||||
mMDC1200Wildcards.add(new WildcardID(mdc));
|
||||
Collections.sort(mMDC1200Wildcards);
|
||||
}
|
||||
|
||||
mMDC1200.put(mdc, alias);
|
||||
}
|
||||
break;
|
||||
case MPT1327:
|
||||
String mpt = ((MPT1327ID) id).getIdent();
|
||||
|
||||
if(mpt != null)
|
||||
{
|
||||
if(mpt.contains(WILDCARD))
|
||||
{
|
||||
mMPT1327Wildcards.add(new WildcardID(mpt));
|
||||
Collections.sort(mMPT1327Wildcards);
|
||||
}
|
||||
|
||||
mMPT1327.put(mpt, alias);
|
||||
}
|
||||
break;
|
||||
case MIN:
|
||||
String min = ((Min) id).getMin();
|
||||
|
||||
if(min != null)
|
||||
{
|
||||
if(min.contains(WILDCARD))
|
||||
{
|
||||
mMobileIDWildcards.add(new WildcardID(min));
|
||||
Collections.sort(mMobileIDWildcards);
|
||||
}
|
||||
|
||||
mMobileID.put(min, alias);
|
||||
}
|
||||
break;
|
||||
case LTR_NET_UID:
|
||||
mUniqueID.put(((UniqueID) id).getUid(), alias);
|
||||
break;
|
||||
case SITE:
|
||||
String siteID = ((SiteID) id).getSite();
|
||||
|
||||
if(siteID != null)
|
||||
{
|
||||
if(siteID.contains(WILDCARD))
|
||||
{
|
||||
mSiteWildcards.add(new WildcardID(siteID));
|
||||
Collections.sort(mSiteWildcards);
|
||||
}
|
||||
|
||||
mSiteID.put(siteID, alias);
|
||||
mESNMap.put(esn.toLowerCase(), alias);
|
||||
}
|
||||
break;
|
||||
case STATUS:
|
||||
mStatus.put(((StatusID) id).getStatus(), alias);
|
||||
break;
|
||||
case TALKGROUP:
|
||||
String tgid = ((TalkgroupID) id).getTalkgroup();
|
||||
|
||||
if(tgid != null)
|
||||
{
|
||||
if(tgid.contains(WILDCARD))
|
||||
{
|
||||
mTalkgroupWildcards.add(new WildcardID(tgid));
|
||||
Collections.sort(mTalkgroupWildcards);
|
||||
}
|
||||
|
||||
mTalkgroup.put(tgid, alias);
|
||||
}
|
||||
break;
|
||||
case BROADCAST_CHANNEL:
|
||||
case NON_RECORDABLE:
|
||||
case PRIORITY:
|
||||
//We don't maintain lookups for these items
|
||||
break;
|
||||
default:
|
||||
mLog.warn("Unrecognized Alias ID Type:" + id.getType().name() + " - can't ADD to lookup table");
|
||||
mStatusMap.put(((StatusID) id).getStatus(), alias);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -234,203 +149,13 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
public void removeAlias(Alias alias)
|
||||
{
|
||||
if(alias != null)
|
||||
for(TalkgroupAliasList talkgroupAliasList: mTalkgroupProtocolMap.values())
|
||||
{
|
||||
for(AliasID aliasID : alias.getId())
|
||||
{
|
||||
removeAliasID(aliasID, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeWildcard(String value, List<WildcardID> wildcards)
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
for(WildcardID wildcardID : wildcards)
|
||||
{
|
||||
if(wildcardID.value().equals(value))
|
||||
{
|
||||
wildcards.remove(wildcardID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the alias and alias identifier from internal mappings.
|
||||
*/
|
||||
private void removeAliasID(AliasID id, Alias alias)
|
||||
{
|
||||
if(id.isValid())
|
||||
{
|
||||
switch(id.getType())
|
||||
{
|
||||
case ESN:
|
||||
String esn = ((Esn) id).getEsn();
|
||||
|
||||
if(esn != null)
|
||||
{
|
||||
if(esn.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(esn, mESNWildcards);
|
||||
}
|
||||
}
|
||||
|
||||
mESN.remove(esn);
|
||||
break;
|
||||
case FLEETSYNC:
|
||||
String fleetsync = ((FleetsyncID) id).getIdent();
|
||||
|
||||
if(fleetsync != null)
|
||||
{
|
||||
if(fleetsync.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(fleetsync, mFleetsyncWildcards);
|
||||
}
|
||||
|
||||
mFleetsync.remove(fleetsync);
|
||||
}
|
||||
break;
|
||||
case LOJACK:
|
||||
mLoJack.remove((LoJackFunctionAndID) id);
|
||||
break;
|
||||
case MDC1200:
|
||||
String mdc = ((MDC1200ID) id).getIdent();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
if(mdc.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(mdc, mMDC1200Wildcards);
|
||||
}
|
||||
|
||||
mMDC1200.remove(mdc);
|
||||
}
|
||||
break;
|
||||
case MPT1327:
|
||||
String mpt = ((MPT1327ID) id).getIdent();
|
||||
|
||||
if(mpt != null)
|
||||
{
|
||||
if(mpt.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(mpt, mMPT1327Wildcards);
|
||||
}
|
||||
|
||||
mMPT1327.remove(mpt);
|
||||
}
|
||||
break;
|
||||
case MIN:
|
||||
String min = ((Min) id).getMin();
|
||||
|
||||
if(min != null)
|
||||
{
|
||||
if(min.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(min, mMobileIDWildcards);
|
||||
}
|
||||
|
||||
mMobileID.remove(min);
|
||||
}
|
||||
break;
|
||||
case LTR_NET_UID:
|
||||
mUniqueID.remove(((UniqueID) id).getUid());
|
||||
break;
|
||||
case SITE:
|
||||
mSiteID.remove(((SiteID) id).getSite());
|
||||
break;
|
||||
case STATUS:
|
||||
mStatus.remove(((StatusID) id).getStatus());
|
||||
break;
|
||||
case TALKGROUP:
|
||||
String tgid = ((TalkgroupID) id).getTalkgroup();
|
||||
|
||||
if(tgid != null)
|
||||
{
|
||||
if(tgid.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(tgid, mTalkgroupWildcards);
|
||||
}
|
||||
|
||||
mTalkgroup.remove(tgid);
|
||||
}
|
||||
break;
|
||||
case NON_RECORDABLE:
|
||||
case PRIORITY:
|
||||
case BROADCAST_CHANNEL:
|
||||
//We don't maintain lookups for these items
|
||||
break;
|
||||
default:
|
||||
mLog.warn("Unrecognized Alias ID Type:" + id.getType().name() + " - can't REMOVE from lookup table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first matching regex wildcard from the list of wildcards that matches the
|
||||
* identifier.
|
||||
*
|
||||
* @param id to match
|
||||
* @param wildcards to match against
|
||||
* @return matching wildcard ID or null
|
||||
*/
|
||||
private String getWildcardMatch(String id, List<WildcardID> wildcards)
|
||||
{
|
||||
if(id != null)
|
||||
{
|
||||
for(WildcardID wildcard : wildcards)
|
||||
{
|
||||
if(wildcard.matches(id))
|
||||
{
|
||||
return wildcard.value();
|
||||
}
|
||||
}
|
||||
talkgroupAliasList.remove(alias);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by site ID
|
||||
*/
|
||||
public Alias getSiteID(String siteID)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(siteID != null)
|
||||
{
|
||||
alias = mSiteID.get(siteID);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(siteID, mSiteWildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mSiteID.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by status ID
|
||||
*/
|
||||
public Alias getStatus(int status)
|
||||
{
|
||||
return mStatus.get(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by Unique ID (UID)
|
||||
*/
|
||||
public Alias getUniqueID(int uniqueID)
|
||||
{
|
||||
return mUniqueID.get(uniqueID);
|
||||
remove(alias, mStatusMap);
|
||||
remove(alias, mESNMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,178 +167,12 @@ public class AliasList implements Listener<AliasEvent>
|
||||
|
||||
if(esn != null)
|
||||
{
|
||||
alias = mESN.get(esn);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(esn, mESNWildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mESN.get(wildcard);
|
||||
}
|
||||
}
|
||||
alias = mESNMap.get(esn);
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by fleetsync ID
|
||||
*/
|
||||
public Alias getFleetsyncAlias(String ident)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mFleetsync.get(ident);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mFleetsyncWildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mFleetsync.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by lojack function and ID
|
||||
*/
|
||||
public Alias getLoJackAlias(LJ1200Message.Function function, String id)
|
||||
{
|
||||
if(id != null)
|
||||
{
|
||||
for(LoJackFunctionAndID lojack : mLoJack.keySet())
|
||||
{
|
||||
if(lojack.matches(function, id))
|
||||
{
|
||||
return mLoJack.get(lojack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by MDC1200 ID
|
||||
*/
|
||||
public Alias getMDC1200Alias(String ident)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMDC1200.get(ident);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMDC1200Wildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMDC1200.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by MPT1327 Ident
|
||||
*/
|
||||
public Alias getMPT1327Alias(String ident)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMPT1327.get(ident);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMPT1327Wildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMPT1327.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by Mobile ID Number (MIN)
|
||||
*/
|
||||
public Alias getMobileIDNumberAlias(String ident)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMobileID.get(ident);
|
||||
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMobileIDWildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMobileID.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by talkgroup
|
||||
*
|
||||
* @param tgid to use when searching for an alias
|
||||
* @param includeWildcards true if you want to additionally search for a matching alias that contains wildcard(s)
|
||||
* when there is not a direct match to the TGID.
|
||||
*/
|
||||
public Alias getTalkgroupAlias(String tgid, boolean includeWildcards)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if(tgid != null)
|
||||
{
|
||||
alias = mTalkgroup.get(tgid);
|
||||
|
||||
if(alias == null && includeWildcards)
|
||||
{
|
||||
String wildcard = getWildcardMatch(tgid, mTalkgroupWildcards);
|
||||
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mTalkgroup.get(wildcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup alias by talkgroup. Defaults to matching to wildcard talkgroups.
|
||||
*/
|
||||
public Alias getTalkgroupAlias(String tgid)
|
||||
{
|
||||
return getTalkgroupAlias(tgid, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias list name
|
||||
*/
|
||||
@@ -660,6 +219,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
case CHANGE:
|
||||
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
{
|
||||
removeAlias(alias);
|
||||
addAlias(alias);
|
||||
}
|
||||
break;
|
||||
@@ -674,4 +234,323 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an optional alias that is associated with the identifier
|
||||
* @param identifier to alias
|
||||
* @return list of alias or empty list
|
||||
*/
|
||||
public List<Alias> getAliases(Identifier identifier)
|
||||
{
|
||||
if(identifier != null)
|
||||
{
|
||||
switch(identifier.getForm())
|
||||
{
|
||||
case TALKGROUP:
|
||||
TalkgroupIdentifier talkgroup = (TalkgroupIdentifier)identifier;
|
||||
|
||||
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(identifier.getProtocol());
|
||||
|
||||
if(talkgroupAliasList != null)
|
||||
{
|
||||
Alias alias = talkgroupAliasList.getAlias(talkgroup);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PATCH_GROUP:
|
||||
PatchGroupIdentifier patchGroupIdentifier = (PatchGroupIdentifier)identifier;
|
||||
PatchGroup patchGroup = patchGroupIdentifier.getValue();
|
||||
|
||||
TalkgroupAliasList patchGroupAliasList = mTalkgroupProtocolMap.get(patchGroupIdentifier.getProtocol());
|
||||
|
||||
if(patchGroupAliasList != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
|
||||
Alias alias = patchGroupAliasList.getAlias(patchGroup.getPatchGroup());
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
aliases.add(alias);
|
||||
}
|
||||
|
||||
for(TalkgroupIdentifier patchedGroup: patchGroup.getPatchedGroupIdentifiers())
|
||||
{
|
||||
Alias patchedAlias = patchGroupAliasList.getAlias(patchedGroup);
|
||||
|
||||
if(patchedAlias != null && !aliases.contains(patchedAlias))
|
||||
{
|
||||
aliases.add(patchedAlias);
|
||||
}
|
||||
}
|
||||
|
||||
return aliases;
|
||||
}
|
||||
break;
|
||||
case ESN:
|
||||
if(identifier instanceof ESNIdentifier)
|
||||
{
|
||||
Alias alias = getESNAlias(((ESNIdentifier)identifier).getValue());
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UNIT_STATUS:
|
||||
if(identifier instanceof UnitStatusIdentifier)
|
||||
{
|
||||
int status = ((UnitStatusIdentifier)identifier).getValue();
|
||||
|
||||
Alias alias = mStatusMap.get(status);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USER_STATUS:
|
||||
if(identifier instanceof UserStatusIdentifier)
|
||||
{
|
||||
int status = ((UserStatusIdentifier)identifier).getValue();
|
||||
|
||||
Alias alias = mStatusMap.get(status);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
aliases.add(alias);
|
||||
return aliases;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if any of the identifiers contain a broadcast channel for streaming of audio.
|
||||
* @param identifierCollection to inspect
|
||||
* @return true if the identifier collection is designated for streaming to one or more channels.
|
||||
*/
|
||||
public boolean isStreamable(IdentifierCollection identifierCollection)
|
||||
{
|
||||
for(Identifier identifier: identifierCollection.getIdentifiers())
|
||||
{
|
||||
List<Alias> aliases = getAliases(identifier);
|
||||
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
if(alias != null && alias.isStreamable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if any of the identifiers have been identified for recording.
|
||||
* @param identifierCollection to inspect
|
||||
* @return true if recordable.
|
||||
*/
|
||||
public boolean isRecordable(IdentifierCollection identifierCollection)
|
||||
{
|
||||
for(Identifier identifier: identifierCollection.getIdentifiers())
|
||||
{
|
||||
List<Alias> aliases = getAliases(identifier);
|
||||
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
if(alias != null && alias.isRecordable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if any of the aliases in this list have an associated alias action
|
||||
*/
|
||||
public boolean hasAliasActions()
|
||||
{
|
||||
return mHasAliasActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowest audio playback priority specified by aliases for identifiers in the
|
||||
* identifier collection.
|
||||
*
|
||||
* @param identifierCollection to inspect for audio priority
|
||||
* @return audio playback priority
|
||||
*/
|
||||
public int getAudioPlaybackPriority(IdentifierCollection identifierCollection)
|
||||
{
|
||||
int priority = Priority.DEFAULT_PRIORITY;
|
||||
|
||||
for(Identifier identifier: identifierCollection.getIdentifiers())
|
||||
{
|
||||
List<Alias> aliases = getAliases(identifier);
|
||||
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
if(alias != null && alias.getPlaybackPriority() < priority)
|
||||
{
|
||||
priority = alias.getPlaybackPriority();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of streaming broadcast channels specified for any of the identifiers in the collection.
|
||||
*
|
||||
* @return list of broadcast channels or an empty list
|
||||
*/
|
||||
public List<BroadcastChannel> getBroadcastChannels(IdentifierCollection identifierCollection)
|
||||
{
|
||||
List<BroadcastChannel> channels = new ArrayList<>();
|
||||
|
||||
for(Identifier identifier: identifierCollection.getIdentifiers())
|
||||
{
|
||||
List<Alias> aliases = getAliases(identifier);
|
||||
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
if(alias != null && alias.isStreamable())
|
||||
{
|
||||
for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels())
|
||||
{
|
||||
if(!channels.contains(broadcastChannel))
|
||||
{
|
||||
channels.add(broadcastChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the alias (as a value) from the specified map
|
||||
*/
|
||||
public static void remove(Alias alias, Map map)
|
||||
{
|
||||
Iterator<Map.Entry> it = map.entrySet().iterator();
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
if(it.next().getValue().equals(alias))
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listing of talkgroups and ranges for a specific protocol
|
||||
*/
|
||||
public class TalkgroupAliasList
|
||||
{
|
||||
private Map<Integer,Alias> mTalkgroupAliasMap = new TreeMap<>();
|
||||
private Map<TalkgroupRange, Alias> mTalkgroupRangeAliasMap = new HashMap<>();
|
||||
|
||||
public TalkgroupAliasList()
|
||||
{
|
||||
}
|
||||
|
||||
public Alias getAlias(TalkgroupIdentifier identifier)
|
||||
{
|
||||
int value = identifier.getValue();
|
||||
|
||||
if(mTalkgroupAliasMap.containsKey(value))
|
||||
{
|
||||
return mTalkgroupAliasMap.get(value);
|
||||
}
|
||||
|
||||
for(TalkgroupRange talkgroupRange: mTalkgroupRangeAliasMap.keySet())
|
||||
{
|
||||
if(talkgroupRange.contains(value))
|
||||
{
|
||||
return mTalkgroupRangeAliasMap.get(talkgroupRange);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void add(Talkgroup talkgroup, Alias alias)
|
||||
{
|
||||
//Detect talkgroup collisions
|
||||
if(mTalkgroupAliasMap.containsKey(talkgroup.getValue()))
|
||||
{
|
||||
Alias existing = mTalkgroupAliasMap.get(talkgroup.getValue());
|
||||
|
||||
mLog.warn("Alias [" + alias.getName() + "] talkgroup [" + talkgroup.getValue() +
|
||||
"] has the same talkgroup value as alias [" + existing.getName() +
|
||||
"] - alias [" + alias.getName() + "] will be used for alias list [" + getName() + "]");
|
||||
}
|
||||
|
||||
mTalkgroupAliasMap.put(talkgroup.getValue(), alias);
|
||||
}
|
||||
|
||||
public void add(TalkgroupRange talkgroupRange, Alias alias)
|
||||
{
|
||||
//Log warning if the new talkgroup range overlaps with any existing ranges
|
||||
for(Map.Entry<TalkgroupRange,Alias> entry: mTalkgroupRangeAliasMap.entrySet())
|
||||
{
|
||||
if(talkgroupRange.overlaps(entry.getKey()))
|
||||
{
|
||||
mLog.warn("Alias [" + alias.getName() + "] with talkgroup range [" + talkgroupRange.toString() +
|
||||
"] overlaps with alias [" + entry.getValue().getName() +
|
||||
"] with talkgroup range [" + entry.getKey().toString() + "] for alias list [" + getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
mTalkgroupRangeAliasMap.put(talkgroupRange, alias);
|
||||
}
|
||||
|
||||
public void remove(Talkgroup talkgroup)
|
||||
{
|
||||
mTalkgroupAliasMap.remove(talkgroup.getValue());
|
||||
}
|
||||
|
||||
public void remove(TalkgroupRange talkgroupRange)
|
||||
{
|
||||
mTalkgroupRangeAliasMap.remove(talkgroupRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the alias from all internal maps
|
||||
*/
|
||||
public void remove(Alias alias)
|
||||
{
|
||||
AliasList.remove(alias, mTalkgroupAliasMap);
|
||||
AliasList.remove(alias, mTalkgroupRangeAliasMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
@@ -30,7 +34,9 @@ import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Alias Model
|
||||
* Alias Model contains all aliases and is responsible for creation and management of alias lists. Alias lists are a
|
||||
* set of aliases that all share a common alias list name and can be attached to a decoding channel for aliasing
|
||||
* identifiers produced by channel decoder(s).
|
||||
*/
|
||||
public class AliasModel extends AbstractTableModel
|
||||
{
|
||||
@@ -68,31 +74,69 @@ public class AliasModel extends AbstractTableModel
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an optional alias list associated with the identifier collection
|
||||
*
|
||||
* @return alias list or null
|
||||
*/
|
||||
public AliasList getAliasList(IdentifierCollection identifierCollection)
|
||||
{
|
||||
if(identifierCollection != null)
|
||||
{
|
||||
return getAliasList(identifierCollection.getAliasListConfiguration());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an alias list specified by the alias list configuration identifier
|
||||
*
|
||||
* @param configurationIdentifier containing the name of an alias list
|
||||
* @return alias list or null.
|
||||
*/
|
||||
public AliasList getAliasList(AliasListConfigurationIdentifier configurationIdentifier)
|
||||
{
|
||||
if(configurationIdentifier != null && configurationIdentifier.isValid())
|
||||
{
|
||||
return getAliasList(configurationIdentifier.getValue());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new alias list containing all aliases that match the alias name, or returns a previously created and
|
||||
* cached alias list. Returned alias list is automatically registered as a listener to this model so that any
|
||||
* updates to the list by the user will automatically be reflected in constructed alias lists.
|
||||
*/
|
||||
public AliasList getAliasList(String name)
|
||||
{
|
||||
if(name != null && mAliasListMap.containsKey(name))
|
||||
if(name == null || name.isEmpty())
|
||||
{
|
||||
return new AliasList(name);
|
||||
}
|
||||
|
||||
if(mAliasListMap.containsKey(name))
|
||||
{
|
||||
return mAliasListMap.get(name);
|
||||
}
|
||||
|
||||
AliasList aliasList = new AliasList(name);
|
||||
|
||||
if(name != null)
|
||||
for(Alias alias : mAliases)
|
||||
{
|
||||
for(Alias alias : mAliases)
|
||||
if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
|
||||
{
|
||||
if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
|
||||
{
|
||||
aliasList.addAlias(alias);
|
||||
}
|
||||
aliasList.addAlias(alias);
|
||||
}
|
||||
|
||||
mAliasListMap.put(name, aliasList);
|
||||
|
||||
//Register the new alias list to receive updates from this model
|
||||
addListener(aliasList);
|
||||
}
|
||||
|
||||
mAliasListMap.put(name, aliasList);
|
||||
|
||||
//Register the new alias list to receive updates from this model
|
||||
addListener(aliasList);
|
||||
|
||||
return aliasList;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,379 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias;
|
||||
|
||||
import io.github.dsheirer.alias.action.AliasAction;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class PatchGroupAlias extends Alias
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(PatchGroupAlias.class);
|
||||
|
||||
private Alias mPatchGroupAlias;
|
||||
private List<Alias> mPatchedAliases = new ArrayList<>();
|
||||
private List<String> mPatchedTalkgroupIDs = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Patch group alias is a single alias for a group of aliases that are temporarily patched together. This will
|
||||
* normally be used for patched talkgroups, but could be used with any type of alias identifiers that can be
|
||||
* temporarily joined to form a patch group.
|
||||
*
|
||||
* Alias properties such as recordable, streamable and call priority are an aggregation from the set of patched
|
||||
* aliases contained in this patch group alias and the patch group ID alias and where applicable, return the highest
|
||||
* value/priority from the group of patched aliases.
|
||||
*/
|
||||
public PatchGroupAlias()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor()
|
||||
{
|
||||
if(mPatchGroupAlias != null)
|
||||
{
|
||||
return mPatchGroupAlias.getColor();
|
||||
}
|
||||
|
||||
return super.getColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alias for this patch group ID
|
||||
*/
|
||||
public void setPatchGroupAlias(Alias alias)
|
||||
{
|
||||
mPatchGroupAlias = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for this patch group
|
||||
*/
|
||||
public Alias getPatchGroupAlias()
|
||||
{
|
||||
return mPatchGroupAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this patch group has an alias
|
||||
*/
|
||||
public boolean hasPatchGroupAlias()
|
||||
{
|
||||
return mPatchGroupAlias != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of patched aliases contained in this patch group
|
||||
*/
|
||||
public List<Alias> getPatchedAliases()
|
||||
{
|
||||
return mPatchedAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes/clears all patched aliases from this patch alias group
|
||||
*/
|
||||
public void clearPatchedAliases()
|
||||
{
|
||||
mPatchedAliases.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the patched alias to this patch alias group
|
||||
*/
|
||||
public void addPatchedAlias(Alias alias)
|
||||
{
|
||||
if(alias == PatchGroupAlias.this)
|
||||
{
|
||||
throw new IllegalArgumentException("Can't add patch group alias to itself - would create an infinite loop");
|
||||
}
|
||||
|
||||
mPatchedAliases.add(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the patched alias from this patch alias group
|
||||
*/
|
||||
public void removePatchedAlias(Alias alias)
|
||||
{
|
||||
mPatchedAliases.remove(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of patched talkgroup IDs for this patch group
|
||||
*/
|
||||
public void setPatchedTalkgroupIDs(List<String> talkgroupIDs)
|
||||
{
|
||||
mPatchedTalkgroupIDs = talkgroupIDs;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of patched talkgroup IDs for this patch group
|
||||
*/
|
||||
public List<String> getPatchedTalkgroupIDs()
|
||||
{
|
||||
return mPatchedTalkgroupIDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
if(hasPatchGroupAlias())
|
||||
{
|
||||
return getPatchGroupAlias().getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(AliasID id: getId())
|
||||
{
|
||||
if(id.getType() == AliasIDType.TALKGROUP)
|
||||
{
|
||||
return "PATCH:" + ((TalkgroupID)id).getTalkgroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "PATCH:****";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AliasAction> getAction()
|
||||
{
|
||||
List<AliasAction> aliasActions = new ArrayList<>();
|
||||
|
||||
if(hasPatchGroupAlias())
|
||||
{
|
||||
aliasActions.addAll(getPatchGroupAlias().getAction());
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias))
|
||||
{
|
||||
for(AliasAction action: alias.getAction())
|
||||
{
|
||||
if(!aliasActions.contains(action))
|
||||
{
|
||||
aliasActions.add(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aliasActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActions()
|
||||
{
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.hasActions())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasPatchGroupAlias() && getPatchGroupAlias().hasActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest listenable audio priority defined among the aliases in the group, or returns 'Do Not Monitor'
|
||||
* if that is the only priority defined. Otherwise, returns default (100) priority.
|
||||
*/
|
||||
@Override
|
||||
public int getCallPriority()
|
||||
{
|
||||
boolean hasDoNotMonitor = false;
|
||||
|
||||
int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY + 1);
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority() && alias.getCallPriority() < highestPriority)
|
||||
{
|
||||
if(alias.getCallPriority() == Priority.DO_NOT_MONITOR)
|
||||
{
|
||||
hasDoNotMonitor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
highestPriority = alias.getCallPriority();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(highestPriority <= Priority.DEFAULT_PRIORITY)
|
||||
{
|
||||
return highestPriority;
|
||||
}
|
||||
else if(hasDoNotMonitor)
|
||||
{
|
||||
return Priority.DO_NOT_MONITOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Priority.DEFAULT_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCallPriority()
|
||||
{
|
||||
if(hasPatchGroupAlias() && getPatchGroupAlias().hasCallPriority())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecordable()
|
||||
{
|
||||
if(hasPatchGroupAlias() && getPatchGroupAlias().isRecordable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.isRecordable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStreamable()
|
||||
{
|
||||
if(hasPatchGroupAlias() && getPatchGroupAlias().isStreamable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.isStreamable())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<BroadcastChannel> getBroadcastChannels()
|
||||
{
|
||||
Set<BroadcastChannel> broadcastChannels = new TreeSet<>();
|
||||
|
||||
if(hasPatchGroupAlias())
|
||||
{
|
||||
broadcastChannels.addAll(getPatchGroupAlias().getBroadcastChannels());
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias))
|
||||
{
|
||||
broadcastChannels.addAll(alias.getBroadcastChannels());
|
||||
}
|
||||
}
|
||||
|
||||
return broadcastChannels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBroadcastChannel(String channel)
|
||||
{
|
||||
if(hasPatchGroupAlias() && getPatchGroupAlias().hasBroadcastChannel(channel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for(Alias alias: mPatchedAliases)
|
||||
{
|
||||
if(!(alias instanceof PatchGroupAlias) && alias.hasBroadcastChannel(channel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Alias a1 = new Alias("Alias 1");
|
||||
a1.addAliasID(new BroadcastChannel("Channel 1"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 2"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 3"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 4"));
|
||||
|
||||
Alias a2 = new Alias("Alias 1");
|
||||
a1.addAliasID(new BroadcastChannel("Channel 1"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 2"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 3"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 4"));
|
||||
|
||||
Alias a3 = new Alias("Alias 1");
|
||||
a1.addAliasID(new BroadcastChannel("Channel 1"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 2"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 3"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 4"));
|
||||
|
||||
Alias a4 = new Alias("Alias 1");
|
||||
a1.addAliasID(new BroadcastChannel("Channel 1"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 2"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 3"));
|
||||
a1.addAliasID(new BroadcastChannel("Channel 4"));
|
||||
|
||||
PatchGroupAlias pga = new PatchGroupAlias();
|
||||
pga.setPatchGroupAlias(a1);
|
||||
pga.addPatchedAlias(a2);
|
||||
pga.addPatchedAlias(a3);
|
||||
pga.addPatchedAlias(a4);
|
||||
|
||||
Set<BroadcastChannel> bc = pga.getBroadcastChannels();
|
||||
|
||||
mLog.debug("Channels:" + bc);
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,7 @@ import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.action.beep.BeepAction;
|
||||
import io.github.dsheirer.alias.action.clip.ClipAction;
|
||||
import io.github.dsheirer.alias.action.script.ScriptAction;
|
||||
import io.github.dsheirer.message.Message;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
|
||||
/**
|
||||
* Alias action defines an action to execute when an alias is detected active.
|
||||
@@ -56,7 +54,7 @@ public abstract class AliasAction
|
||||
* action attached. The alias argument is the parent alias containing the
|
||||
* alias action.
|
||||
*/
|
||||
public abstract void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message);
|
||||
public abstract void execute(Alias alias, IMessage message);
|
||||
|
||||
/**
|
||||
* Dismiss a persistent alias action
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -14,56 +15,94 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.action;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.IMessageListener;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Manages all alias action events. Each received message is interrogated for
|
||||
* any alias entries and then each alias is interrogated for any alias actions.
|
||||
* Manages all alias action events. Each received message is interrogated for any identifiers that may be aliasable
|
||||
* and have associated alias actions.
|
||||
*
|
||||
* Each alias action is executed and provided a copy of the source message so
|
||||
* that the contents of the message can be used as part of the action.
|
||||
* Each alias action is executed and provided a copy of the source message so that the contents of the message can be
|
||||
* used as part of the action.
|
||||
*/
|
||||
public class AliasActionManager implements Listener<Message>
|
||||
public class AliasActionManager extends Module implements IMessageListener, Listener<IMessage>
|
||||
{
|
||||
public AliasActionManager()
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AliasActionManager.class);
|
||||
private AliasList mAliasList;
|
||||
|
||||
public AliasActionManager(AliasList aliasList)
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
public void receive(IMessage message)
|
||||
{
|
||||
if(message.isValid())
|
||||
if(mAliasList != null && message.isValid())
|
||||
{
|
||||
List<Alias> aliases = message.getAliases();
|
||||
List<Identifier> identifiers = message.getIdentifiers();
|
||||
|
||||
if(aliases != null)
|
||||
for(Identifier identifier: identifiers)
|
||||
{
|
||||
for(Alias alias : aliases)
|
||||
{
|
||||
if(alias.hasActions())
|
||||
{
|
||||
List<AliasAction> actions = alias.getAction();
|
||||
List<Alias> aliases = mAliasList.getAliases(identifier);
|
||||
|
||||
for(AliasAction action : actions)
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
if(alias != null && alias.hasActions())
|
||||
{
|
||||
for(AliasAction action: alias.getAction())
|
||||
{
|
||||
/* Provide access to the thread pool manager in case the
|
||||
* action needs to setup a timer, and provide the original
|
||||
* message to be used as part of the action (e.g. sending
|
||||
* the message as a text message to a cell phone */
|
||||
action.execute(ThreadPool.SCHEDULED, alias, message);
|
||||
action.execute(alias, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
//No actions neeeded
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
//No actions neeeded
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
//No actions neeeded
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
//No actions neeeded
|
||||
}
|
||||
|
||||
/**
|
||||
* IMessageListener interface ... delegates to this class implementation of Listener<Message>
|
||||
*/
|
||||
@Override
|
||||
public Listener<IMessage> getMessageListener()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.action;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.swing.JOptionPane;
|
||||
import java.awt.EventQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -18,19 +38,15 @@ public abstract class RecurringAction extends AliasAction
|
||||
protected AtomicBoolean mRunning = new AtomicBoolean(false);
|
||||
@JsonIgnore
|
||||
private ScheduledFuture<?> mPerpetualAction;
|
||||
@JsonIgnore
|
||||
protected ScheduledExecutorService mScheduledExecutorService;
|
||||
|
||||
protected Interval mInterval = Interval.ONCE;
|
||||
protected int mPeriod = 5;
|
||||
|
||||
public abstract void performAction(Alias alias, Message message);
|
||||
public abstract void performAction(Alias alias, IMessage message);
|
||||
|
||||
@Override
|
||||
public void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message)
|
||||
public void execute(Alias alias, IMessage message)
|
||||
{
|
||||
mScheduledExecutorService = scheduledExecutorService;
|
||||
|
||||
if(mRunning.compareAndSet(false, true))
|
||||
{
|
||||
switch(mInterval)
|
||||
@@ -41,10 +57,10 @@ public abstract class RecurringAction extends AliasAction
|
||||
break;
|
||||
case DELAYED_RESET:
|
||||
performThreadedAction(alias, message);
|
||||
mScheduledExecutorService.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
|
||||
break;
|
||||
case UNTIL_DISMISSED:
|
||||
mPerpetualAction = mScheduledExecutorService.scheduleAtFixedRate(
|
||||
mPerpetualAction = ThreadPool.SCHEDULED.scheduleAtFixedRate(
|
||||
new PerformActionTask(alias, message), mPeriod, mPeriod, TimeUnit.SECONDS);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -56,18 +72,13 @@ public abstract class RecurringAction extends AliasAction
|
||||
|
||||
final String text = sb.toString();
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
JOptionPane.showMessageDialog(null, text,
|
||||
"Alias Alert", JOptionPane.INFORMATION_MESSAGE);
|
||||
EventQueue.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null, text,
|
||||
"Alias Alert", JOptionPane.INFORMATION_MESSAGE);
|
||||
|
||||
dismiss(false);
|
||||
dismiss(false);
|
||||
|
||||
mScheduledExecutorService.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
|
||||
}
|
||||
ThreadPool.SCHEDULED.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -79,16 +90,9 @@ public abstract class RecurringAction extends AliasAction
|
||||
* Spawns the performAction() event into a new thread so that it doesn't
|
||||
* delay any decoder actions.
|
||||
*/
|
||||
private void performThreadedAction(final Alias alias, final Message message)
|
||||
private void performThreadedAction(final Alias alias, final IMessage message)
|
||||
{
|
||||
mScheduledExecutorService.schedule(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
performAction(alias, message);
|
||||
}
|
||||
}, 0, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.schedule(() -> performAction(alias, message), 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +143,7 @@ public abstract class RecurringAction extends AliasAction
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private Interval(String label)
|
||||
Interval(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
@@ -153,9 +157,9 @@ public abstract class RecurringAction extends AliasAction
|
||||
public class PerformActionTask implements Runnable
|
||||
{
|
||||
private Alias mAlias;
|
||||
private Message mMessage;
|
||||
private IMessage mMessage;
|
||||
|
||||
public PerformActionTask(Alias alias, Message message)
|
||||
public PerformActionTask(Alias alias, IMessage message)
|
||||
{
|
||||
mAlias = alias;
|
||||
mMessage = message;
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.action.beep;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.action.AliasActionType;
|
||||
import io.github.dsheirer.alias.action.RecurringAction;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
|
||||
public class BeepAction extends RecurringAction
|
||||
{
|
||||
@@ -17,7 +37,7 @@ public class BeepAction extends RecurringAction
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(Alias alias, Message message )
|
||||
public void performAction(Alias alias, IMessage message )
|
||||
{
|
||||
System.out.println( "\007" );
|
||||
}
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.action.clip;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@@ -5,7 +25,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.action.AliasActionType;
|
||||
import io.github.dsheirer.alias.action.RecurringAction;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -45,7 +65,7 @@ public class ClipAction extends RecurringAction
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(Alias alias, Message message)
|
||||
public void performAction(Alias alias, IMessage message)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.action.script;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.action.AliasActionType;
|
||||
import io.github.dsheirer.alias.action.RecurringAction;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -39,7 +59,7 @@ public class ScriptAction extends RecurringAction
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(Alias alias, Message message)
|
||||
public void performAction(Alias alias, IMessage message)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -63,8 +83,7 @@ public class ScriptAction extends RecurringAction
|
||||
|
||||
int exitCode = p.waitFor();
|
||||
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(p.getInputStream()));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
|
||||
String line = "";
|
||||
|
||||
@@ -77,8 +96,7 @@ public class ScriptAction extends RecurringAction
|
||||
|
||||
if(exitCode != 0)
|
||||
{
|
||||
throw new RuntimeException("Exit Code: " + exitCode +
|
||||
" Console:" + sb.toString());
|
||||
throw new RuntimeException("Exit Code: " + exitCode + " Console:" + sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
******************************************************************************/
|
||||
@@ -23,46 +23,52 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.alias.id.esn.Esn;
|
||||
import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
|
||||
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
|
||||
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
|
||||
import io.github.dsheirer.alias.id.mdc.MDC1200ID;
|
||||
import io.github.dsheirer.alias.id.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
|
||||
import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
|
||||
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
|
||||
import io.github.dsheirer.alias.id.priority.Priority;
|
||||
import io.github.dsheirer.alias.id.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.record.Record;
|
||||
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
|
||||
import io.github.dsheirer.alias.id.status.StatusID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
|
||||
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
|
||||
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.PROPERTY, property="type")
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value=BroadcastChannel.class, name="broadcastChannel"),
|
||||
@JsonSubTypes.Type(value=Esn.class, name="esn"),
|
||||
@JsonSubTypes.Type(value=FleetsyncID.class, name="fleetsyncID"),
|
||||
@JsonSubTypes.Type(value = BroadcastChannel.class, name = "broadcastChannel"),
|
||||
@JsonSubTypes.Type(value = Esn.class, name = "esn"),
|
||||
@JsonSubTypes.Type(value = FleetsyncID.class, name = "fleetsyncID"),
|
||||
@JsonSubTypes.Type(value = LoJackFunctionAndID.class, name = "loJackFunctionAndID"),
|
||||
@JsonSubTypes.Type(value = MDC1200ID.class, name = "mdc1200ID"),
|
||||
@JsonSubTypes.Type(value = Min.class, name = "min"),
|
||||
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
|
||||
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
|
||||
@JsonSubTypes.Type(value = Talkgroup.class, name = "talkgroup"),
|
||||
@JsonSubTypes.Type(value = TalkgroupRange.class, name = "talkgroupRange"),
|
||||
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
|
||||
@JsonSubTypes.Type(value = Record.class, name = "record"),
|
||||
@JsonSubTypes.Type(value = SiteID.class, name = "siteID"),
|
||||
@JsonSubTypes.Type(value = StatusID.class, name = "statusID"),
|
||||
@JsonSubTypes.Type(value = TalkgroupID.class, name = "talkgroupID"),
|
||||
@JsonSubTypes.Type(value = LegacyTalkgroupID.class, name = "talkgroupID"),
|
||||
@JsonSubTypes.Type(value = UniqueID.class, name = "uniqueID")
|
||||
})
|
||||
@JacksonXmlRootElement( localName = "id" )
|
||||
@JacksonXmlRootElement(localName = "id")
|
||||
public abstract class AliasID
|
||||
{
|
||||
public AliasID()
|
||||
{
|
||||
}
|
||||
public AliasID()
|
||||
{
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public abstract AliasIDType getType();
|
||||
|
||||
public abstract boolean matches( AliasID id );
|
||||
@JsonIgnore
|
||||
public abstract AliasIDType getType();
|
||||
|
||||
@JsonIgnore
|
||||
public abstract boolean isValid();
|
||||
public abstract boolean matches(AliasID id);
|
||||
|
||||
@JsonIgnore
|
||||
public abstract boolean isValid();
|
||||
}
|
||||
|
||||
@@ -1,49 +1,55 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
******************************************************************************/
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id;
|
||||
|
||||
public enum AliasIDType
|
||||
{
|
||||
ESN( "ESN" ),
|
||||
FLEETSYNC( "Fleetsync" ),
|
||||
LOJACK( "LoJack" ),
|
||||
LTR_NET_UID( "LTR-Net UID" ),
|
||||
MDC1200( "MDC-1200" ),
|
||||
MIN( "Passport MIN" ),
|
||||
MPT1327( "MPT-1327" ),
|
||||
SITE( "Site" ),
|
||||
STATUS( "Status" ),
|
||||
TALKGROUP( "Talkgroup" ),
|
||||
BROADCAST_CHANNEL("Audio Broadcast Channel"),
|
||||
ESN("ESN"),
|
||||
INVERT("Audio Inversion"),
|
||||
LOJACK("LoJack"),
|
||||
LTR_NET_UID("LTR-Net UID"),
|
||||
MIN("Passport MIN"),
|
||||
PRIORITY("Audio Priority"),
|
||||
RECORD("Record"),
|
||||
SITE("Site"),
|
||||
STATUS("Status"),
|
||||
TALKGROUP("Talkgroup"),
|
||||
TALKGROUP_RANGE("Talkgroup Range"),
|
||||
|
||||
INVERT( "Audio Inversion" ),
|
||||
PRIORITY( "Audio Priority" ),
|
||||
NON_RECORDABLE( "Audio Non-Recordable" ),
|
||||
BROADCAST_CHANNEL( "Audio Broadcast Channel" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private AliasIDType( String label )
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
//Legacy identifier types - no longer used
|
||||
FLEETSYNC("Fleetsync"),
|
||||
LEGACY_TALKGROUP("Legacy Talkgroup"),
|
||||
MDC1200("MDC-1200"),
|
||||
MPT1327("MPT-1327"),
|
||||
NON_RECORDABLE("Audio Non-Recordable");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
AliasIDType(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
******************************************************************************/
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
@@ -26,10 +28,19 @@ import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
@@ -40,328 +51,323 @@ import java.util.List;
|
||||
|
||||
public class AliasIdentifierEditor extends Editor<Alias>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static ListModel<AliasID> EMPTY_MODEL = new DefaultListModel<>();
|
||||
private JList<AliasID> mAliasIDList = new JList<>( EMPTY_MODEL );
|
||||
private JButton mNewIDButton;
|
||||
private JButton mCloneIDButton;
|
||||
private JButton mDeleteIDButton;
|
||||
private EditorContainer mEditorContainer = new EditorContainer();
|
||||
private static ListModel<AliasID> EMPTY_MODEL = new DefaultListModel<>();
|
||||
private JList<AliasID> mAliasIDList = new JList<>(EMPTY_MODEL);
|
||||
private JButton mNewIDButton;
|
||||
private JButton mCloneIDButton;
|
||||
private JButton mDeleteIDButton;
|
||||
private EditorContainer mEditorContainer = new EditorContainer();
|
||||
|
||||
private AliasModel mAliasModel;
|
||||
private AliasModel mAliasModel;
|
||||
private BroadcastModel mBroadcastModel;
|
||||
|
||||
public AliasIdentifierEditor( AliasModel aliasModel, BroadcastModel broadcastModel )
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
|
||||
public AliasIdentifierEditor(AliasModel aliasModel, BroadcastModel broadcastModel)
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
mBroadcastModel = broadcastModel;
|
||||
|
||||
init();
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 3",
|
||||
"[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]" ) );
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 3",
|
||||
"[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]"));
|
||||
|
||||
mAliasIDList.setVisibleRowCount( 6 );
|
||||
mAliasIDList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
|
||||
mAliasIDList.setLayoutOrientation( JList.VERTICAL );
|
||||
mAliasIDList.addListSelectionListener( new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged( ListSelectionEvent event )
|
||||
{
|
||||
if( !event.getValueIsAdjusting() )
|
||||
{
|
||||
JList<?> list = (JList<?>)event.getSource();
|
||||
|
||||
Object selectedItem = list.getSelectedValue();
|
||||
|
||||
if( selectedItem != null && selectedItem instanceof AliasID )
|
||||
{
|
||||
AliasID selected = (AliasID)selectedItem;
|
||||
mAliasIDList.setVisibleRowCount(6);
|
||||
mAliasIDList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
mAliasIDList.setLayoutOrientation(JList.VERTICAL);
|
||||
mAliasIDList.addListSelectionListener(new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent event)
|
||||
{
|
||||
if(!event.getValueIsAdjusting())
|
||||
{
|
||||
JList<?> list = (JList<?>)event.getSource();
|
||||
|
||||
mEditorContainer.setAliasID( selected );
|
||||
|
||||
mCloneIDButton.setEnabled( true );
|
||||
mDeleteIDButton.setEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
mCloneIDButton.setEnabled( false );
|
||||
mDeleteIDButton.setEnabled( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( mAliasIDList );
|
||||
add( scroller, "span,grow" );
|
||||
|
||||
add( mEditorContainer, "span,grow" );
|
||||
Object selectedItem = list.getSelectedValue();
|
||||
|
||||
mNewIDButton = new JButton( "New ..." );
|
||||
mNewIDButton.setToolTipText( "Create a new Alias Identifier" );
|
||||
mNewIDButton.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
if(selectedItem != null && selectedItem instanceof AliasID)
|
||||
{
|
||||
AliasID selected = (AliasID)selectedItem;
|
||||
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.ESN ) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.FLEETSYNC) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.LOJACK) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.LTR_NET_UID) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.MDC1200 ) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.MPT1327 ) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.MIN ) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.SITE) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.STATUS) );
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.TALKGROUP) );
|
||||
mEditorContainer.setAliasID(selected);
|
||||
|
||||
menu.addSeparator();
|
||||
mCloneIDButton.setEnabled(true);
|
||||
mDeleteIDButton.setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCloneIDButton.setEnabled(false);
|
||||
mDeleteIDButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.BROADCAST_CHANNEL) );
|
||||
JScrollPane scroller = new JScrollPane(mAliasIDList);
|
||||
add(scroller, "span,grow");
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
Alias alias = getItem();
|
||||
add(mEditorContainer, "span,grow");
|
||||
|
||||
if( alias.isRecordable() )
|
||||
{
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.NON_RECORDABLE) );
|
||||
}
|
||||
mNewIDButton = new JButton("New ...");
|
||||
mNewIDButton.setToolTipText("Create a new Alias Identifier");
|
||||
mNewIDButton.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
if( !alias.hasCallPriority() )
|
||||
{
|
||||
menu.add( new AddAliasIdentifierItem( AliasIDType.PRIORITY) );
|
||||
}
|
||||
}
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP_RANGE));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.ESN));
|
||||
// menu.add(new AddAliasIdentifierItem(AliasIDType.LOJACK));
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.STATUS));
|
||||
|
||||
menu.show( e.getComponent(), e.getX(), e.getY() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewIDButton );
|
||||
|
||||
mCloneIDButton = new JButton( "Clone" );
|
||||
mCloneIDButton.setToolTipText( "Create a copy of the currently selected identifier" );
|
||||
mCloneIDButton.setEnabled( false );
|
||||
mCloneIDButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
AliasID selected = mAliasIDList.getSelectedValue();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
AliasID clone = AliasFactory.copyOf( selected );
|
||||
menu.addSeparator();
|
||||
|
||||
if( clone != null )
|
||||
{
|
||||
addAliasIDToList( clone );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( mCloneIDButton );
|
||||
|
||||
mDeleteIDButton = new JButton( "Delete" );
|
||||
mDeleteIDButton.setToolTipText( "Delete the currently selected identifier" );
|
||||
mDeleteIDButton.setEnabled( false );
|
||||
mDeleteIDButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
final AliasID selected = mAliasIDList.getSelectedValue();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int choice = JOptionPane.showConfirmDialog( mDeleteIDButton,
|
||||
"Do you want to delete [" + selected.toString() + "]",
|
||||
"Are you sure?", JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( choice == JOptionPane.YES_OPTION && hasItem() )
|
||||
{
|
||||
Alias alias = getItem();
|
||||
|
||||
alias.removeAliasID( selected );
|
||||
|
||||
mAliasModel.broadcast( new AliasEvent( alias, AliasEvent.Event.CHANGE ) );
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.BROADCAST_CHANNEL));
|
||||
|
||||
setItem( alias );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( mDeleteIDButton, "wrap" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Alias alias )
|
||||
{
|
||||
super.setItem( alias );
|
||||
|
||||
if( alias == null || alias.getId().isEmpty() )
|
||||
{
|
||||
mAliasIDList.setModel( EMPTY_MODEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultListModel<AliasID> model = new DefaultListModel<AliasID>();
|
||||
if(hasItem())
|
||||
{
|
||||
Alias alias = getItem();
|
||||
|
||||
List<AliasID> ids = alias.getId();
|
||||
|
||||
Collections.sort( ids, new Comparator<AliasID>()
|
||||
{
|
||||
@Override
|
||||
public int compare( AliasID o1, AliasID o2 )
|
||||
{
|
||||
return o1.toString().compareTo( o2.toString() );
|
||||
}
|
||||
} );
|
||||
|
||||
for( AliasID id: ids )
|
||||
{
|
||||
model.addElement( id );
|
||||
}
|
||||
|
||||
mAliasIDList.setModel( model );
|
||||
}
|
||||
|
||||
mEditorContainer.setAliasID( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( isModified() || mEditorContainer.isModified() )
|
||||
{
|
||||
if( mEditorContainer.isModified() )
|
||||
{
|
||||
mEditorContainer.save();
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mAliasModel.broadcast( new AliasEvent( getItem(), AliasEvent.Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EditorContainer extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
if(!alias.isRecordable())
|
||||
{
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.RECORD));
|
||||
}
|
||||
|
||||
private Editor<AliasID> mEditor = new EmptyEditor<>();
|
||||
if(!alias.hasCallPriority())
|
||||
{
|
||||
menu.add(new AddAliasIdentifierItem(AliasIDType.PRIORITY));
|
||||
}
|
||||
}
|
||||
|
||||
public EditorContainer()
|
||||
{
|
||||
setLayout( new MigLayout( "","[grow,fill]", "[grow,fill]" ) );
|
||||
menu.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
});
|
||||
|
||||
add( mEditor );
|
||||
}
|
||||
|
||||
public boolean isModified()
|
||||
{
|
||||
if( mEditor != null )
|
||||
{
|
||||
return mEditor.isModified();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
if( mEditor != null )
|
||||
{
|
||||
mEditor.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAliasID( AliasID aliasID )
|
||||
{
|
||||
if( mEditor != null )
|
||||
{
|
||||
if( mEditor.isModified() )
|
||||
{
|
||||
int option = JOptionPane.showConfirmDialog(
|
||||
EditorContainer.this,
|
||||
"Identifier settings have changed. Do you want to save these changes?",
|
||||
"Save Changes?",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE );
|
||||
|
||||
if( option == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mEditor.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
removeAll();
|
||||
|
||||
//This will always give us an editor
|
||||
mEditor = AliasFactory.getEditor( aliasID, mBroadcastModel );
|
||||
|
||||
add( mEditor );
|
||||
add(mNewIDButton);
|
||||
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void addAliasIDToList( final AliasID id )
|
||||
{
|
||||
if( id != null && hasItem() )
|
||||
{
|
||||
final Alias alias = getItem();
|
||||
|
||||
alias.addAliasID( id );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setItem( alias );
|
||||
|
||||
mAliasIDList.setSelectedValue( id, true );
|
||||
|
||||
AliasIdentifierEditor.this.setModified( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class AddAliasIdentifierItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AliasIDType mAliasIDType;
|
||||
mCloneIDButton = new JButton("Clone");
|
||||
mCloneIDButton.setToolTipText("Create a copy of the currently selected identifier");
|
||||
mCloneIDButton.setEnabled(false);
|
||||
mCloneIDButton.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
AliasID selected = mAliasIDList.getSelectedValue();
|
||||
|
||||
public AddAliasIdentifierItem( AliasIDType type )
|
||||
{
|
||||
super( type.toString() );
|
||||
|
||||
mAliasIDType = type;
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
final AliasID id = AliasFactory.getAliasID( mAliasIDType );
|
||||
|
||||
addAliasIDToList( id );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
if(selected != null)
|
||||
{
|
||||
AliasID clone = AliasFactory.copyOf(selected);
|
||||
|
||||
if(clone != null)
|
||||
{
|
||||
addAliasIDToList(clone);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
add(mCloneIDButton);
|
||||
|
||||
mDeleteIDButton = new JButton("Delete");
|
||||
mDeleteIDButton.setToolTipText("Delete the currently selected identifier");
|
||||
mDeleteIDButton.setEnabled(false);
|
||||
mDeleteIDButton.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
final AliasID selected = mAliasIDList.getSelectedValue();
|
||||
|
||||
if(selected != null)
|
||||
{
|
||||
int choice = JOptionPane.showConfirmDialog(mDeleteIDButton,
|
||||
"Do you want to delete [" + selected.toString() + "]",
|
||||
"Are you sure?", JOptionPane.YES_NO_OPTION);
|
||||
|
||||
if(choice == JOptionPane.YES_OPTION && hasItem())
|
||||
{
|
||||
Alias alias = getItem();
|
||||
|
||||
alias.removeAliasID(selected);
|
||||
|
||||
mAliasModel.broadcast(new AliasEvent(alias, AliasEvent.Event.CHANGE));
|
||||
|
||||
setItem(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
add(mDeleteIDButton, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(Alias alias)
|
||||
{
|
||||
super.setItem(alias);
|
||||
|
||||
if(alias == null || alias.getId().isEmpty())
|
||||
{
|
||||
mAliasIDList.setModel(EMPTY_MODEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultListModel<AliasID> model = new DefaultListModel<AliasID>();
|
||||
|
||||
List<AliasID> ids = alias.getId();
|
||||
|
||||
Collections.sort(ids, new Comparator<AliasID>()
|
||||
{
|
||||
@Override
|
||||
public int compare(AliasID o1, AliasID o2)
|
||||
{
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
|
||||
for(AliasID id : ids)
|
||||
{
|
||||
model.addElement(id);
|
||||
}
|
||||
|
||||
mAliasIDList.setModel(model);
|
||||
}
|
||||
|
||||
mEditorContainer.setAliasID(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if(isModified() || mEditorContainer.isModified())
|
||||
{
|
||||
if(mEditorContainer.isModified())
|
||||
{
|
||||
mEditorContainer.save();
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
if(hasItem())
|
||||
{
|
||||
mAliasModel.broadcast(new AliasEvent(getItem(), AliasEvent.Event.CHANGE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EditorContainer extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Editor<AliasID> mEditor = new EmptyEditor<>();
|
||||
|
||||
public EditorContainer()
|
||||
{
|
||||
setLayout(new MigLayout("", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
add(mEditor);
|
||||
}
|
||||
|
||||
public boolean isModified()
|
||||
{
|
||||
if(mEditor != null)
|
||||
{
|
||||
return mEditor.isModified();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
if(mEditor != null)
|
||||
{
|
||||
mEditor.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAliasID(AliasID aliasID)
|
||||
{
|
||||
if(mEditor != null)
|
||||
{
|
||||
if(mEditor.isModified())
|
||||
{
|
||||
int option = JOptionPane.showConfirmDialog(
|
||||
EditorContainer.this,
|
||||
"Identifier settings have changed. Do you want to save these changes?",
|
||||
"Save Changes?",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if(option == JOptionPane.YES_OPTION)
|
||||
{
|
||||
mEditor.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
removeAll();
|
||||
|
||||
//This will always give us an editor
|
||||
mEditor = AliasFactory.getEditor(aliasID, mBroadcastModel);
|
||||
|
||||
add(mEditor);
|
||||
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void addAliasIDToList(final AliasID id)
|
||||
{
|
||||
if(id != null && hasItem())
|
||||
{
|
||||
final Alias alias = getItem();
|
||||
|
||||
alias.addAliasID(id);
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setItem(alias);
|
||||
|
||||
mAliasIDList.setSelectedValue(id, true);
|
||||
|
||||
AliasIdentifierEditor.this.setModified(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class AddAliasIdentifierItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AliasIDType mAliasIDType;
|
||||
|
||||
public AddAliasIdentifierItem(AliasIDType type)
|
||||
{
|
||||
super(type.toString());
|
||||
|
||||
mAliasIDType = type;
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
final AliasID id = AliasFactory.getAliasID(mAliasIDType);
|
||||
|
||||
addAliasIDToList(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,13 @@ public class Esn extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "ESN: " + mEsn;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("ESN: ").append(mEsn != null ? mEsn : "(empty)");
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" **NOT VALID**");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.fleetsync;
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.fleetsync;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
@@ -48,7 +50,7 @@ public class FleetsyncID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Fleetsync: " + mID;
|
||||
return "Fleetsync: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,21 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.fleetsync;
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.fleetsync;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
@@ -23,9 +25,13 @@ import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mdc;
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.mdc;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
@@ -49,7 +51,7 @@ public class MDC1200ID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MDC-1200: " + mID;
|
||||
return "MDC-1200: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD**";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.mdc;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class MDC1200IDEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT = "<html>"
|
||||
+ "<h3>MDC-1200 Identifier</h3>"
|
||||
+ "<b>MDC-1200:</b> four digit [0-9] value (e.g. <u>1234</u>)<br>"
|
||||
+ "<b>Wildcard:</b> use an asterisk (*) to wildcard individual<br>"
|
||||
+ "digits (e.g. <u>123*</u> or <u>**34</u>)"
|
||||
+ "</html>";
|
||||
|
||||
private JTextField mTextField;
|
||||
|
||||
public MDC1200IDEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("MDC-1200 ID:"));
|
||||
|
||||
MaskFormatter formatter = null;
|
||||
|
||||
try
|
||||
{
|
||||
//Mask: 4 digits
|
||||
formatter = new MaskFormatter("####");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//Do nothing, the mask was invalid
|
||||
}
|
||||
|
||||
mTextField = new JFormattedTextField(formatter);
|
||||
mTextField.getDocument().addDocumentListener(this);
|
||||
mTextField.setToolTipText(HELP_TEXT);
|
||||
add(mTextField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
JOptionPane.showMessageDialog(MDC1200IDEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
public MDC1200ID getMDC1200ID()
|
||||
{
|
||||
if(getItem() instanceof MDC1200ID)
|
||||
{
|
||||
return (MDC1200ID)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
MDC1200ID mdc = getMDC1200ID();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
mTextField.setText(mdc.getIdent());
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
MDC1200ID mdc = getMDC1200ID();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
mdc.setIdent(mTextField.getText());
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mobileID;
|
||||
package io.github.dsheirer.alias.id.legacy.mobileID;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mobileID;
|
||||
package io.github.dsheirer.alias.id.legacy.mobileID;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
@@ -52,7 +52,7 @@ public class Min extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MIN: " + mMin;
|
||||
return "MIN: " + (mMin != null ? mMin : "(empty)") + (isValid() ? "" : " **INVALID - USE TALKGROUP INSTEAD");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,21 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mpt1327;
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.mpt1327;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
@@ -49,7 +51,7 @@ public class MPT1327ID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "MPT-1327: " + mID;
|
||||
return "MPT-1327: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD**";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,29 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mpt1327;
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.mpt1327;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.legacy.nonrecordable;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
|
||||
public class NonRecordable extends AliasID
|
||||
{
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.NON_RECORDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Audio Non-Recordable - **INVALID - USE RECORD INSTEAD**";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.nonrecordable;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class NonRecordableEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT = "<html>"
|
||||
+ "<h3>Audio Non-Recordable</h3>"
|
||||
+ "This identifies an alias as non-recordable.<br><br>"
|
||||
+ "The alias can still be monitored but associated audio will<br>"
|
||||
+ "not be recorded.<br><br>"
|
||||
+ "The default behavior when audio recording is enabled for a<br>"
|
||||
+ "channel is to record all aliases except any alias with a<br>"
|
||||
+ "non-recordable identifier";
|
||||
|
||||
public NonRecordableEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 1", "[]", "[][]"));
|
||||
|
||||
add(new JLabel("Non-Recordable"), "wrap");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
JOptionPane.showMessageDialog(NonRecordableEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.siteID;
|
||||
package io.github.dsheirer.alias.id.legacy.siteID;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
@@ -48,7 +48,7 @@ public class SiteID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Site: " + mSite;
|
||||
return "Site: " + (mSite != null ? mSite : "(empty)") + (isValid() ? "" : " **NOT VALID**");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.siteID;
|
||||
package io.github.dsheirer.alias.id.legacy.siteID;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
@@ -1,37 +1,39 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.talkgroup;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
|
||||
public class TalkgroupID extends AliasID
|
||||
public class LegacyTalkgroupID extends AliasID
|
||||
{
|
||||
private String mTalkgroup;
|
||||
|
||||
public TalkgroupID()
|
||||
public LegacyTalkgroupID()
|
||||
{
|
||||
//No arg JAXB constructor
|
||||
}
|
||||
|
||||
public TalkgroupID(String talkgroup)
|
||||
public LegacyTalkgroupID(String talkgroup)
|
||||
{
|
||||
mTalkgroup = talkgroup;
|
||||
}
|
||||
@@ -57,7 +59,7 @@ public class TalkgroupID extends AliasID
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Talkgroup: " + mTalkgroup);
|
||||
sb.append("Legacy Talkgroup:").append(mTalkgroup).append(" *Disabled - Please use Talkgroup instead");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -67,9 +69,9 @@ public class TalkgroupID extends AliasID
|
||||
{
|
||||
boolean retVal = false;
|
||||
|
||||
if(id instanceof TalkgroupID)
|
||||
if(id instanceof LegacyTalkgroupID)
|
||||
{
|
||||
TalkgroupID tgid = (TalkgroupID)id;
|
||||
LegacyTalkgroupID tgid = (LegacyTalkgroupID)id;
|
||||
|
||||
//Create a pattern - replace * wildcards with regex single-char wildcard
|
||||
String pattern = mTalkgroup.replace("*", ".?");
|
||||
@@ -84,6 +86,6 @@ public class TalkgroupID extends AliasID
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.TALKGROUP;
|
||||
return AliasIDType.LEGACY_TALKGROUP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.legacy.talkgroup;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class LegacyTalkgroupIDEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT =
|
||||
"<html><h3>Talkgroup Identifier</h3>"
|
||||
+ "<b>P25:</b> 4 or 6 hex characters (e.g. <u>AB12</u> or <u>ABC123</u>)<br>"
|
||||
+ "<b>LTR:</b> A-HH-TTT where A=Area H=Home T=Talkgroup (<u>0-01-128</u>)<br>"
|
||||
+ "<b>Passport</b>: 5-digit number (<u>12345</u> or <u>00023</u>)<br>"
|
||||
+ "<br>"
|
||||
+ "<b>Wildcard:</b> use an asterisk (*) in place of each talkgroup digit (e.g. <u>0*1*5</u>)"
|
||||
+ "</html>";
|
||||
|
||||
private JTextField mTextField;
|
||||
|
||||
public LegacyTalkgroupIDEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("Talkgroup:"));
|
||||
|
||||
mTextField = new JTextField();
|
||||
mTextField.getDocument().addDocumentListener(this);
|
||||
mTextField.setToolTipText(HELP_TEXT);
|
||||
add(mTextField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
JOptionPane.showMessageDialog(LegacyTalkgroupIDEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
public LegacyTalkgroupID getTalkgroupID()
|
||||
{
|
||||
if(getItem() instanceof LegacyTalkgroupID)
|
||||
{
|
||||
return (LegacyTalkgroupID)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
LegacyTalkgroupID talkgroup = getTalkgroupID();
|
||||
|
||||
if(talkgroup != null)
|
||||
{
|
||||
mTextField.setText(talkgroup.getTalkgroup());
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
LegacyTalkgroupID talkgroup = getTalkgroupID();
|
||||
|
||||
if(talkgroup != null)
|
||||
{
|
||||
talkgroup.setTalkgroup(mTextField.getText());
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.uniqueID;
|
||||
package io.github.dsheirer.alias.id.legacy.uniqueID;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
@@ -48,7 +48,7 @@ public class UniqueID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "UniqueID: " + mUid;
|
||||
return "UniqueID: " + mUid + " **INVALID - USE TALKGROUP INSTEAD";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.uniqueID;
|
||||
package io.github.dsheirer.alias.id.legacy.uniqueID;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
@@ -26,7 +26,7 @@ import io.github.dsheirer.module.decode.lj1200.LJ1200Message;
|
||||
public class LoJackFunctionAndID extends AliasID
|
||||
{
|
||||
private LJ1200Message.Function mFunction = LJ1200Message.Function.F0_UNKNOWN;
|
||||
private String mID = "*****";
|
||||
private String mID = null;
|
||||
|
||||
public LoJackFunctionAndID()
|
||||
{
|
||||
@@ -62,7 +62,8 @@ public class LoJackFunctionAndID extends AliasID
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "LoJack FUNC: " + mFunction.getLabel() + " ID:" + (mID == null ? "" : mID);
|
||||
return "LoJack FUNCTION: " + mFunction.getLabel() +
|
||||
" ID:" + (mID == null ? "" : mID) + (isValid() ? "" : " **NOT VALID**");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.mdc;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class MDC1200IDEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT = "<html>"
|
||||
+ "<h3>MDC-1200 Identifier</h3>"
|
||||
+ "<b>MDC-1200:</b> four digit [0-9] value (e.g. <u>1234</u>)<br>"
|
||||
+ "<b>Wildcard:</b> use an asterisk (*) to wildcard individual<br>"
|
||||
+ "digits (e.g. <u>123*</u> or <u>**34</u>)"
|
||||
+ "</html>";
|
||||
|
||||
private JTextField mTextField;
|
||||
|
||||
public MDC1200IDEditor( AliasID aliasID )
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem( aliasID );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
|
||||
|
||||
add( new JLabel( "MDC-1200 ID:" ) );
|
||||
|
||||
MaskFormatter formatter = null;
|
||||
|
||||
try
|
||||
{
|
||||
//Mask: 4 digits
|
||||
formatter = new MaskFormatter( "####" );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
//Do nothing, the mask was invalid
|
||||
}
|
||||
|
||||
mTextField = new JFormattedTextField( formatter );
|
||||
mTextField.getDocument().addDocumentListener( this );
|
||||
mTextField.setToolTipText( HELP_TEXT );
|
||||
add( mTextField, "growx,push" );
|
||||
|
||||
JLabel help = new JLabel( "Help ..." );
|
||||
help.setForeground( Color.BLUE.brighter() );
|
||||
help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
|
||||
help.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( MDC1200IDEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( help, "align left" );
|
||||
}
|
||||
|
||||
public MDC1200ID getMDC1200ID()
|
||||
{
|
||||
if( getItem() instanceof MDC1200ID )
|
||||
{
|
||||
return (MDC1200ID)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( AliasID aliasID )
|
||||
{
|
||||
super.setItem( aliasID );
|
||||
|
||||
MDC1200ID mdc = getMDC1200ID();
|
||||
|
||||
if( mdc != null )
|
||||
{
|
||||
mTextField.setText( mdc.getIdent() );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
MDC1200ID mdc = getMDC1200ID();
|
||||
|
||||
if( mdc != null )
|
||||
{
|
||||
mdc.setIdent( mTextField.getText() );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package io.github.dsheirer.alias.id.nonrecordable;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
|
||||
public class NonRecordable extends AliasID
|
||||
{
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.NON_RECORDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Audio Non-Recordable";
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.nonrecordable;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class NonRecordableEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT = "<html>"
|
||||
+ "<h3>Audio Non-Recordable</h3>"
|
||||
+ "This identifies an alias as non-recordable.<br><br>"
|
||||
+ "The alias can still be monitored but associated audio will<br>"
|
||||
+ "not be recorded.<br><br>"
|
||||
+ "The default behavior when audio recording is enabled for a<br>"
|
||||
+ "channel is to record all aliases except any alias with a<br>"
|
||||
+ "non-recordable identifier";
|
||||
|
||||
public NonRecordableEditor( AliasID aliasID )
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem( aliasID );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
|
||||
|
||||
add( new JLabel( "Non-Recordable" ), "wrap" );
|
||||
|
||||
JLabel help = new JLabel( "Help ..." );
|
||||
help.setForeground( Color.BLUE.brighter() );
|
||||
help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
|
||||
help.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( NonRecordableEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( help, "align left" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
}
|
||||
}
|
||||
56
src/main/java/io/github/dsheirer/alias/id/record/Record.java
Normal file
56
src/main/java/io/github/dsheirer/alias/id/record/Record.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.record;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
|
||||
/**
|
||||
* Alias identifier to flag an alias for audio recording
|
||||
*/
|
||||
public class Record extends AliasID
|
||||
{
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.RECORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Record Audio";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.record;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class RecordEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT = "<html>"
|
||||
+ "<h3>Record Audio</h3>"
|
||||
+ "Any audio associated with this alias will be recorded.<br><br>";
|
||||
|
||||
public RecordEditor(AliasID aliasID )
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem( aliasID );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
|
||||
|
||||
add( new JLabel( "Record Audio" ), "wrap" );
|
||||
|
||||
JLabel help = new JLabel( "Help ..." );
|
||||
help.setForeground( Color.BLUE.brighter() );
|
||||
help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
|
||||
help.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( RecordEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( help, "align left" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Integer talkgroup identifier with protocol.
|
||||
*/
|
||||
public class Talkgroup extends AliasID
|
||||
{
|
||||
private Protocol mProtocol = Protocol.UNKNOWN;
|
||||
private int mValue;
|
||||
|
||||
public Talkgroup()
|
||||
{
|
||||
//No arg JAXB constructor
|
||||
}
|
||||
|
||||
public Talkgroup(Protocol protocol, int value)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "value")
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(int value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
if(mProtocol == null || mProtocol == Protocol.UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(mProtocol);
|
||||
return talkgroupFormat.getMinimumValidValue() <= mValue && mValue <= talkgroupFormat.getMaximumValidValue();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Talkgroup:").append(TalkgroupFormatter.format(mProtocol, mValue));
|
||||
sb.append(" Protocol:").append((mProtocol));
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" **NOT VALID**");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
if(id instanceof Talkgroup)
|
||||
{
|
||||
Talkgroup tgid = (Talkgroup)id;
|
||||
return (getProtocol() == tgid.getProtocol()) && (getValue() == tgid.getValue());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.TALKGROUP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.ParseException;
|
||||
|
||||
public class TalkgroupEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TalkgroupEditor.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
|
||||
private MaskFormatter mMaskFormatter = new MaskFormatter();
|
||||
private JComboBox<Protocol> mComboProtocol;
|
||||
private JFormattedTextField mTalkgroupField;
|
||||
|
||||
|
||||
public TalkgroupEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("Protocol:"));
|
||||
|
||||
mComboProtocol = new JComboBox<>();
|
||||
|
||||
DefaultComboBoxModel<Protocol> model = new DefaultComboBoxModel<>();
|
||||
|
||||
for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
|
||||
{
|
||||
model.addElement(protocol);
|
||||
}
|
||||
|
||||
mComboProtocol.setModel(model);
|
||||
mComboProtocol.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
|
||||
updateEditor(protocol);
|
||||
setModified(true);
|
||||
}
|
||||
});
|
||||
|
||||
add(mComboProtocol);
|
||||
|
||||
add(new JLabel("Value:"));
|
||||
|
||||
mTalkgroupField = new JFormattedTextField(mMaskFormatter);
|
||||
mTalkgroupField.getDocument().addDocumentListener(this);
|
||||
add(mTalkgroupField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(getCurrentProtocol());
|
||||
JOptionPane.showMessageDialog(TalkgroupEditor.this,
|
||||
talkgroupFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
private void updateEditor(Protocol protocol)
|
||||
{
|
||||
TalkgroupFormat mask = TalkgroupFormat.get(protocol);
|
||||
int currentValue = 0;
|
||||
Talkgroup talkgroup = getTalkgroup();
|
||||
|
||||
if(talkgroup != null)
|
||||
{
|
||||
currentValue = talkgroup.getValue();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mTalkgroupField.setValue(null);
|
||||
mTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaskFormatter.setMask(mask.getMask());
|
||||
if(mask.getMask().contains("*"))
|
||||
{
|
||||
mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
|
||||
}
|
||||
mTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentValue));
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Protocol getCurrentProtocol()
|
||||
{
|
||||
return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Current talkgroup alias id
|
||||
*/
|
||||
public Talkgroup getTalkgroup()
|
||||
{
|
||||
if(getItem() instanceof Talkgroup)
|
||||
{
|
||||
return (Talkgroup)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
Talkgroup talkgroup = getTalkgroup();
|
||||
|
||||
if(talkgroup != null)
|
||||
{
|
||||
Protocol currentProtocol = getCurrentProtocol();
|
||||
if(currentProtocol == talkgroup.getProtocol())
|
||||
{
|
||||
updateEditor(talkgroup.getProtocol());
|
||||
}
|
||||
mComboProtocol.getModel().setSelectedItem(talkgroup.getProtocol());
|
||||
|
||||
String formatted = TalkgroupFormatter.format(talkgroup.getProtocol(), talkgroup.getValue());
|
||||
mTalkgroupField.setValue(formatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
|
||||
mTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
Talkgroup talkgroup = getTalkgroup();
|
||||
|
||||
if(talkgroup != null)
|
||||
{
|
||||
Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
|
||||
if(protocol == null)
|
||||
{
|
||||
protocol = Protocol.UNKNOWN;
|
||||
}
|
||||
|
||||
int value = -1;
|
||||
|
||||
try
|
||||
{
|
||||
value = TalkgroupFormatter.parse(protocol, mTalkgroupField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
TalkgroupFormat mask = TalkgroupFormat.get(protocol);
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(value < mask.getMinimumValidValue() || value > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid value [" + mTalkgroupField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(TalkgroupEditor.this, message, "Invalid Talkgroup Value",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
talkgroup.setValue(value);
|
||||
}
|
||||
|
||||
talkgroup.setProtocol(protocol);
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Talkgroup protocol identifier entry masks and min/max valid ranges and valid range descriptions
|
||||
*
|
||||
* Note: the getMask() value is intended for use with a MaskFormatter attached to a JFormattedTextField. The
|
||||
* protocol masks that have a dash (-) use the # (any digit) character and the protocol masks that do not have
|
||||
* a formatting dash use an asterisk (*). Within the editor(s) that use this enumeration, the editor must use
|
||||
* a setValidCharacters() on the mask formatter whenever it detects the mask containing one or more asterisks.
|
||||
*/
|
||||
public enum TalkgroupFormat
|
||||
{
|
||||
APCO25("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||
"<html>APCO25 valid range is 1 to 65,535(talkgroup)<br>or 1 to 16,777,215 (radio ID)"),
|
||||
FLEETSYNC("###-####", 1, 0x7FFFFF, "001-0001 to 127-8192",
|
||||
"<html>Fleetsync valid ranges are 1-127(prefix)<br>and 1-8192(ident) (ie. 001-0001 to 127-8192)"),
|
||||
LTR("##-###", 257, 5375, "01-001 to 20-255",
|
||||
"<html>LTR valid ranges are 1-20(repeater) and 1-255(talkgroup) (ie. 01-001 to 20-255)"),
|
||||
MDC1200("*****", 1, 0xFFFF, "1 to 65,535",
|
||||
"MDC-1200 valid value range is 1-65,535"),
|
||||
MPT1327("###-####", 1, 0x7FFFFF, "000-0001 to 127-8192",
|
||||
"<html>MPT-1327 valid ranges are 0-127(prefix)<br>and 1-8192(ident) (ie. 000-0001 to 127-8192)"),
|
||||
PASSPORT("*****", 1, 0xFFFF, "1 to 65,535",
|
||||
"Passport valid value range is 1-65,535"),
|
||||
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
|
||||
"Unknown protocol valid value range is 1-16,777,215");
|
||||
|
||||
private String mMask;
|
||||
private int mMinimumValue;
|
||||
private int mMaximumValue;
|
||||
private String mValidRangeDescription;
|
||||
private String mValidRangeHelpText;
|
||||
|
||||
TalkgroupFormat(String mask, int minimumValue, int maximumValue, String validRangeDescription, String validRangeHelpText)
|
||||
{
|
||||
mMask = mask;
|
||||
mMinimumValue = minimumValue;
|
||||
mMaximumValue = maximumValue;
|
||||
mValidRangeDescription = validRangeDescription;
|
||||
mValidRangeHelpText = validRangeHelpText;
|
||||
}
|
||||
|
||||
public String getMask()
|
||||
{
|
||||
return mMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum valid value for the protocol
|
||||
*/
|
||||
public int getMinimumValidValue()
|
||||
{
|
||||
return mMinimumValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum valid value for the protocol
|
||||
*/
|
||||
public int getMaximumValidValue()
|
||||
{
|
||||
return mMaximumValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the value is valid for the protocol
|
||||
*/
|
||||
public boolean isValid(int value)
|
||||
{
|
||||
return getMinimumValidValue() <= value && value <= getMaximumValidValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Short description of the valid value range
|
||||
*/
|
||||
public String getValidRangeDescription()
|
||||
{
|
||||
return mValidRangeDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Help text for valid value ranges
|
||||
*/
|
||||
public String getValidRangeHelpText()
|
||||
{
|
||||
return mValidRangeHelpText;
|
||||
}
|
||||
|
||||
public static TalkgroupFormat get(Protocol protocol)
|
||||
{
|
||||
if(protocol == null)
|
||||
{
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
switch(protocol)
|
||||
{
|
||||
case APCO25:
|
||||
return APCO25;
|
||||
case FLEETSYNC:
|
||||
return FLEETSYNC;
|
||||
case LTR:
|
||||
case LTR_NET:
|
||||
case LTR_STANDARD:
|
||||
return LTR;
|
||||
case MDC1200:
|
||||
return MDC1200;
|
||||
case MPT1327:
|
||||
return MPT1327;
|
||||
case PASSPORT:
|
||||
return PASSPORT;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.FleetsyncTalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.IntegerFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.LTRTalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.MDC1200TalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.MPT1327TalkgroupFormatter;
|
||||
import io.github.dsheirer.preference.identifier.talkgroup.PassportTalkgroupFormatter;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Protocol-specific formatting of talkgroup values and parsing of formatted talkgroup values.
|
||||
*/
|
||||
public class TalkgroupFormatter
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TalkgroupFormatter.class);
|
||||
private static Map<Protocol,IntegerFormatter> mFormatterMap = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
|
||||
mFormatterMap.put(Protocol.FLEETSYNC, new FleetsyncTalkgroupFormatter());
|
||||
LTRTalkgroupFormatter ltr = new LTRTalkgroupFormatter();
|
||||
mFormatterMap.put(Protocol.LTR, ltr);
|
||||
mFormatterMap.put(Protocol.LTR_NET, ltr);
|
||||
mFormatterMap.put(Protocol.LTR_STANDARD, ltr);
|
||||
mFormatterMap.put(Protocol.MDC1200, new MDC1200TalkgroupFormatter());
|
||||
mFormatterMap.put(Protocol.MPT1327, new MPT1327TalkgroupFormatter());
|
||||
mFormatterMap.put(Protocol.PASSPORT, new PassportTalkgroupFormatter());
|
||||
mFormatterMap.put(Protocol.UNKNOWN, new IntegerFormatter());
|
||||
}
|
||||
|
||||
public TalkgroupFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the formatted value into an integer using a protocol specific formatter
|
||||
*/
|
||||
public static int parse(Protocol protocol, String value) throws ParseException
|
||||
{
|
||||
IntegerFormatter formatter = mFormatterMap.get(protocol);
|
||||
|
||||
if(formatter == null)
|
||||
{
|
||||
formatter = mFormatterMap.get(Protocol.UNKNOWN);
|
||||
}
|
||||
|
||||
return formatter.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the integer value using a protocol-specific formatter
|
||||
*/
|
||||
public static String format(Protocol protocol, int value)
|
||||
{
|
||||
IntegerFormatter formatter = mFormatterMap.get(protocol);
|
||||
|
||||
if(formatter == null)
|
||||
{
|
||||
formatter = mFormatterMap.get(Protocol.UNKNOWN);
|
||||
}
|
||||
|
||||
return formatter.format(value);
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class TalkgroupIDEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String HELP_TEXT =
|
||||
"<html><h3>Talkgroup Identifier</h3>"
|
||||
+ "<b>P25:</b> 4 or 6 hex characters (e.g. <u>AB12</u> or <u>ABC123</u>)<br>"
|
||||
+ "<b>LTR:</b> A-HH-TTT where A=Area H=Home T=Talkgroup (<u>0-01-128</u>)<br>"
|
||||
+ "<b>Passport</b>: 5-digit number (<u>12345</u> or <u>00023</u>)<br>"
|
||||
+ "<br>"
|
||||
+ "<b>Wildcard:</b> use an asterisk (*) in place of each talkgroup digit (e.g. <u>0*1*5</u>)"
|
||||
+ "</html>";
|
||||
|
||||
private JTextField mTextField;
|
||||
|
||||
public TalkgroupIDEditor( AliasID aliasID )
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem( aliasID );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
|
||||
|
||||
add( new JLabel( "Talkgroup:" ) );
|
||||
|
||||
mTextField = new JTextField();
|
||||
mTextField.getDocument().addDocumentListener( this );
|
||||
mTextField.setToolTipText( HELP_TEXT );
|
||||
add( mTextField, "growx,push" );
|
||||
|
||||
JLabel help = new JLabel( "Help ..." );
|
||||
help.setForeground( Color.BLUE.brighter() );
|
||||
help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
|
||||
help.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( TalkgroupIDEditor.this,
|
||||
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( help, "align left" );
|
||||
}
|
||||
|
||||
public TalkgroupID getTalkgroupID()
|
||||
{
|
||||
if( getItem() instanceof TalkgroupID )
|
||||
{
|
||||
return (TalkgroupID)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( AliasID aliasID )
|
||||
{
|
||||
super.setItem( aliasID );
|
||||
|
||||
TalkgroupID talkgroup = getTalkgroupID();
|
||||
|
||||
if( talkgroup != null )
|
||||
{
|
||||
mTextField.setText( talkgroup.getTalkgroup() );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
TalkgroupID talkgroup = getTalkgroupID();
|
||||
|
||||
if( talkgroup != null )
|
||||
{
|
||||
talkgroup.setTalkgroup( mTextField.getText() );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
|
||||
/**
|
||||
* Integer talkgroup identifier range of values with protocol.
|
||||
*/
|
||||
public class TalkgroupRange extends AliasID
|
||||
{
|
||||
private Protocol mProtocol = Protocol.UNKNOWN;
|
||||
private int mMinTalkgroup;
|
||||
private int mMaxTalkgroup;
|
||||
|
||||
public TalkgroupRange()
|
||||
{
|
||||
//No arg JAXB constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a talkgroup range of from - to talkgroup values (inclusive) for the specified protocol
|
||||
* @param protocol for the talkgroup range
|
||||
* @param minTalkgroup starting or minimum talkgroup value
|
||||
* @param maxTalkgroup ending or maximum talkgroup value
|
||||
*/
|
||||
public TalkgroupRange(Protocol protocol, int minTalkgroup, int maxTalkgroup)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
mMinTalkgroup = minTalkgroup;
|
||||
mMaxTalkgroup = maxTalkgroup;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "min")
|
||||
public int getMinTalkgroup()
|
||||
{
|
||||
return mMinTalkgroup;
|
||||
}
|
||||
|
||||
public void setMinTalkgroup(int minTalkgroup)
|
||||
{
|
||||
mMinTalkgroup = minTalkgroup;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "max")
|
||||
public int getMaxTalkgroup()
|
||||
{
|
||||
return mMaxTalkgroup;
|
||||
}
|
||||
|
||||
public void setMaxTalkgroup(int maxTalkgroup)
|
||||
{
|
||||
mMaxTalkgroup = maxTalkgroup;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
|
||||
public Protocol getProtocol()
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
public void setProtocol(Protocol protocol)
|
||||
{
|
||||
mProtocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
if(mProtocol == null || mProtocol == Protocol.UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(mProtocol);
|
||||
return talkgroupFormat.getMinimumValidValue() <= mMinTalkgroup &&
|
||||
mMinTalkgroup <= talkgroupFormat.getMaximumValidValue() &&
|
||||
talkgroupFormat.getMinimumValidValue() <= mMaxTalkgroup &&
|
||||
mMaxTalkgroup <= talkgroupFormat.getMaximumValidValue();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Talkgroup Range:").append(TalkgroupFormatter.format(mProtocol, mMinTalkgroup));
|
||||
sb.append(" to ").append(TalkgroupFormatter.format(mProtocol, mMaxTalkgroup));
|
||||
sb.append(" Protocol:").append(mProtocol != null ? mProtocol : "unspecified");
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" **NOT VALID**");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AliasID id)
|
||||
{
|
||||
if(id instanceof TalkgroupRange)
|
||||
{
|
||||
TalkgroupRange tgid = (TalkgroupRange)id;
|
||||
return (getProtocol() == tgid.getProtocol()) &&
|
||||
(getMinTalkgroup() == tgid.getMinTalkgroup()) &&
|
||||
(getMaxTalkgroup() == tgid.getMaxTalkgroup());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this talkgroup range contains/includes the talkgroup value
|
||||
* @param talkgroupValue
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(int talkgroupValue)
|
||||
{
|
||||
return getMinTalkgroup() <= talkgroupValue && talkgroupValue <= getMaxTalkgroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this talkgroup range overlaps the talkgroup range argument.
|
||||
* @param talkgroupRange to check for overlap
|
||||
* @return true if the ranges overlap
|
||||
*/
|
||||
public boolean overlaps(TalkgroupRange talkgroupRange)
|
||||
{
|
||||
return contains(talkgroupRange.getMinTalkgroup()) ||
|
||||
contains(talkgroupRange.getMaxTalkgroup()) ||
|
||||
(getMinTalkgroup() < talkgroupRange.getMinTalkgroup() &&
|
||||
talkgroupRange.getMaxTalkgroup() < getMaxTalkgroup()) ||
|
||||
(talkgroupRange.getMinTalkgroup() < getMinTalkgroup() &&
|
||||
getMaxTalkgroup() < talkgroupRange.getMaxTalkgroup());
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
{
|
||||
return AliasIDType.TALKGROUP_RANGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.alias.id.talkgroup;
|
||||
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.ParseException;
|
||||
|
||||
public class TalkgroupRangeEditor extends DocumentListenerEditor<AliasID>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TalkgroupRangeEditor.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
|
||||
private MaskFormatter mMaskFormatter = new MaskFormatter();
|
||||
private JComboBox<Protocol> mComboProtocol;
|
||||
private JFormattedTextField mMinTalkgroupField;
|
||||
private JFormattedTextField mMaxTalkgroupField;
|
||||
|
||||
public TalkgroupRangeEditor(AliasID aliasID)
|
||||
{
|
||||
initGUI();
|
||||
|
||||
setItem(aliasID);
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
|
||||
|
||||
add(new JLabel("Protocol:"));
|
||||
|
||||
mComboProtocol = new JComboBox<Protocol>();
|
||||
|
||||
DefaultComboBoxModel<Protocol> model = new DefaultComboBoxModel<>();
|
||||
|
||||
for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
|
||||
{
|
||||
model.addElement(protocol);
|
||||
}
|
||||
|
||||
mComboProtocol.setModel(model);
|
||||
mComboProtocol.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
|
||||
updateEditor(protocol);
|
||||
setModified(true);
|
||||
}
|
||||
});
|
||||
|
||||
add(mComboProtocol);
|
||||
|
||||
add(new JLabel("Min:"));
|
||||
|
||||
mMinTalkgroupField = new JFormattedTextField(mMaskFormatter);
|
||||
mMinTalkgroupField.getDocument().addDocumentListener(this);
|
||||
add(mMinTalkgroupField, "growx,push");
|
||||
|
||||
add(new JLabel("Max:"));
|
||||
|
||||
mMaxTalkgroupField = new JFormattedTextField(mMaskFormatter);
|
||||
mMaxTalkgroupField.getDocument().addDocumentListener(this);
|
||||
add(mMaxTalkgroupField, "growx,push");
|
||||
|
||||
JLabel help = new JLabel("Help ...");
|
||||
help.setForeground(Color.BLUE.brighter());
|
||||
help.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
help.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(getCurrentProtocol());
|
||||
JOptionPane.showMessageDialog(TalkgroupRangeEditor.this,
|
||||
talkgroupFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
add(help, "align left");
|
||||
}
|
||||
|
||||
private void updateEditor(Protocol protocol)
|
||||
{
|
||||
TalkgroupFormat mask = TalkgroupFormat.get(protocol);
|
||||
int currentMinValue = 0;
|
||||
int currentMaxValue = 0;
|
||||
TalkgroupRange talkgroupRange = getTalkgroupRange();
|
||||
|
||||
if(talkgroupRange != null)
|
||||
{
|
||||
currentMinValue = talkgroupRange.getMinTalkgroup();
|
||||
currentMaxValue = talkgroupRange.getMaxTalkgroup();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mMinTalkgroupField.setValue(null);
|
||||
mMaxTalkgroupField.setValue(null);
|
||||
|
||||
mMinTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaxTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
|
||||
mMaskFormatter.setMask(mask.getMask());
|
||||
if(mask.getMask().contains("*"))
|
||||
{
|
||||
mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
|
||||
}
|
||||
|
||||
mMinTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentMinValue));
|
||||
mMaxTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentMaxValue));
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Protocol getCurrentProtocol()
|
||||
{
|
||||
return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public TalkgroupRange getTalkgroupRange()
|
||||
{
|
||||
if(getItem() instanceof TalkgroupRange)
|
||||
{
|
||||
return (TalkgroupRange)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(AliasID aliasID)
|
||||
{
|
||||
super.setItem(aliasID);
|
||||
|
||||
TalkgroupRange talkgroupRange = getTalkgroupRange();
|
||||
|
||||
updateEditor(talkgroupRange.getProtocol());
|
||||
|
||||
if(talkgroupRange != null)
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(talkgroupRange.getProtocol());
|
||||
String minFormatted = TalkgroupFormatter.format(talkgroupRange.getProtocol(), talkgroupRange.getMinTalkgroup());
|
||||
mMinTalkgroupField.setValue(minFormatted);
|
||||
String maxFormatted = TalkgroupFormatter.format(talkgroupRange.getProtocol(), talkgroupRange.getMaxTalkgroup());
|
||||
mMaxTalkgroupField.setValue(maxFormatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
|
||||
mMinTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
|
||||
mMaxTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
TalkgroupRange talkgroupRange = getTalkgroupRange();
|
||||
|
||||
if(talkgroupRange != null)
|
||||
{
|
||||
Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
|
||||
|
||||
if(protocol == null)
|
||||
{
|
||||
protocol = Protocol.UNKNOWN;
|
||||
}
|
||||
|
||||
talkgroupRange.setProtocol(protocol);
|
||||
|
||||
int minValue = -1;
|
||||
int maxValue = -1;
|
||||
|
||||
try
|
||||
{
|
||||
minValue = TalkgroupFormatter.parse(protocol, mMinTalkgroupField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
maxValue = TalkgroupFormatter.parse(protocol, mMaxTalkgroupField.getText());
|
||||
}
|
||||
catch(ParseException pe)
|
||||
{
|
||||
//ignore ... value is still -1 and outside valid value range
|
||||
}
|
||||
|
||||
TalkgroupFormat mask = TalkgroupFormat.get(protocol);
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(minValue < mask.getMinimumValidValue() || minValue > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid minimum value [" + mMinTalkgroupField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(TalkgroupRangeEditor.this, message,
|
||||
"Invalid Talkgroup Value", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
talkgroupRange.setMinTalkgroup(minValue);
|
||||
}
|
||||
|
||||
//Check for valid value within range ... notify user but allow value to persist
|
||||
if(maxValue < mask.getMinimumValidValue() || maxValue > mask.getMaximumValidValue())
|
||||
{
|
||||
String message = "Invalid maximum value [" + mMaxTalkgroupField.getText() + "]. " + protocol.name() +
|
||||
" valid range is [" + mask.getValidRangeDescription() + "]";
|
||||
|
||||
JOptionPane.showMessageDialog(TalkgroupRangeEditor.this, message,
|
||||
"Invalid Talkgroup Value", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
talkgroupRange.setMaxTalkgroup(maxValue);
|
||||
}
|
||||
|
||||
talkgroupRange.setProtocol(protocol);
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
}
|
||||
111
src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
Normal file
111
src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.audio.squelch.ISquelchStateListener;
|
||||
import io.github.dsheirer.identifier.IdentifierUpdateListener;
|
||||
import io.github.dsheirer.identifier.IdentifierUpdateNotification;
|
||||
import io.github.dsheirer.identifier.MutableIdentifierCollection;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
|
||||
/**
|
||||
* Base audio module implementation.
|
||||
*/
|
||||
public abstract class AbstractAudioModule extends Module implements IAudioPacketProvider, IdentifierUpdateListener,
|
||||
ISquelchStateListener
|
||||
{
|
||||
//Static unique audio channel identifier.
|
||||
private static int AUDIO_CHANNEL_ID_GENERATOR = 1;
|
||||
|
||||
private int mAudioChannelId = AUDIO_CHANNEL_ID_GENERATOR++;
|
||||
private Listener<ReusableAudioPacket> mAudioPacketListener;
|
||||
private MutableIdentifierCollection mIdentifierCollection = new MutableIdentifierCollection();
|
||||
|
||||
/**
|
||||
* Constructs an abstract audio module
|
||||
*/
|
||||
public AbstractAudioModule()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique channel identifier for use in tagging audio packets with an audio channel ID so that they can
|
||||
* be identified within a combined audio packet stream
|
||||
*/
|
||||
public int getAudioChannelId()
|
||||
{
|
||||
return mAudioChannelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive updated identifiers from decoder state(s).
|
||||
*/
|
||||
@Override
|
||||
public Listener<IdentifierUpdateNotification> getIdentifierUpdateListener()
|
||||
{
|
||||
return mIdentifierCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifier collection containing the current set of identifiers received from the decoder state(s).
|
||||
*/
|
||||
public MutableIdentifierCollection getIdentifierCollection()
|
||||
{
|
||||
return mIdentifierCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an audio packet listener to receive the output from this audio module.
|
||||
*/
|
||||
@Override
|
||||
public void setAudioPacketListener(Listener<ReusableAudioPacket> listener)
|
||||
{
|
||||
mAudioPacketListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the audio packet listener from receiving audio packets from this module.
|
||||
*/
|
||||
@Override
|
||||
public void removeAudioPacketListener()
|
||||
{
|
||||
mAudioPacketListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registered listener for receiving audio packets produced by this module
|
||||
*/
|
||||
public Listener<ReusableAudioPacket> getAudioPacketListener()
|
||||
{
|
||||
return mAudioPacketListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if there is a listener registered to receive audio packets from this audio module.
|
||||
*/
|
||||
public boolean hasAudioPacketListener()
|
||||
{
|
||||
return mAudioPacketListener != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.audio.output.AudioOutput;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.settings.ColorSetting;
|
||||
import io.github.dsheirer.settings.Setting;
|
||||
import io.github.dsheirer.settings.SettingChangeListener;
|
||||
import io.github.dsheirer.settings.SettingsManager;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class AudioChannelPanel extends JPanel
|
||||
implements Listener<AudioEvent>, SettingChangeListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AudioChannelPanel.class);
|
||||
|
||||
public static final String PROPERTY_PREFIX = "audio.channel.panel.color.";
|
||||
public static final String PROPERTY_COLOR_BACKGROUND = PROPERTY_PREFIX + "background";
|
||||
public static final String PROPERTY_COLOR_LABEL = PROPERTY_PREFIX + "label";
|
||||
public static final String PROPERTY_COLOR_MUTED = PROPERTY_PREFIX + "muted";
|
||||
public static final String PROPERTY_COLOR_VALUE = PROPERTY_PREFIX + "value";
|
||||
|
||||
private Font mFont = new Font(Font.MONOSPACED, Font.PLAIN, 16);
|
||||
|
||||
private Color mBackgroundColor;
|
||||
private Color mLabelColor;
|
||||
private Color mMutedColor;
|
||||
private Color mValueColor;
|
||||
|
||||
private IconManager mIconManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
private AudioOutput mAudioOutput;
|
||||
|
||||
private JLabel mMutedLabel = new JLabel("M");
|
||||
private JLabel mChannelName = new JLabel(" ");
|
||||
private JLabel mToAlias = new JLabel(" ");
|
||||
private JLabel mTo = new JLabel("-----");
|
||||
|
||||
private boolean mConfigured = false;
|
||||
|
||||
public AudioChannelPanel(IconManager iconManager, SettingsManager settingsManager, AudioOutput audioOutput)
|
||||
{
|
||||
mIconManager = iconManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mSettingsManager.addListener(this);
|
||||
|
||||
mAudioOutput = audioOutput;
|
||||
|
||||
if(mAudioOutput != null)
|
||||
{
|
||||
mAudioOutput.addAudioEventListener(this);
|
||||
mAudioOutput.setMetadataListener(new AudioMetadataProcessor());
|
||||
}
|
||||
|
||||
mBackgroundColor = SystemProperties.getInstance().get(PROPERTY_COLOR_BACKGROUND, Color.BLACK);
|
||||
mLabelColor = SystemProperties.getInstance().get(PROPERTY_COLOR_LABEL, Color.LIGHT_GRAY);
|
||||
mMutedColor = SystemProperties.getInstance().get(PROPERTY_COLOR_MUTED, Color.RED);
|
||||
mValueColor = SystemProperties.getInstance().get(PROPERTY_COLOR_VALUE, Color.GREEN);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("align center center, insets 0 0 0 0",
|
||||
"[][][align right]0[grow,fill]", ""));
|
||||
setBackground(mBackgroundColor);
|
||||
|
||||
mMutedLabel.setFont(mFont);
|
||||
mMutedLabel.setForeground(mMutedColor);
|
||||
mMutedLabel.setVisible(false);
|
||||
add(mMutedLabel);
|
||||
|
||||
mChannelName = new JLabel(mAudioOutput != null ? mAudioOutput.getChannelName() : " ");
|
||||
mChannelName.setFont(mFont);
|
||||
mChannelName.setForeground(mLabelColor);
|
||||
add(mChannelName);
|
||||
|
||||
mToAlias.setFont(mFont);
|
||||
mToAlias.setForeground(mValueColor);
|
||||
add(mToAlias);
|
||||
|
||||
mTo.setFont(mFont);
|
||||
mTo.setForeground(mValueColor);
|
||||
add(mTo,"wmin 10lp");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final AudioEvent audioEvent)
|
||||
{
|
||||
switch(audioEvent.getType())
|
||||
{
|
||||
case AUDIO_STOPPED:
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
resetLabels();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case AUDIO_MUTED:
|
||||
case AUDIO_UNMUTED:
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mMutedLabel.setVisible(mAudioOutput.isMuted());
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the from and to labels. Note: this does not happen on the swing
|
||||
* event thread. Only invoke from the swing thread.
|
||||
*/
|
||||
private void resetLabels()
|
||||
{
|
||||
updateLabel(mTo, null, mToAlias, null);
|
||||
|
||||
mConfigured = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the alias label with text and icon from the alias. Note: this
|
||||
* does not occur on the Swing event thread -- wrap any calls to this
|
||||
* method with an event thread call.
|
||||
*/
|
||||
private void updateLabel(JLabel textLabel, String value, JLabel iconLabel, Alias alias)
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
iconLabel.setIcon(mIconManager.getIcon(alias.getIconName(), 18));
|
||||
|
||||
String aliasName = alias.getName();
|
||||
|
||||
//Truncate label if length exceeds 33 characters - hack!
|
||||
if(aliasName.length() > 33)
|
||||
{
|
||||
textLabel.setText(aliasName.substring(0,30) + "...");
|
||||
}
|
||||
else
|
||||
{
|
||||
textLabel.setText(aliasName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iconLabel.setIcon(null);
|
||||
textLabel.setText(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iconLabel.setIcon(null);
|
||||
textLabel.setText("-----");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes audio metadata to update this panel's display values
|
||||
*/
|
||||
public class AudioMetadataProcessor implements Listener<Metadata>
|
||||
{
|
||||
@Override
|
||||
public void receive(final Metadata metadata)
|
||||
{
|
||||
if(metadata.isUpdated() || !mConfigured)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateLabel(mTo, metadata.getPrimaryAddressTo().getIdentifier(),
|
||||
mToAlias, metadata.getPrimaryAddressTo().getAlias());
|
||||
|
||||
mConfigured = true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mTo != null)
|
||||
{
|
||||
mTo.setForeground(mLabelColor);
|
||||
}
|
||||
if(mToAlias != null)
|
||||
{
|
||||
mToAlias.setForeground(mLabelColor);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingDeleted(Setting setting)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Processes audio packets to assign attributes to each packet based on alias list settings. Updates the
|
||||
* monitoring, recording and streaming attributes.
|
||||
*/
|
||||
public class AudioMetadataProcessor
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AudioMetadataProcessor.class);
|
||||
private AliasModel mAliasModel;
|
||||
private Map<Integer, AliasList> mAliasListMap = new HashMap<>();
|
||||
private Set<Integer> mAliasListRetrievedSet = new TreeSet<>();
|
||||
|
||||
public AudioMetadataProcessor(AliasModel aliasModel)
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
public void process(ReusableAudioPacket audioPacket)
|
||||
{
|
||||
if(audioPacket.hasIdentifierCollection() && audioPacket.getIdentifierCollection().hasAliasListConfiguration())
|
||||
{
|
||||
AliasList aliasList = null;
|
||||
|
||||
if(mAliasListRetrievedSet.contains(audioPacket.getAudioChannelId()))
|
||||
{
|
||||
aliasList = mAliasListMap.get(audioPacket.getAudioChannelId());
|
||||
}
|
||||
else
|
||||
{
|
||||
aliasList = mAliasModel.getAliasList(audioPacket.getIdentifierCollection().getAliasListConfiguration());
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
mAliasListMap.put(audioPacket.getAudioChannelId(), aliasList);
|
||||
mAliasListRetrievedSet.add(audioPacket.getAudioChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
audioPacket.addBroadcastChannels(aliasList.getBroadcastChannels(audioPacket.getIdentifierCollection()));
|
||||
audioPacket.setMonitoringPriority(aliasList.getAudioPlaybackPriority(audioPacket.getIdentifierCollection()));
|
||||
|
||||
//If the audio packet is already marked recordable, leave it alone, otherwise attempt to determine
|
||||
//if we should record the audio packet from the aliased identifiers
|
||||
if(!audioPacket.isRecordable())
|
||||
{
|
||||
audioPacket.setRecordable(aliasList.isRecordable(audioPacket.getIdentifierCollection()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +1,118 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.audio.squelch.ISquelchStateListener;
|
||||
import io.github.dsheirer.audio.squelch.SquelchState;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.audio.squelch.SquelchStateEvent;
|
||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
|
||||
import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter2;
|
||||
import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner;
|
||||
import io.github.dsheirer.dsp.filter.polyphase.PolyphaseFIRDecimatingFilter_RB;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.IFilteredRealBufferListener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import io.github.dsheirer.sample.buffer.IReusableBufferListener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacketQueue;
|
||||
import io.github.dsheirer.sample.buffer.ReusableFloatBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* Provides packaging of demodulated audio sample buffers into audio packets for
|
||||
* broadcast to registered audio packet listeners. Includes audio packet
|
||||
* metadata in constructed audio packets.
|
||||
* Provides packaging of demodulated audio sample buffers into audio packets for broadcast to registered audio packet
|
||||
* listeners. Includes audio packet metadata in constructed audio packets.
|
||||
*
|
||||
* Incorporates audio squelch state listener to control if audio packets are
|
||||
* broadcast or ignored.
|
||||
* Incorporates audio squelch state listener to control if audio packets are broadcast or ignored.
|
||||
*
|
||||
* This class is designed to support 8 kHz sample rate demodulated audio.
|
||||
*/
|
||||
public class AudioModule extends Module implements IAudioPacketProvider, IFilteredRealBufferListener,
|
||||
ISquelchStateListener, Listener<RealBuffer>
|
||||
public class AudioModule extends AbstractAudioModule implements IReusableBufferListener, Listener<ReusableFloatBuffer>
|
||||
{
|
||||
protected static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
|
||||
|
||||
private static float[] mDecimationCoefficients;
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
|
||||
private static float[] sHighPassFilterCoefficients;
|
||||
|
||||
static
|
||||
{
|
||||
//Band-pass filter to both decimate (48kHz to 8kHz) and block 0 - 300 Hz (LTR signalling).
|
||||
FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder()
|
||||
.sampleRate(48000)
|
||||
.stopFrequency1(150)
|
||||
.passFrequencyBegin(300)
|
||||
.passFrequencyEnd(3500)
|
||||
.stopFrequency2(4000)
|
||||
.stopRipple(0.0004)
|
||||
.passRipple(0.008)
|
||||
FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
|
||||
.sampleRate(8000)
|
||||
.stopBandCutoff(200)
|
||||
.stopBandAmplitude(0.0)
|
||||
.stopBandRipple(0.025)
|
||||
.passBandStart(300)
|
||||
.passBandAmplitude(1.0)
|
||||
.passBandRipple(0.01)
|
||||
.build();
|
||||
|
||||
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
|
||||
|
||||
try
|
||||
{
|
||||
if(!designer.isValid())
|
||||
{
|
||||
throw new FilterDesignException("Couldn't design the audio decimation filter");
|
||||
}
|
||||
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
|
||||
|
||||
mDecimationCoefficients = designer.getImpulseResponse();
|
||||
if(designer.isValid())
|
||||
{
|
||||
sHighPassFilterCoefficients = designer.getImpulseResponse();
|
||||
}
|
||||
}
|
||||
catch(FilterDesignException e)
|
||||
catch(FilterDesignException fde)
|
||||
{
|
||||
mLog.debug("Error designing filter", e);
|
||||
mLog.error("Filter design error", fde);
|
||||
}
|
||||
}
|
||||
|
||||
private ReusableAudioPacketQueue mAudioPacketQueue = new ReusableAudioPacketQueue("AudioModule");
|
||||
private RealFIRFilter2 mHighPassFilter = new RealFIRFilter2(sHighPassFilterCoefficients);
|
||||
private SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
||||
private SquelchState mSquelchState = SquelchState.SQUELCH;
|
||||
private Listener<AudioPacket> mAudioPacketListener;
|
||||
private PolyphaseFIRDecimatingFilter_RB mAudioDecimationFilter;
|
||||
private Metadata mMetadata;
|
||||
private boolean mRecordAudioOverride;
|
||||
|
||||
public AudioModule(Metadata metadata)
|
||||
/**
|
||||
* Creates an Audio Module.
|
||||
*/
|
||||
public AudioModule()
|
||||
{
|
||||
mMetadata = metadata;
|
||||
|
||||
mAudioDecimationFilter = new PolyphaseFIRDecimatingFilter_RB(mDecimationCoefficients, 6, 2.0f);
|
||||
mAudioDecimationFilter.setListener(new Listener<RealBuffer>()
|
||||
{
|
||||
@Override
|
||||
public void receive(RealBuffer realBuffer)
|
||||
{
|
||||
if(mAudioPacketListener != null)
|
||||
{
|
||||
AudioPacket packet = new AudioPacket(realBuffer.getSamples(), mMetadata.copyOf());
|
||||
mAudioPacketListener.receive(packet);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
removeAudioPacketListener();
|
||||
mSquelchStateListener = null;
|
||||
mAudioPacketListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all audio packets as recordable when the argument is true. Otherwise, defers to the aliased identifiers
|
||||
* from the identifier collection to determine whether to record the audio or not.
|
||||
* @param recordAudio set to true to mark all audio as recordable.
|
||||
*/
|
||||
public void setRecordAudio(boolean recordAudio)
|
||||
{
|
||||
mRecordAudioOverride = recordAudio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
getIdentifierCollection().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
public void start()
|
||||
{
|
||||
/* No start operations provided */
|
||||
}
|
||||
@@ -125,64 +120,82 @@ public class AudioModule extends Module implements IAudioPacketProvider, IFilter
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
/* Issue an end audio packet in case a recorder is still rolling */
|
||||
if(mAudioPacketListener != null)
|
||||
/* Issue an end-audio packet in case a recorder is still rolling */
|
||||
if(hasAudioPacketListener())
|
||||
{
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END, mMetadata.copyOf()));
|
||||
ReusableAudioPacket endAudioPacket = mAudioPacketQueue.getEndAudioBuffer();
|
||||
endAudioPacket.resetAttributes();
|
||||
endAudioPacket.setAudioChannelId(getAudioChannelId());
|
||||
endAudioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
|
||||
|
||||
if(mRecordAudioOverride)
|
||||
{
|
||||
endAudioPacket.setRecordable(true);
|
||||
}
|
||||
endAudioPacket.incrementUserCount();
|
||||
getAudioPacketListener().receive(endAudioPacket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes demodulated audio samples into audio packets with current audio
|
||||
* metadata and sends to the registered listener
|
||||
*/
|
||||
@Override
|
||||
public void receive(RealBuffer buffer)
|
||||
{
|
||||
if(mAudioPacketListener != null && mSquelchState == SquelchState.UNSQUELCH)
|
||||
{
|
||||
mAudioDecimationFilter.receive(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAudioPacketListener(Listener<AudioPacket> listener)
|
||||
{
|
||||
mAudioPacketListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAudioPacketListener()
|
||||
{
|
||||
mAudioPacketListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<SquelchState> getSquelchStateListener()
|
||||
public Listener<SquelchStateEvent> getSquelchStateListener()
|
||||
{
|
||||
return mSquelchStateListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(ReusableFloatBuffer reusableFloatBuffer)
|
||||
{
|
||||
if(hasAudioPacketListener() && mSquelchState == SquelchState.UNSQUELCH)
|
||||
{
|
||||
ReusableFloatBuffer highPassFiltered = mHighPassFilter.filter(reusableFloatBuffer);
|
||||
|
||||
ReusableAudioPacket audioPacket = mAudioPacketQueue.getBuffer(highPassFiltered.getSampleCount());
|
||||
audioPacket.resetAttributes();
|
||||
audioPacket.setAudioChannelId(getAudioChannelId());
|
||||
audioPacket.loadAudioFrom(highPassFiltered);
|
||||
if(mRecordAudioOverride)
|
||||
{
|
||||
audioPacket.setRecordable(true);
|
||||
}
|
||||
audioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
|
||||
|
||||
getAudioPacketListener().receive(audioPacket);
|
||||
|
||||
highPassFiltered.decrementUserCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
reusableFloatBuffer.decrementUserCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<ReusableFloatBuffer> getReusableBufferListener()
|
||||
{
|
||||
//Redirect received reusable buffers to the receive(buffer) method
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for squelch state listener
|
||||
*/
|
||||
public class SquelchStateListener implements Listener<SquelchState>
|
||||
public class SquelchStateListener implements Listener<SquelchStateEvent>
|
||||
{
|
||||
@Override
|
||||
public void receive(SquelchState state)
|
||||
public void receive(SquelchStateEvent event)
|
||||
{
|
||||
if(state == SquelchState.SQUELCH && mAudioPacketListener != null)
|
||||
if(event.getSquelchState() == SquelchState.SQUELCH && hasAudioPacketListener())
|
||||
{
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END, mMetadata.copyOf()));
|
||||
ReusableAudioPacket endAudioPacket = mAudioPacketQueue.getEndAudioBuffer();
|
||||
endAudioPacket.resetAttributes();
|
||||
endAudioPacket.setAudioChannelId(getAudioChannelId());
|
||||
endAudioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
|
||||
getAudioPacketListener().receive(endAudioPacket);
|
||||
}
|
||||
|
||||
mSquelchState = state;
|
||||
mSquelchState = event.getSquelchState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
|
||||
public class AudioPacket
|
||||
{
|
||||
private Type mType;
|
||||
private RealBuffer mAudioData;
|
||||
private Metadata mMetadata;
|
||||
|
||||
public AudioPacket(Type type, Metadata metadata)
|
||||
{
|
||||
mType = type;
|
||||
mMetadata = metadata;
|
||||
}
|
||||
|
||||
public AudioPacket(float[] audio, Metadata metadata)
|
||||
{
|
||||
this(Type.AUDIO, metadata);
|
||||
|
||||
mAudioData = new RealBuffer(audio);
|
||||
}
|
||||
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return mMetadata != null;
|
||||
}
|
||||
|
||||
public Metadata getMetadata()
|
||||
{
|
||||
return mMetadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata)
|
||||
{
|
||||
mMetadata = metadata;
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
public RealBuffer getAudioBuffer()
|
||||
{
|
||||
return mAudioData;
|
||||
}
|
||||
|
||||
public boolean hasAudioBuffer()
|
||||
{
|
||||
return mAudioData != null;
|
||||
}
|
||||
|
||||
public enum Type
|
||||
{
|
||||
AUDIO,
|
||||
END;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.dsp.filter.channelizer.ContinuousReusableBufferProcessor;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Processes audio packets from all decoder channels, assigns alias attributes and distributes packets
|
||||
* for playback, streaming and recording.
|
||||
*/
|
||||
public class AudioPacketManager implements Listener<ReusableAudioPacket>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AudioPacketManager.class);
|
||||
private AudioMetadataProcessor mAudioMetadataProcessor;
|
||||
private ReusableBufferBroadcaster<ReusableAudioPacket> mBroadcaster = new ReusableBufferBroadcaster<>();
|
||||
private ContinuousReusableBufferProcessor<ReusableAudioPacket> mBufferProcessor;
|
||||
|
||||
public AudioPacketManager(AliasModel aliasModel)
|
||||
{
|
||||
mAudioMetadataProcessor = new AudioMetadataProcessor(aliasModel);
|
||||
mBufferProcessor = new ContinuousReusableBufferProcessor<>(10000, 500);
|
||||
mBufferProcessor.setListener(new Listener<List<ReusableAudioPacket>>()
|
||||
{
|
||||
@Override
|
||||
public void receive(List<ReusableAudioPacket> reusableAudioPackets)
|
||||
{
|
||||
for(ReusableAudioPacket audioPacket: reusableAudioPackets)
|
||||
{
|
||||
mAudioMetadataProcessor.process(audioPacket);
|
||||
mBroadcaster.broadcast(audioPacket);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
mLog.info("Audio packet manager started");
|
||||
mBufferProcessor.start();
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
mLog.info("Audio packet manager stopped");
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary processing method for receiving audio packets from all processing channels.
|
||||
*/
|
||||
@Override
|
||||
public void receive(ReusableAudioPacket audioPacket)
|
||||
{
|
||||
mBufferProcessor.receive(audioPacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the listener to receive enriched audio packets from this manager
|
||||
*/
|
||||
public void addListener(Listener<ReusableAudioPacket> listener)
|
||||
{
|
||||
mBroadcaster.addListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener from receiving enriched audio packets from this manager
|
||||
*/
|
||||
public void removeListener(Listener<ReusableAudioPacket> listener)
|
||||
{
|
||||
mBroadcaster.removeListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AudioPacketRateCounter implements Listener<AudioPacket>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AudioPacketRateCounter.class );
|
||||
|
||||
private Listener<AudioPacket> mListener;
|
||||
private long mCount;
|
||||
private long mStartTime = -1;
|
||||
|
||||
private String mName;
|
||||
|
||||
public AudioPacketRateCounter()
|
||||
{
|
||||
mName = "UNNAMED";
|
||||
}
|
||||
|
||||
public AudioPacketRateCounter( String name )
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( AudioPacket packet )
|
||||
{
|
||||
if( mStartTime == -1 )
|
||||
{
|
||||
mStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
mCount += packet.getAudioBuffer().getSamples().length;
|
||||
|
||||
long elapsed = System.currentTimeMillis() - mStartTime;
|
||||
|
||||
if( elapsed != 0 )
|
||||
{
|
||||
mLog.debug( "[" + mName + "] Audio Rate: " + ( mCount / elapsed ) + " kHz" );
|
||||
}
|
||||
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( packet );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<AudioPacket> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 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 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.
|
||||
* 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/>
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.sample.ConversionUtils;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -34,17 +32,18 @@ public class AudioUtils
|
||||
/**
|
||||
* Converts the audio packets into a byte array of 16-bit, little-endian audio samples
|
||||
*/
|
||||
public static byte[] convertTo16BitSamples(List<AudioPacket> audioPackets)
|
||||
public static byte[] convertTo16BitSamples(List<ReusableAudioPacket> audioPackets)
|
||||
{
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
|
||||
try
|
||||
{
|
||||
for(AudioPacket packet: audioPackets)
|
||||
for(ReusableAudioPacket audioPacket: audioPackets)
|
||||
{
|
||||
//Converting from 32-bit floats to signed 16-bit samples
|
||||
ByteBuffer buffer = ConversionUtils.convertToSigned16BitSamples(packet.getAudioBuffer().getSamples());
|
||||
ByteBuffer buffer = ConversionUtils.convertToSigned16BitSamples(audioPacket.getAudioSamples());
|
||||
stream.write(buffer.array());
|
||||
audioPacket.decrementUserCount();
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.audio.output.AudioOutput;
|
||||
import io.github.dsheirer.audio.playback.AudioOutput;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
|
||||
public interface IAudioPacketListener
|
||||
{
|
||||
public Listener<AudioPacket> getAudioPacketListener();
|
||||
public Listener<ReusableAudioPacket> getAudioPacketListener();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
|
||||
public interface IAudioPacketProvider
|
||||
{
|
||||
public void setAudioPacketListener( Listener<AudioPacket> listener );
|
||||
public void setAudioPacketListener( Listener<ReusableAudioPacket> listener );
|
||||
public void removeAudioPacketListener();
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio;
|
||||
|
||||
/**
|
||||
* Standard voice inversion foldover frequencies
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/Voice_inversion
|
||||
*/
|
||||
public enum InversionFrequency
|
||||
{
|
||||
HZ_2500( 2500 ),
|
||||
HZ_2550( 2550 ),
|
||||
HZ_2600( 2600 ),
|
||||
HZ_2632( 2632 ),
|
||||
HZ_2675( 2675 ),
|
||||
HZ_2718( 2718 ),
|
||||
HZ_2800( 2800 ),
|
||||
HZ_2868( 2868 ),
|
||||
HZ_2950( 2950 ),
|
||||
HZ_3023( 3023 ),
|
||||
HZ_3075( 3075 ),
|
||||
HZ_3107( 3107 ),
|
||||
HZ_3150( 3150 ),
|
||||
HZ_3196( 3196 ),
|
||||
HZ_3333( 3333 ),
|
||||
HZ_3339( 3339 ),
|
||||
HZ_3400( 3400 ),
|
||||
HZ_3496( 3496 ),
|
||||
HZ_3729( 3729 ),
|
||||
HZ_4096( 4096 );
|
||||
|
||||
private int mFrequency;
|
||||
|
||||
private InversionFrequency( int frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
@@ -99,15 +99,15 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
/**
|
||||
* Broadcasts the next song's audio metadata prior to streaming the next song.
|
||||
*
|
||||
* @param metadata for the next recording that will be streamed
|
||||
* @param identifierCollection for the next recording that will be streamed
|
||||
*/
|
||||
protected void broadcastMetadata(Metadata metadata)
|
||||
protected void broadcastMetadata(IdentifierCollection identifierCollection)
|
||||
{
|
||||
IBroadcastMetadataUpdater metadataUpdater = getMetadataUpdater();
|
||||
|
||||
if(metadataUpdater != null)
|
||||
{
|
||||
metadataUpdater.update(metadata);
|
||||
metadataUpdater.update(identifierCollection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,11 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
if(mBroadcastState != state)
|
||||
{
|
||||
mLog.info("[" + getStreamName() + "] status: " + state);
|
||||
if(state == BroadcastState.CONNECTED || state == BroadcastState.DISCONNECTED)
|
||||
{
|
||||
mLog.info("[" + getStreamName() + "] status: " + state);
|
||||
}
|
||||
|
||||
mBroadcastState = state;
|
||||
|
||||
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
|
||||
@@ -438,7 +442,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
|
||||
if(connected())
|
||||
{
|
||||
broadcastMetadata(nextRecording.getMetadata());
|
||||
broadcastMetadata(nextRecording.getIdentifierCollection());
|
||||
}
|
||||
|
||||
metadataUpdateRequired = false;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -33,20 +33,20 @@ public class AudioRecording implements Comparable<AudioRecording>
|
||||
private long mStartTime;
|
||||
private long mRecordingLength;
|
||||
private AtomicInteger mPendingReplayCount = new AtomicInteger();
|
||||
private Metadata mMetadata;
|
||||
private IdentifierCollection mIdentifierCollection;
|
||||
|
||||
/**
|
||||
* Audio recording that is ready to be streamed
|
||||
*
|
||||
* @param path to the audio recording file
|
||||
* @param metadata associated with the recording
|
||||
* @param identifierCollection associated with the recording
|
||||
* @param start time of recording in milliseconds since epoch
|
||||
* @param recordingLength in milliseconds
|
||||
*/
|
||||
public AudioRecording(Path path, Metadata metadata, long start, long recordingLength)
|
||||
public AudioRecording(Path path, IdentifierCollection identifierCollection, long start, long recordingLength)
|
||||
{
|
||||
mPath = path;
|
||||
mMetadata = metadata;
|
||||
mIdentifierCollection = identifierCollection;
|
||||
mStartTime = start;
|
||||
mRecordingLength = recordingLength;
|
||||
}
|
||||
@@ -60,11 +60,19 @@ public class AudioRecording implements Comparable<AudioRecording>
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional audio metadata for the recording.
|
||||
* Optional audio metadata/identifiers for the recording.
|
||||
*/
|
||||
public Metadata getMetadata()
|
||||
public IdentifierCollection getIdentifierCollection()
|
||||
{
|
||||
return mMetadata;
|
||||
return mIdentifierCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this recording contains an optional identifier collection.
|
||||
*/
|
||||
public boolean hasIdentifierCollection()
|
||||
{
|
||||
return mIdentifierCollection != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
@@ -40,6 +43,7 @@ import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.AudioRecorder;
|
||||
import io.github.dsheirer.record.mp3.MP3Recorder;
|
||||
import org.slf4j.Logger;
|
||||
@@ -60,7 +64,7 @@ public class BroadcastFactory
|
||||
* @param configuration describing the server and audio types
|
||||
* @return configured broadcaster or null
|
||||
*/
|
||||
public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration)
|
||||
public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration, AliasModel aliasModel)
|
||||
{
|
||||
if(configuration != null)
|
||||
{
|
||||
@@ -71,15 +75,15 @@ public class BroadcastFactory
|
||||
switch(configuration.getBroadcastServerType())
|
||||
{
|
||||
case BROADCASTIFY:
|
||||
return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration);
|
||||
return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration, aliasModel);
|
||||
case ICECAST_TCP:
|
||||
return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration);
|
||||
return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration, aliasModel);
|
||||
case ICECAST_HTTP:
|
||||
return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration);
|
||||
return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration, aliasModel);
|
||||
case SHOUTCAST_V1:
|
||||
return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration);
|
||||
return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration, aliasModel);
|
||||
case SHOUTCAST_V2:
|
||||
return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration);
|
||||
return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration, aliasModel);
|
||||
case UNKNOWN:
|
||||
default:
|
||||
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
|
||||
@@ -147,7 +151,8 @@ public class BroadcastFactory
|
||||
* @param broadcastModel model for broadcastAudio configurations
|
||||
* @return an editor for the specified broadcastAudio configuration
|
||||
*/
|
||||
public static Editor<BroadcastConfiguration> getEditor(BroadcastConfiguration configuration,
|
||||
public static Editor<BroadcastConfiguration> getEditor(UserPreferences userPreferences,
|
||||
BroadcastConfiguration configuration,
|
||||
BroadcastModel broadcastModel,
|
||||
AliasModel aliasModel,
|
||||
IconManager iconManager)
|
||||
@@ -157,7 +162,7 @@ public class BroadcastFactory
|
||||
switch(configuration.getBroadcastServerType())
|
||||
{
|
||||
case BROADCASTIFY:
|
||||
editor = new BroadcastifyConfigurationEditor(broadcastModel, aliasModel, iconManager);
|
||||
editor = new BroadcastifyConfigurationEditor(userPreferences, broadcastModel, aliasModel, iconManager);
|
||||
break;
|
||||
case ICECAST_TCP:
|
||||
editor = new IcecastTCPConfigurationEditor(broadcastModel, aliasModel, iconManager);
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.audio.AudioPacket;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -46,7 +51,7 @@ import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BroadcastModel extends AbstractTableModel implements Listener<AudioPacket>
|
||||
public class BroadcastModel extends AbstractTableModel implements Listener<ReusableAudioPacket>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(BroadcastModel.class);
|
||||
|
||||
@@ -72,21 +77,21 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
private Map<String,AudioBroadcaster> mBroadcasterMap = new HashMap<>();
|
||||
private IconManager mIconManager;
|
||||
private StreamManager mStreamManager;
|
||||
private AliasModel mAliasModel;
|
||||
private Broadcaster<BroadcastEvent> mBroadcastEventBroadcaster = new Broadcaster<>();
|
||||
|
||||
/**
|
||||
* Model for managing Broadcast configurations and any associated broadcaster instances.
|
||||
*/
|
||||
public BroadcastModel(IconManager iconManager)
|
||||
public BroadcastModel(AliasModel aliasModel, IconManager iconManager, UserPreferences userPreferences)
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
mIconManager = iconManager;
|
||||
mStreamManager = new StreamManager(new CompletedRecordingListener(), BroadcastFormat.MP3,
|
||||
SystemProperties.getInstance().getApplicationFolder(TEMPORARY_STREAM_DIRECTORY));
|
||||
mStreamManager = new StreamManager(new CompletedRecordingListener(), BroadcastFormat.MP3, userPreferences);
|
||||
mStreamManager.start();
|
||||
|
||||
//Monitor to remove temporary recording files that have been streamed by all audio broadcasters
|
||||
ThreadPool.SCHEDULED.scheduleAtFixedRate(new RecordingDeletionMonitor(),
|
||||
15l, 15l, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.scheduleAtFixedRate(new RecordingDeletionMonitor(), 15l, 15l, TimeUnit.SECONDS);
|
||||
|
||||
removeOrphanedTemporaryRecordings();
|
||||
}
|
||||
@@ -276,19 +281,22 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
public void receive(ReusableAudioPacket audioPacket)
|
||||
{
|
||||
if(audioPacket.hasMetadata() && audioPacket.getMetadata().isStreamable())
|
||||
if(audioPacket.isStreamable())
|
||||
{
|
||||
for(BroadcastChannel channel: audioPacket.getMetadata().getBroadcastChannels())
|
||||
for(BroadcastChannel channel: audioPacket.getBroadcastChannels())
|
||||
{
|
||||
if(mBroadcasterMap.containsKey(channel.getChannelName()))
|
||||
{
|
||||
audioPacket.incrementUserCount();
|
||||
mStreamManager.receive(audioPacket);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audioPacket.decrementUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,7 +307,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
if(broadcastConfiguration != null && broadcastConfiguration.isEnabled() && broadcastConfiguration.isValid() &&
|
||||
!mBroadcasterMap.containsKey(broadcastConfiguration.getName()))
|
||||
{
|
||||
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(broadcastConfiguration);
|
||||
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(broadcastConfiguration, mAliasModel);
|
||||
|
||||
if(audioBroadcaster != null)
|
||||
{
|
||||
@@ -580,12 +588,20 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex)
|
||||
{
|
||||
if(columnIndex == COLUMN_SERVER_ICON)
|
||||
switch(columnIndex)
|
||||
{
|
||||
return ImageIcon.class;
|
||||
case COLUMN_BROADCASTER_STATUS:
|
||||
return BroadcastState.class;
|
||||
case COLUMN_BROADCASTER_AGED_OFF_COUNT:
|
||||
case COLUMN_BROADCASTER_QUEUE_SIZE:
|
||||
case COLUMN_BROADCASTER_STREAMED_COUNT:
|
||||
return Integer.class;
|
||||
case COLUMN_SERVER_ICON:
|
||||
return ImageIcon.class;
|
||||
case COLUMN_STREAM_NAME:
|
||||
default:
|
||||
return String.class;
|
||||
}
|
||||
|
||||
return String.class;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -703,22 +719,25 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
@Override
|
||||
public void receive(AudioRecording audioRecording)
|
||||
{
|
||||
Metadata metadata = audioRecording.getMetadata();
|
||||
|
||||
if(metadata != null && metadata.isStreamable())
|
||||
if(audioRecording != null && audioRecording.hasIdentifierCollection())
|
||||
{
|
||||
for(BroadcastChannel broadcastChannel : metadata.getBroadcastChannels())
|
||||
AliasList aliasList = mAliasModel.getAliasList(audioRecording.getIdentifierCollection());
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
String channelName = broadcastChannel.getChannelName();
|
||||
|
||||
if(channelName != null)
|
||||
for(BroadcastChannel broadcastChannel : aliasList.getBroadcastChannels(audioRecording.getIdentifierCollection()))
|
||||
{
|
||||
AudioBroadcaster audioBroadcaster = getBroadcaster(channelName);
|
||||
String channelName = broadcastChannel.getChannelName();
|
||||
|
||||
if(audioBroadcaster != null)
|
||||
if(channelName != null)
|
||||
{
|
||||
audioRecording.addPendingReplay();
|
||||
audioBroadcaster.receive(audioRecording);
|
||||
AudioBroadcaster audioBroadcaster = getBroadcaster(channelName);
|
||||
|
||||
if(audioBroadcaster != null)
|
||||
{
|
||||
audioRecording.addPendingReplay();
|
||||
audioBroadcaster.receive(audioRecording);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
@@ -23,6 +26,7 @@ import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -51,6 +55,7 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
private BroadcastModel mBroadcastModel;
|
||||
private AliasModel mAliasModel;
|
||||
private IconManager mIconManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||
private JideSplitPane mSplitPane;
|
||||
@@ -60,12 +65,14 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
private JButton mCopyButton = new JButton(COPY_BROADCAST_CONFIGURATION);
|
||||
private JButton mDeleteButton = new JButton(DELETE_BROADCAST_CONFIGURATION);
|
||||
|
||||
public BroadcastPanel(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager)
|
||||
public BroadcastPanel(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
mBroadcastModel = broadcastModel;
|
||||
mAliasModel = aliasModel;
|
||||
mIconManager = iconManager;
|
||||
mEditor = mEmptyEditor;
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -74,7 +81,8 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel);
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel, mUserPreferences,
|
||||
"broadcast.panel.broadcast.status.panel");
|
||||
|
||||
mBroadcastStatusPanel.getTable().setAutoCreateRowSorter(true);
|
||||
mBroadcastStatusPanel.getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
@@ -210,8 +218,8 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
|
||||
if (selectedConfiguration != null)
|
||||
{
|
||||
mEditor = BroadcastFactory.getEditor(selectedConfiguration, mBroadcastModel, mAliasModel,
|
||||
mIconManager);
|
||||
mEditor = BroadcastFactory.getEditor(mUserPreferences, selectedConfiguration, mBroadcastModel,
|
||||
mAliasModel, mIconManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -70,6 +70,11 @@ public enum BroadcastState
|
||||
*/
|
||||
MOUNT_POINT_IN_USE("Mount Point In Use", false),
|
||||
|
||||
/**
|
||||
* Network is unavailable or the server address cannot be resolved
|
||||
*/
|
||||
NETWORK_UNAVAILABLE("Network Unavailable", false),
|
||||
|
||||
/**
|
||||
* Server is not known or reachable
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,25 +15,37 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
|
||||
public class BroadcastStatusPanel extends JPanel
|
||||
{
|
||||
private JTable mTable;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
private JScrollPane mScrollPane;
|
||||
private BroadcastModel mBroadcastModel;
|
||||
private UserPreferences mUserPreferences;
|
||||
private String mPreferenceKey;
|
||||
|
||||
public BroadcastStatusPanel(BroadcastModel broadcastModel)
|
||||
public BroadcastStatusPanel(BroadcastModel broadcastModel, UserPreferences userPreferences, String preferenceKey)
|
||||
{
|
||||
mBroadcastModel = broadcastModel;
|
||||
mUserPreferences = userPreferences;
|
||||
mPreferenceKey = preferenceKey;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -52,6 +65,7 @@ public class BroadcastStatusPanel extends JPanel
|
||||
renderer.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
mTable.getColumnModel().getColumn(BroadcastModel.COLUMN_BROADCASTER_STATUS).setCellRenderer(new StatusCellRenderer());
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, mPreferenceKey);
|
||||
|
||||
mScrollPane = new JScrollPane(mTable);
|
||||
|
||||
@@ -96,7 +110,8 @@ public class BroadcastStatusPanel extends JPanel
|
||||
setBackground(table.getBackground());
|
||||
setForeground(Color.LIGHT_GRAY);
|
||||
}
|
||||
else if(state == BroadcastState.INVALID_SETTINGS)
|
||||
else if(state == BroadcastState.INVALID_SETTINGS ||
|
||||
state == BroadcastState.NETWORK_UNAVAILABLE)
|
||||
{
|
||||
setBackground(Color.YELLOW);
|
||||
setForeground(table.getForeground());
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
|
||||
public interface IBroadcastMetadataUpdater
|
||||
{
|
||||
/**
|
||||
* Updates broadcast audio metadata
|
||||
*
|
||||
* @param metadata containing metadata attributes
|
||||
* @param identifierCollection containing metadata attributes
|
||||
*/
|
||||
void update(Metadata metadata);
|
||||
void update(IdentifierCollection identifierCollection);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -14,19 +15,19 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.audio.AudioPacket;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.AudioRecorder;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import io.github.dsheirer.util.TimeStamp;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -37,7 +38,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class StreamManager implements Listener<AudioPacket>
|
||||
public class StreamManager implements Listener<ReusableAudioPacket>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(StreamManager.class);
|
||||
private static final long MAXIMUM_RECORDER_LIFESPAN_MILLIS = 30000; //30 seconds
|
||||
@@ -46,7 +47,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
|
||||
private Listener<AudioRecording> mAudioRecordingListener;
|
||||
private BroadcastFormat mBroadcastFormat;
|
||||
private Path mTempDirectory;
|
||||
private UserPreferences mUserPreferences;
|
||||
private Map<Integer,AudioRecorder> mStreamRecorders = new HashMap<>();
|
||||
private Runnable mRecorderMonitor;
|
||||
private ScheduledFuture<?> mRecorderMonitorFuture;
|
||||
@@ -61,15 +62,14 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
* Completed streamable audio recordings are nominated to the output listener (for broadcast) upon completion
|
||||
*
|
||||
* @param listener to receive completed audio recordings
|
||||
* @param tempDirectory where to store temporary audio recordings
|
||||
* @param broadcastFormat for the stream
|
||||
* @param userPreferences to obtain the temporary streaming recording directory
|
||||
*/
|
||||
public StreamManager(Listener<AudioRecording> listener, BroadcastFormat broadcastFormat, Path tempDirectory)
|
||||
public StreamManager(Listener<AudioRecording> listener, BroadcastFormat broadcastFormat, UserPreferences userPreferences)
|
||||
{
|
||||
assert (tempDirectory != null && Files.isDirectory(tempDirectory));
|
||||
|
||||
mAudioRecordingListener = listener;
|
||||
mBroadcastFormat = broadcastFormat;
|
||||
mTempDirectory = tempDirectory;
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,17 +115,17 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
public void receive(ReusableAudioPacket audioPacket)
|
||||
{
|
||||
if(mRunning.get() && audioPacket.hasMetadata())
|
||||
if(mRunning.get() && audioPacket.hasIdentifierCollection())
|
||||
{
|
||||
synchronized(mStreamRecorders)
|
||||
{
|
||||
int channelMetadataID = audioPacket.getMetadata().getMetadataID();
|
||||
int channelMetadataID = audioPacket.getAudioChannelId();
|
||||
|
||||
AudioPacket.Type type = audioPacket.getType();
|
||||
ReusableAudioPacket.Type type = audioPacket.getType();
|
||||
|
||||
if(type == AudioPacket.Type.AUDIO)
|
||||
if(type == ReusableAudioPacket.Type.AUDIO)
|
||||
{
|
||||
if(mStreamRecorders.containsKey(channelMetadataID))
|
||||
{
|
||||
@@ -133,19 +133,20 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
|
||||
if(recorder != null)
|
||||
{
|
||||
audioPacket.incrementUserCount();
|
||||
recorder.receive(audioPacket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
|
||||
mBroadcastFormat);
|
||||
recorder.start(ThreadPool.SCHEDULED);
|
||||
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(), mBroadcastFormat);
|
||||
recorder.start();
|
||||
audioPacket.incrementUserCount();
|
||||
recorder.receive(audioPacket);
|
||||
mStreamRecorders.put(channelMetadataID, recorder);
|
||||
}
|
||||
}
|
||||
else if(type == AudioPacket.Type.END)
|
||||
else if(type == ReusableAudioPacket.Type.END)
|
||||
{
|
||||
removeRecorder(channelMetadataID);
|
||||
}
|
||||
@@ -155,6 +156,8 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audioPacket.decrementUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,7 +180,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
public void receive(AudioRecorder audioRecorder)
|
||||
{
|
||||
AudioRecording audioRecording =
|
||||
new AudioRecording(audioRecorder.getPath(), audioRecorder.getMetadata(),
|
||||
new AudioRecording(audioRecorder.getPath(), audioRecorder.getIdentifierCollection(),
|
||||
audioRecorder.getTimeRecordingStart(), audioRecorder.getRecordingLength());
|
||||
|
||||
if(mAudioRecordingListener != null)
|
||||
@@ -201,7 +204,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
sb.append(TimeStamp.getLongTimeStamp("_"));
|
||||
sb.append(mBroadcastFormat.getFileExtension());
|
||||
|
||||
Path temporaryRecordingPath = mTempDirectory.resolve(sb.toString());
|
||||
Path temporaryRecordingPath = mUserPreferences.getDirectoryPreference().getDirectoryStreaming().resolve(sb.toString());
|
||||
|
||||
return temporaryRecordingPath;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.broadcastify;
|
||||
|
||||
import com.radioreference.api.soap2.UserFeedBroadcast;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfigurationEditor;
|
||||
@@ -26,6 +28,8 @@ import io.github.dsheirer.audio.broadcast.BroadcastEvent;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.UserFeedBroadcast;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
@@ -64,10 +68,13 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
||||
private JCheckBox mEnabled;
|
||||
private JButton mSaveButton;
|
||||
private JButton mResetButton;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
public BroadcastifyConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager)
|
||||
public BroadcastifyConfigurationEditor(UserPreferences userPreferences, BroadcastModel broadcastModel,
|
||||
AliasModel aliasModel, IconManager iconManager)
|
||||
{
|
||||
super(broadcastModel, aliasModel, iconManager);
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -91,7 +98,7 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
final UserFeedSelectionDialog dialog = new UserFeedSelectionDialog(BroadcastifyConfigurationEditor.this);
|
||||
final UserFeedSelectionDialog dialog = new UserFeedSelectionDialog(mUserPreferences,BroadcastifyConfigurationEditor.this);
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@@ -391,7 +398,7 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
||||
@Override
|
||||
public void receive(UserFeedBroadcast userFeedBroadcast)
|
||||
{
|
||||
mName.setText(userFeedBroadcast.getDescr());
|
||||
mName.setText(userFeedBroadcast.getDescription());
|
||||
mServer.setText(userFeedBroadcast.getHostname());
|
||||
mPort.setText(userFeedBroadcast.getPort());
|
||||
mMountPoint.setText(userFeedBroadcast.getMount());
|
||||
|
||||
@@ -1,78 +1,155 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.broadcastify;
|
||||
|
||||
import com.radioreference.api.soap2.UserFeedBroadcast;
|
||||
import io.github.dsheirer.radioreference.RadioReferenceService;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceService;
|
||||
import io.github.dsheirer.rrapi.type.AuthorizationInformation;
|
||||
import io.github.dsheirer.rrapi.type.UserFeedBroadcast;
|
||||
import io.github.dsheirer.rrapi.type.UserInfo;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.xml.rpc.ServiceException;
|
||||
import java.awt.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.UnknownHostException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
public class UserFeedSelectionDialog extends JDialog implements DocumentListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( UserFeedSelectionDialog.class );
|
||||
|
||||
public static final String SDRTRUNK_APP_KEY = "88969092";
|
||||
|
||||
private Listener<UserFeedBroadcast> mListener;
|
||||
private UserPreferences mUserPreferences;
|
||||
private JTextField mUserNameText;
|
||||
private JTextField mPasswordText;
|
||||
private JCheckBox mSaveCredentialsCheckBox;
|
||||
private JButton mClearStoredCredentialsButton;
|
||||
private JButton mLookupButton;
|
||||
private JList mUserFeedBroadcastList;
|
||||
private JButton mOKButton;
|
||||
|
||||
public UserFeedSelectionDialog(Listener<UserFeedBroadcast> listener)
|
||||
public UserFeedSelectionDialog(UserPreferences userPreferences, Listener<UserFeedBroadcast> listener)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mListener = listener;
|
||||
|
||||
//Register to receive radio reference preferences updates
|
||||
MyEventBus.getEventBus().register(this);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new MigLayout("","[align right,grow,fill][align left,grow,fill][]","[][][][][grow][]"));
|
||||
panel.setLayout(new MigLayout("","[align right,grow,fill][align left,grow,fill][]","[][][][][][grow][]"));
|
||||
|
||||
panel.add(new JLabel("Please enter your credentials"), "align left,span");
|
||||
|
||||
panel.add(new JLabel("User Name:"));
|
||||
mUserNameText = new JTextField();
|
||||
String storedUserName = mUserPreferences.getRadioReferencePreference().getUserName();
|
||||
if(storedUserName != null)
|
||||
{
|
||||
mUserNameText.setText(storedUserName);
|
||||
}
|
||||
mUserNameText.getDocument().addDocumentListener(this);
|
||||
panel.add(mUserNameText, "wrap");
|
||||
|
||||
panel.add(new JLabel("Password:"));
|
||||
mPasswordText = new JTextField();
|
||||
String storedPassword = mUserPreferences.getRadioReferencePreference().getPassword();
|
||||
if(storedPassword != null)
|
||||
{
|
||||
mPasswordText.setText(storedPassword);
|
||||
}
|
||||
mPasswordText.getDocument().addDocumentListener(this);
|
||||
panel.add(mPasswordText, "wrap");
|
||||
|
||||
mSaveCredentialsCheckBox = new JCheckBox("Store Credentials");
|
||||
mSaveCredentialsCheckBox.setSelected(mUserPreferences.getRadioReferencePreference().isStoreCredentials());
|
||||
mSaveCredentialsCheckBox.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
//If user unchecks box and there are stored credentials, prompt to clear them
|
||||
if(!mSaveCredentialsCheckBox.isSelected() && mUserPreferences.getRadioReferencePreference().hasStoredCredentials())
|
||||
{
|
||||
int choice = JOptionPane.showOptionDialog(UserFeedSelectionDialog.this,
|
||||
"Would you like to remove previously stored credentials from this computer?",
|
||||
"Clear Stored Credentials?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, 0);
|
||||
|
||||
if(choice == JOptionPane.YES_OPTION)
|
||||
{
|
||||
mUserPreferences.getRadioReferencePreference().removeStoreCredentials();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
panel.add(mSaveCredentialsCheckBox);
|
||||
|
||||
mClearStoredCredentialsButton = new JButton("Remove");
|
||||
mClearStoredCredentialsButton.setToolTipText("Clear stored credentials");
|
||||
mClearStoredCredentialsButton.setEnabled(mUserPreferences.getRadioReferencePreference().hasStoredCredentials());
|
||||
mClearStoredCredentialsButton.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
mUserPreferences.getRadioReferencePreference().removeStoreCredentials();
|
||||
}
|
||||
});
|
||||
panel.add(mClearStoredCredentialsButton, "wrap");
|
||||
|
||||
mLookupButton = new JButton("Get Feeds");
|
||||
mLookupButton.setEnabled(false);
|
||||
mLookupButton.setEnabled(storedPassword != null && storedPassword != null);
|
||||
mLookupButton.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
@@ -87,45 +164,25 @@ public class UserFeedSelectionDialog extends JDialog implements DocumentListener
|
||||
{
|
||||
try
|
||||
{
|
||||
RadioReferenceService service =
|
||||
new RadioReferenceService(mUserNameText.getText(), mPasswordText.getText());
|
||||
AuthorizationInformation authorizationInformation = new AuthorizationInformation(SDRTRUNK_APP_KEY,
|
||||
mUserNameText.getText(), mPasswordText.getText());
|
||||
|
||||
UserFeedBroadcast[] feeds = service.getUserFeedBroadcasts();
|
||||
mLog.debug("User:" + authorizationInformation.getUserName() + " Pass:" + authorizationInformation.getPassword() + " Key:" + authorizationInformation.getApplicationKey());
|
||||
|
||||
mUserFeedBroadcastList.setListData(feeds);
|
||||
RadioReferenceService service = new RadioReferenceService(authorizationInformation);
|
||||
UserInfo userInfo = service.getUserInfo();
|
||||
mLog.info("RR User:" + userInfo.getUserName() + " Expiration Date:" + userInfo.getExpirationDate());
|
||||
List<UserFeedBroadcast> feeds = service.getUserFeeds();
|
||||
|
||||
mUserFeedBroadcastList.setListData(feeds.toArray(new UserFeedBroadcast[feeds.size()]));
|
||||
}
|
||||
catch(ServiceException se)
|
||||
catch(RadioReferenceException rre)
|
||||
{
|
||||
JOptionPane.showMessageDialog(UserFeedSelectionDialog.this,
|
||||
"Unable to create radio reference web service client. See log file.",
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
mLog.error("Error creating the radio reference web service client", se);
|
||||
}
|
||||
catch(RemoteException re)
|
||||
{
|
||||
Throwable cause = re.getCause();
|
||||
|
||||
if(cause == null)
|
||||
{
|
||||
JOptionPane.showMessageDialog(UserFeedSelectionDialog.this,
|
||||
re.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else if(cause instanceof UnknownHostException)
|
||||
{
|
||||
JOptionPane.showMessageDialog(UserFeedSelectionDialog.this,
|
||||
"Broadcastify server is unavailable", "No Server",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
JOptionPane.showMessageDialog(UserFeedSelectionDialog.this,
|
||||
"An unknown error has occurred. Please see log file.", "" +
|
||||
"Unknown Error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
mLog.error("Error retrieving user broadcast feed configurations from radio reference " +
|
||||
"service: ", re);
|
||||
}
|
||||
mLog.error("Error creating the radio reference web service client", rre);
|
||||
}
|
||||
|
||||
mLookupButton.setEnabled(true);
|
||||
@@ -160,6 +217,7 @@ public class UserFeedSelectionDialog extends JDialog implements DocumentListener
|
||||
{
|
||||
if(mListener != null)
|
||||
{
|
||||
storeCredentials();
|
||||
mListener.receive((UserFeedBroadcast)mUserFeedBroadcastList.getSelectedValue());
|
||||
}
|
||||
|
||||
@@ -182,11 +240,37 @@ public class UserFeedSelectionDialog extends JDialog implements DocumentListener
|
||||
setTitle("Broadcastify Feed Lookup");
|
||||
setLayout(new BorderLayout());
|
||||
add(panel, BorderLayout.CENTER);
|
||||
setSize(300,250);
|
||||
setSize(400,450);
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores login credentials in the user preferences
|
||||
*/
|
||||
private void storeCredentials()
|
||||
{
|
||||
boolean store = mSaveCredentialsCheckBox.isSelected();
|
||||
mUserPreferences.getRadioReferencePreference().setStoreCredentials(store);
|
||||
|
||||
if(store)
|
||||
{
|
||||
String userName = mUserNameText.getText();
|
||||
|
||||
if(userName != null)
|
||||
{
|
||||
mUserPreferences.getRadioReferencePreference().setUserName(userName);
|
||||
}
|
||||
|
||||
String password = mPasswordText.getText();
|
||||
|
||||
if(password != null)
|
||||
{
|
||||
mUserPreferences.getRadioReferencePreference().setPassword(password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtons()
|
||||
{
|
||||
String username = mUserNameText.getText();
|
||||
@@ -240,8 +324,20 @@ public class UserFeedSelectionDialog extends JDialog implements DocumentListener
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
|
||||
setText(value.getDescr());
|
||||
setText(value.getDescription());
|
||||
|
||||
return this; }
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void preferenceUpdated(PreferenceType preferenceType)
|
||||
{
|
||||
if(preferenceType == PreferenceType.RADIO_REFERENCE)
|
||||
{
|
||||
//Update the store-credentials checkbox only, so we don't change the username or password currently displayed
|
||||
mSaveCredentialsCheckBox.setSelected(mUserPreferences.getRadioReferencePreference().isStoreCredentials());
|
||||
mClearStoredCredentialsButton.setEnabled(mUserPreferences.getRadioReferencePreference().hasStoredCredentials());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
@@ -25,10 +26,12 @@ import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
private IBroadcastMetadataUpdater mMetadataUpdater;
|
||||
private AliasModel mAliasModel;
|
||||
|
||||
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
|
||||
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, AliasModel aliasModel)
|
||||
{
|
||||
super(broadcastConfiguration);
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +47,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
if(mMetadataUpdater == null)
|
||||
{
|
||||
mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration());
|
||||
mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration(), mAliasModel);
|
||||
}
|
||||
|
||||
return mMetadataUpdater;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -14,14 +15,23 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@@ -35,11 +45,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
@@ -52,7 +62,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
private final static String UTF8 = "UTF-8";
|
||||
|
||||
private IcecastConfiguration mIcecastConfiguration;
|
||||
|
||||
private AliasModel mAliasModel;
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private AtomicBoolean mUpdating = new AtomicBoolean();
|
||||
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
|
||||
@@ -65,9 +75,10 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
|
||||
* sequence, those updates will be queued and processed in the order received.
|
||||
*/
|
||||
public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration)
|
||||
public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration, AliasModel aliasModel)
|
||||
{
|
||||
mIcecastConfiguration = icecastConfiguration;
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,119 +124,122 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
* and will remain in the update queue until the next metadata update is requested. However, this is a design
|
||||
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
|
||||
*/
|
||||
public void update(Metadata metadata)
|
||||
public void update(IdentifierCollection identifierCollection)
|
||||
{
|
||||
mMetadataQueue.offer(getSong(metadata));
|
||||
mMetadataQueue.offer(getSong(identifierCollection));
|
||||
|
||||
if(mUpdating.compareAndSet(false, true))
|
||||
if(!mUpdating.get() && !mMetadataQueue.isEmpty())
|
||||
{
|
||||
String song = mMetadataQueue.poll();
|
||||
|
||||
while(song != null)
|
||||
Runnable runnable = new Runnable()
|
||||
{
|
||||
HttpRequest updateRequest = createUpdateRequest(song);
|
||||
|
||||
if(updateRequest != null)
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ThreadPool.SCHEDULED.schedule(new Runnable()
|
||||
if(!mMetadataQueue.isEmpty() && mUpdating.compareAndSet(false, true))
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
ConnectFuture connectFuture = getSocketConnector()
|
||||
.connect(new InetSocketAddress(mIcecastConfiguration.getHost(),
|
||||
mIcecastConfiguration.getPort()));
|
||||
connectFuture.awaitUninterruptibly();
|
||||
IoSession session = connectFuture.getSession();
|
||||
ConnectFuture connectFuture = getSocketConnector()
|
||||
.connect(new InetSocketAddress(mIcecastConfiguration.getHost(),
|
||||
mIcecastConfiguration.getPort()));
|
||||
connectFuture.awaitUninterruptibly();
|
||||
IoSession session = connectFuture.getSession();
|
||||
|
||||
if(session != null)
|
||||
{
|
||||
session.write(updateRequest);
|
||||
}
|
||||
}
|
||||
catch(UnresolvedAddressException uae)
|
||||
if(session != null)
|
||||
{
|
||||
//Do nothing - the server is temporarily unavailable
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Throwable throwableCause = e.getCause();
|
||||
String song = mMetadataQueue.poll();
|
||||
|
||||
if(throwableCause instanceof ConnectException)
|
||||
while(song != null)
|
||||
{
|
||||
//Do nothing, the server is unavailable
|
||||
}
|
||||
else if(throwableCause instanceof UnresolvedAddressException)
|
||||
{
|
||||
//Do nothing - the server is temporarily unavailable
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!mStackTraceLoggingSuppressed)
|
||||
HttpRequest updateRequest = createUpdateRequest(song);
|
||||
|
||||
if(updateRequest != null)
|
||||
{
|
||||
mLog.error("Error sending metadata update. Future errors will " +
|
||||
"be suppressed", e);
|
||||
|
||||
mStackTraceLoggingSuppressed = true;
|
||||
session.write(updateRequest);
|
||||
}
|
||||
|
||||
//Fetch next metadata update to send
|
||||
song = mMetadataQueue.poll();
|
||||
}
|
||||
|
||||
session.closeNow();
|
||||
}
|
||||
}
|
||||
}, 0l, TimeUnit.SECONDS);
|
||||
catch(UnresolvedAddressException | RuntimeIoException ure)
|
||||
{
|
||||
//Do nothing - the server is temporarily unavailable
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Throwable throwableCause = e.getCause();
|
||||
|
||||
if(!mStackTraceLoggingSuppressed)
|
||||
{
|
||||
mLog.error("Error sending metadata update. Future errors will be suppressed", e);
|
||||
mStackTraceLoggingSuppressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
mUpdating.set(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Fetch next metadata update to send
|
||||
song = mMetadataQueue.poll();
|
||||
}
|
||||
|
||||
mUpdating.set(false);
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the song information for a metadata update
|
||||
*/
|
||||
private static String getSong(Metadata metadata)
|
||||
private String getSong(IdentifierCollection identifierCollection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(metadata != null)
|
||||
if(identifierCollection != null)
|
||||
{
|
||||
String to = metadata.getPrimaryAddressTo().getIdentifier();
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
sb.append("TO:");
|
||||
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
||||
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
if(to == null)
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
|
||||
sb.append("TO:").append(to);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(to);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
sb.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
|
||||
sb.append(" FROM:");
|
||||
if(from != null)
|
||||
{
|
||||
sb.append(" FROM:").append(from);
|
||||
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
|
||||
List<Alias> aliases = aliasList.getAliases(from);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
sb.append(" FROM:UNKNOWN");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 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.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
@@ -29,11 +33,9 @@ import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.ProtocolDecoderException;
|
||||
import org.apache.mina.http.HttpClientCodec;
|
||||
import org.apache.mina.http.HttpException;
|
||||
import org.apache.mina.http.HttpRequestImpl;
|
||||
import org.apache.mina.http.api.DefaultHttpResponse;
|
||||
import org.apache.mina.http.api.HttpMethod;
|
||||
import org.apache.mina.http.api.HttpStatus;
|
||||
import org.apache.mina.http.api.HttpVersion;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
@@ -50,6 +52,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(IcecastHTTPAudioBroadcaster.class);
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
private static final String HTTP_1_0_OK_HEX_DUMP = "48 54 54 50 2F 31 2E 30 20 32 30 30 20 4F 4B";
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
@@ -69,9 +72,9 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Icecast stream
|
||||
*/
|
||||
public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration)
|
||||
public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration, AliasModel aliasModel)
|
||||
{
|
||||
super(configuration);
|
||||
super(configuration, aliasModel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +115,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
mSocketConnector.setConnectTimeoutCheckInterval(10000);
|
||||
|
||||
// mSocketConnector.getFilterChain().addLast("logger",
|
||||
// new LoggingFilter(IcecastTCPAudioBroadcaster.class));
|
||||
// new LoggingFilter(IcecastHTTPAudioBroadcaster.class));
|
||||
|
||||
mSocketConnector.getFilterChain().addLast("codec", new HttpClientCodec());
|
||||
mSocketConnector.setHandler(new IcecastHTTPIOHandler());
|
||||
@@ -145,12 +148,12 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
}
|
||||
else if(throwableCause != null)
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
setBroadcastState(BroadcastState.DISCONNECTED);
|
||||
mLog.debug("Failed to connect", rie);
|
||||
}
|
||||
else
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
setBroadcastState(BroadcastState.DISCONNECTED);
|
||||
mLog.debug("Failed to connect - no exception is available");
|
||||
}
|
||||
|
||||
@@ -265,25 +268,30 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
if(throwable instanceof ProtocolDecoderException)
|
||||
{
|
||||
Throwable cause = ((ProtocolDecoderException) throwable).getCause();
|
||||
Throwable cause = throwable.getCause();
|
||||
|
||||
if(cause instanceof HttpException &&
|
||||
((HttpException) cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
|
||||
/**
|
||||
* Warning: Hack. Icecast 2.4.2+ doesn't like to send HTTP headers along with their HTTP/1.0 OK
|
||||
* message which causes Apache Mina to think that it hasn't received the full HTTP response. So, we
|
||||
* intercept the out of bounds exception and then inspect the message hex dump to see if it's an
|
||||
* OK response and then play like everything is well and good.
|
||||
*/
|
||||
if(cause instanceof ArrayIndexOutOfBoundsException &&
|
||||
((ProtocolDecoderException)throwable).getHexdump().startsWith(HTTP_1_0_OK_HEX_DUMP))
|
||||
{
|
||||
//Ignore - Icecast 2.4 sometimes doesn't send any headers with their HTTP responses. Mina expects a
|
||||
//content-length for HTTP responses.
|
||||
setBroadcastState(BroadcastState.CONNECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("HTTP protocol decoder error", throwable);
|
||||
setBroadcastState(BroadcastState.TEMPORARY_BROADCAST_ERROR);
|
||||
setBroadcastState(BroadcastState.DISCONNECTED);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Broadcast error", throwable);
|
||||
setBroadcastState(BroadcastState.TEMPORARY_BROADCAST_ERROR);
|
||||
setBroadcastState(BroadcastState.DISCONNECTED);
|
||||
disconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
|
||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||
@@ -27,15 +28,14 @@ import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.core.write.WriteTimeoutException;
|
||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -46,7 +46,8 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
private final static String TERMINATOR = "\r\n";
|
||||
private final static String SEPARATOR = ":";
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 3000; //3 seconds
|
||||
private static final long CONNECTION_ATTEMPT_TIMEOUT = 5000; //5 seconds
|
||||
private static final long CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS = 5000; //5 seconds
|
||||
private static final int WRITE_TIMEOUT_SECONDS = 5;
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
@@ -65,9 +66,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Icecast stream
|
||||
*/
|
||||
public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration)
|
||||
public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration, AliasModel aliasModel)
|
||||
{
|
||||
super(configuration);
|
||||
super(configuration, aliasModel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
if(mSocketConnector == null)
|
||||
{
|
||||
mSocketConnector = new NioSocketConnector();
|
||||
mSocketConnector.setConnectTimeoutCheckInterval(CONNECTION_ATTEMPT_TIMEOUT);
|
||||
mSocketConnector.getSessionConfig().setWriteTimeout(WRITE_TIMEOUT_SECONDS);
|
||||
|
||||
// LoggingFilter loggingFilter = new LoggingFilter(IcecastTCPAudioBroadcaster.class);
|
||||
// loggingFilter.setMessageSentLogLevel(LogLevel.NONE);
|
||||
@@ -127,45 +128,41 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
.connect(new InetSocketAddress(getBroadcastConfiguration().getHost(),
|
||||
getBroadcastConfiguration().getPort()));
|
||||
|
||||
boolean connected = future.await(CONNECTION_ATTEMPT_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
boolean connected = future.await(CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS);
|
||||
|
||||
mStreamingSession = future.getSession();
|
||||
if(connected)
|
||||
{
|
||||
mStreamingSession = future.getSession();
|
||||
mConnecting.set(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(RuntimeIoException rioe)
|
||||
{
|
||||
if(rioe.getCause() instanceof SocketException)
|
||||
{
|
||||
setBroadcastState(BroadcastState.NETWORK_UNAVAILABLE);
|
||||
mConnecting.set(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(UnresolvedAddressException uae)
|
||||
{
|
||||
//What do you do with this? Nothing.
|
||||
setBroadcastState(BroadcastState.NETWORK_UNAVAILABLE);
|
||||
mConnecting.set(false);
|
||||
return;
|
||||
}
|
||||
catch(InterruptedException ie)
|
||||
catch(Exception e)
|
||||
{
|
||||
//We couldn't connect within the timeout period -- disconnect so that we can try again later
|
||||
disconnect();
|
||||
}
|
||||
catch(RuntimeIoException rie)
|
||||
{
|
||||
Throwable throwableCause = rie.getCause();
|
||||
|
||||
if(throwableCause instanceof ConnectException)
|
||||
{
|
||||
setBroadcastState(BroadcastState.NO_SERVER);
|
||||
}
|
||||
else if(throwableCause != null)
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
mLog.debug("[" + getStreamName() + "] failed to connect", rie);
|
||||
}
|
||||
else
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
mLog.debug("[" + getStreamName() + "] failed to connect - no exception is available");
|
||||
}
|
||||
|
||||
disconnect();
|
||||
mLog.error("Error", e);
|
||||
//Disregard ... we'll disconnect and try again
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
disconnect();
|
||||
mLog.error("Throwable error caught", t);
|
||||
}
|
||||
|
||||
disconnect();
|
||||
mConnecting.set(false);
|
||||
}
|
||||
};
|
||||
@@ -188,6 +185,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
}
|
||||
else
|
||||
{
|
||||
setBroadcastState(BroadcastState.DISCONNECTED);
|
||||
mLastConnectionAttempt = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -263,49 +261,12 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
|
||||
{
|
||||
if(cause instanceof IOException)
|
||||
{
|
||||
IOException ioe = (IOException)cause;
|
||||
|
||||
if(ioe.getMessage() != null)
|
||||
{
|
||||
String reason = ioe.getMessage();
|
||||
|
||||
if(connected())
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
else if(reason.startsWith("Connection reset"))
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
else if(reason.startsWith("Operation timed out"))
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
else if(ioe instanceof WriteTimeoutException)
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
disconnect();
|
||||
mLog.error("[" + getStreamName() + "] Unspecified IO error - streaming halted.", cause);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!(cause instanceof IOException))
|
||||
{
|
||||
mLog.error("[" + getStreamName() + "] Broadcast error", cause);
|
||||
setBroadcastState(BroadcastState.ERROR);
|
||||
disconnect();
|
||||
}
|
||||
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.audio.broadcast.shoutcast.v1;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
@@ -47,7 +48,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
private IBroadcastMetadataUpdater mMetadataUpdater;
|
||||
|
||||
private AliasModel mAliasModel;
|
||||
private long mLastConnectionAttempt = 0;
|
||||
private AtomicBoolean mConnecting = new AtomicBoolean();
|
||||
|
||||
@@ -61,9 +62,10 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Shoutcast stream
|
||||
*/
|
||||
public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration)
|
||||
public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration, AliasModel aliasModel)
|
||||
{
|
||||
super(configuration);
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +81,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
if(mMetadataUpdater == null)
|
||||
{
|
||||
mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration());
|
||||
mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration(), mAliasModel);
|
||||
}
|
||||
|
||||
return mMetadataUpdater;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -14,12 +15,20 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.shoutcast.v1;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
@@ -38,6 +47,7 @@ import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
@@ -50,7 +60,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
private final static String UTF8 = "UTF-8";
|
||||
|
||||
private ShoutcastV1Configuration mShoutcastV1Configuration;
|
||||
|
||||
private AliasModel mAliasModel;
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private AtomicBoolean mUpdating = new AtomicBoolean();
|
||||
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
|
||||
@@ -62,9 +72,10 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
|
||||
* sequence, those updates will be queued and processed in the order received.
|
||||
*/
|
||||
public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration)
|
||||
public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration, AliasModel aliasModel)
|
||||
{
|
||||
mShoutcastV1Configuration = shoutcastV1Configuration;
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,9 +122,9 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
* and will remain in the update queue until the next metadata update is requested. However, this is a design
|
||||
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
|
||||
*/
|
||||
public void update(Metadata metadata)
|
||||
public void update(IdentifierCollection identifierCollection)
|
||||
{
|
||||
mMetadataQueue.offer(getSong(metadata));
|
||||
mMetadataQueue.offer(getSong(identifierCollection));
|
||||
|
||||
if(mUpdating.compareAndSet(false, true))
|
||||
{
|
||||
@@ -177,45 +188,54 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
/**
|
||||
* Creates the song information for a metadata update
|
||||
*/
|
||||
private static String getSong(Metadata metadata)
|
||||
private String getSong(IdentifierCollection identifierCollection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(metadata != null)
|
||||
if(identifierCollection != null)
|
||||
{
|
||||
String to = metadata.getPrimaryAddressTo().getIdentifier();
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
sb.append("TO:");
|
||||
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
||||
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
if(to == null)
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
|
||||
sb.append("TO:").append(to);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(to);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
sb.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
|
||||
sb.append(" FROM:");
|
||||
if(from != null)
|
||||
{
|
||||
sb.append(" FROM:").append(from);
|
||||
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
|
||||
List<Alias> aliases = aliasList.getAliases(from);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
sb.append(" FROM:UNKNOWN");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -14,10 +15,14 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.audio.broadcast.shoutcast.v2;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||
@@ -36,7 +41,11 @@ import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageF
|
||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
|
||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
|
||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
|
||||
import io.github.dsheirer.channel.metadata.Metadata;
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
@@ -66,7 +75,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
|
||||
private AliasModel mAliasModel;
|
||||
private long mLastConnectionAttempt = 0;
|
||||
private AtomicBoolean mConnecting = new AtomicBoolean();
|
||||
private LinkedTransferQueue<UltravoxMessage> mMetadataMessageQueue = new LinkedTransferQueue<>();
|
||||
@@ -83,9 +92,10 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
*
|
||||
* @param configuration for the Shoutcast V2 stream
|
||||
*/
|
||||
public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration)
|
||||
public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration, AliasModel aliasModel)
|
||||
{
|
||||
super(configuration);
|
||||
mAliasModel = aliasModel;
|
||||
}
|
||||
|
||||
public ShoutcastV2Configuration getConfiguration()
|
||||
@@ -119,9 +129,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Metadata metadata)
|
||||
public void update(IdentifierCollection identifierCollection)
|
||||
{
|
||||
List<UltravoxMessage> metadataMessages = getMetadataMessages(metadata);
|
||||
List<UltravoxMessage> metadataMessages = getMetadataMessages(identifierCollection);
|
||||
|
||||
if(!metadataMessages.isEmpty())
|
||||
{
|
||||
@@ -241,10 +251,10 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
*
|
||||
* See UltravoxMetadata.TAG.asXML(String value)
|
||||
*
|
||||
* @param metadata containing audio metadata tags and attributes
|
||||
* @param identifierCollection containing audio metadata tags and attributes
|
||||
* @return a sequence of CacheableXMLMetadata messages sufficient to carry the complete set of metadata
|
||||
*/
|
||||
private List<UltravoxMessage> getMetadataMessages(Metadata metadata)
|
||||
private List<UltravoxMessage> getMetadataMessages(IdentifierCollection identifierCollection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -266,24 +276,49 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
sb.append(UltravoxMetadata.URL.asXML(getConfiguration().getURL()));
|
||||
}
|
||||
|
||||
if(metadata != null)
|
||||
if(identifierCollection != null)
|
||||
{
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
|
||||
|
||||
if(to == null)
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName()));
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
|
||||
to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
|
||||
}
|
||||
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
if(to != null)
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName()));
|
||||
sb.append("TO:").append(to);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(to);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
else
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier()));
|
||||
sb.append("TO:UNKNOWN");
|
||||
}
|
||||
|
||||
Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
sb.append(" FROM:").append(from);
|
||||
|
||||
List<Alias> aliases = aliasList.getAliases(from);
|
||||
|
||||
if(!aliases.isEmpty())
|
||||
{
|
||||
sb.append(" ").append(Joiner.on(", ").skipNulls().join(aliases));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(" FROM:UNKNOWN");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio.codec.mbe;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AmbeAudioModule extends JmbeAudioModule
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AmbeAudioModule.class);
|
||||
private static final String AMBE_CODEC = "AMBE 3600 x 2450";
|
||||
private static boolean sLibraryStatusLogged = false;
|
||||
|
||||
public AmbeAudioModule(UserPreferences userPreferences)
|
||||
{
|
||||
super(userPreferences);
|
||||
|
||||
if(!sLibraryStatusLogged)
|
||||
{
|
||||
if(getAudioCodec() != null)
|
||||
{
|
||||
mLog.info("AMBE CODEC successfully loaded - P25-2/DMR/NXDN audio will be available");
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn("AMBE CODEC not loaded - P25-2/DMR/NXDN audio will NOT be available");
|
||||
}
|
||||
|
||||
sLibraryStatusLogged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCodecName()
|
||||
{
|
||||
return AMBE_CODEC;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio.codec.mbe;
|
||||
|
||||
import io.github.dsheirer.identifier.encryption.EncryptionKeyIdentifier;
|
||||
|
||||
/**
|
||||
* P25 Encryption Parameters
|
||||
*/
|
||||
public interface IEncryptionSyncParameters
|
||||
{
|
||||
/**
|
||||
* Encryption key identifier
|
||||
*/
|
||||
EncryptionKeyIdentifier getEncryptionKey();
|
||||
|
||||
/**
|
||||
* Message Indicator
|
||||
* @return key generator fill values
|
||||
*/
|
||||
String getMessageIndicator();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.audio.codec.mbe;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ImbeAudioModule extends JmbeAudioModule
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(ImbeAudioModule.class);
|
||||
private static final String IMBE_CODEC = "IMBE";
|
||||
private static boolean sLibraryStatusLogged = false;
|
||||
|
||||
public ImbeAudioModule(UserPreferences userPreferences)
|
||||
{
|
||||
super(userPreferences);
|
||||
|
||||
if(!sLibraryStatusLogged)
|
||||
{
|
||||
if(getAudioCodec() != null)
|
||||
{
|
||||
mLog.info("JMBE audio conversion library IMBE CODEC successfully loaded - P25-1 audio will be available");
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn("JMBE audio conversion library, IMBE CODEC not loaded - P25-1 audio will NOT be available");
|
||||
}
|
||||
|
||||
sLibraryStatusLogged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCodecName()
|
||||
{
|
||||
return IMBE_CODEC;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user