mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
#90 [WIP] merged metadata management for channel state, decoder states and audio metadata into a new metadata class. The new metadata class is maintained for each decoding audio channel, or in the future, a decoding TDMA channel. Audio playback, recording and streaming all use the same metadata object for the channel. The list of channel processing gui panels have been deleted and channel processing status will now reside in a table where each table row is a metadata instance from the processing channel. The channel processing manager is responsible for adding/removing the channel's metadata instance to/from the metadata table. This allows the channel processing table to be the controller for the messages, events and channel spectrum views, keyed to the selected table row metadata.
I still have to clean up the gui components and wire in the table selection listeners.
This commit is contained in:
1
.idea/dictionaries/denny.xml
generated
1
.idea/dictionaries/denny.xml
generated
@@ -8,6 +8,7 @@
|
||||
<w>icecast</w>
|
||||
<w>ident</w>
|
||||
<w>polyphase</w>
|
||||
<w>remez</w>
|
||||
<w>samplerate</w>
|
||||
<w>sdrtrunk</w>
|
||||
<w>sheirer</w>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -14,6 +14,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 alias;
|
||||
|
||||
@@ -29,7 +30,6 @@ import alias.id.siteID.SiteID;
|
||||
import alias.id.status.StatusID;
|
||||
import alias.id.talkgroup.TalkgroupID;
|
||||
import alias.id.uniqueID.UniqueID;
|
||||
import audio.metadata.MetadataType;
|
||||
import module.decode.lj1200.LJ1200Message.Function;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -48,16 +48,16 @@ public class AliasList implements Listener<AliasEvent>
|
||||
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 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<>();
|
||||
@@ -85,9 +85,9 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
public void addAlias(Alias alias)
|
||||
{
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
for (AliasID aliasID : alias.getId())
|
||||
for(AliasID aliasID : alias.getId())
|
||||
{
|
||||
addAliasID(aliasID, alias);
|
||||
}
|
||||
@@ -99,18 +99,18 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
private void addAliasID(AliasID id, Alias alias)
|
||||
{
|
||||
if (id.isValid())
|
||||
if(id.isValid())
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (id.getType())
|
||||
switch(id.getType())
|
||||
{
|
||||
case ESN:
|
||||
String esn = ((Esn)id).getEsn();
|
||||
String esn = ((Esn) id).getEsn();
|
||||
|
||||
if(esn != null)
|
||||
{
|
||||
if (esn.contains(WILDCARD))
|
||||
if(esn.contains(WILDCARD))
|
||||
{
|
||||
mESNWildcards.add(new WildcardID(esn));
|
||||
Collections.sort(mESNWildcards);
|
||||
@@ -120,11 +120,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case FLEETSYNC:
|
||||
String fleetsync = ((FleetsyncID)id).getIdent();
|
||||
String fleetsync = ((FleetsyncID) id).getIdent();
|
||||
|
||||
if(fleetsync != null)
|
||||
{
|
||||
if (fleetsync.contains(WILDCARD))
|
||||
if(fleetsync.contains(WILDCARD))
|
||||
{
|
||||
mFleetsyncWildcards.add(new WildcardID(fleetsync));
|
||||
Collections.sort(mFleetsyncWildcards);
|
||||
@@ -137,11 +137,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
mLoJack.put((LoJackFunctionAndID) id, alias);
|
||||
break;
|
||||
case MDC1200:
|
||||
String mdc = ((MDC1200ID)id).getIdent();
|
||||
String mdc = ((MDC1200ID) id).getIdent();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
if (mdc.contains(WILDCARD))
|
||||
if(mdc.contains(WILDCARD))
|
||||
{
|
||||
mMDC1200Wildcards.add(new WildcardID(mdc));
|
||||
Collections.sort(mMDC1200Wildcards);
|
||||
@@ -151,11 +151,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case MPT1327:
|
||||
String mpt = ((MPT1327ID)id).getIdent();
|
||||
String mpt = ((MPT1327ID) id).getIdent();
|
||||
|
||||
if(mpt != null)
|
||||
{
|
||||
if (mpt.contains(WILDCARD))
|
||||
if(mpt.contains(WILDCARD))
|
||||
{
|
||||
mMPT1327Wildcards.add(new WildcardID(mpt));
|
||||
Collections.sort(mMPT1327Wildcards);
|
||||
@@ -165,11 +165,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case MIN:
|
||||
String min = ((Min)id).getMin();
|
||||
String min = ((Min) id).getMin();
|
||||
|
||||
if(min != null)
|
||||
{
|
||||
if (min.contains(WILDCARD))
|
||||
if(min.contains(WILDCARD))
|
||||
{
|
||||
mMobileIDWildcards.add(new WildcardID(min));
|
||||
Collections.sort(mMobileIDWildcards);
|
||||
@@ -179,14 +179,14 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case LTR_NET_UID:
|
||||
mUniqueID.put(((UniqueID)id).getUid(), alias);
|
||||
mUniqueID.put(((UniqueID) id).getUid(), alias);
|
||||
break;
|
||||
case SITE:
|
||||
String siteID = ((SiteID)id).getSite();
|
||||
String siteID = ((SiteID) id).getSite();
|
||||
|
||||
if(siteID != null)
|
||||
{
|
||||
if (siteID.contains(WILDCARD))
|
||||
if(siteID.contains(WILDCARD))
|
||||
{
|
||||
mSiteWildcards.add(new WildcardID(siteID));
|
||||
Collections.sort(mSiteWildcards);
|
||||
@@ -199,11 +199,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
mStatus.put(((StatusID) id).getStatus(), alias);
|
||||
break;
|
||||
case TALKGROUP:
|
||||
String tgid = ((TalkgroupID)id).getTalkgroup();
|
||||
String tgid = ((TalkgroupID) id).getTalkgroup();
|
||||
|
||||
if(tgid != null)
|
||||
{
|
||||
if (tgid.contains(WILDCARD))
|
||||
if(tgid.contains(WILDCARD))
|
||||
{
|
||||
mTalkgroupWildcards.add(new WildcardID(tgid));
|
||||
Collections.sort(mTalkgroupWildcards);
|
||||
@@ -222,7 +222,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't add alias ID " + id + " for alias " + alias);
|
||||
}
|
||||
@@ -234,9 +234,9 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
public void removeAlias(Alias alias)
|
||||
{
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
for (AliasID aliasID : alias.getId())
|
||||
for(AliasID aliasID : alias.getId())
|
||||
{
|
||||
removeAliasID(aliasID, alias);
|
||||
}
|
||||
@@ -247,7 +247,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
if(value != null)
|
||||
{
|
||||
for(WildcardID wildcardID: wildcards)
|
||||
for(WildcardID wildcardID : wildcards)
|
||||
{
|
||||
if(wildcardID.value().equals(value))
|
||||
{
|
||||
@@ -262,12 +262,12 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
private void removeAliasID(AliasID id, Alias alias)
|
||||
{
|
||||
if (id.isValid())
|
||||
if(id.isValid())
|
||||
{
|
||||
switch (id.getType())
|
||||
switch(id.getType())
|
||||
{
|
||||
case ESN:
|
||||
String esn = ((Esn)id).getEsn();
|
||||
String esn = ((Esn) id).getEsn();
|
||||
|
||||
if(esn != null)
|
||||
{
|
||||
@@ -280,13 +280,13 @@ public class AliasList implements Listener<AliasEvent>
|
||||
mESN.remove(esn);
|
||||
break;
|
||||
case FLEETSYNC:
|
||||
String fleetsync = ((FleetsyncID)id).getIdent();
|
||||
String fleetsync = ((FleetsyncID) id).getIdent();
|
||||
|
||||
if(fleetsync != null)
|
||||
{
|
||||
if(fleetsync.contains(WILDCARD))
|
||||
{
|
||||
removeWildcard(fleetsync,mFleetsyncWildcards);
|
||||
removeWildcard(fleetsync, mFleetsyncWildcards);
|
||||
}
|
||||
|
||||
mFleetsync.remove(fleetsync);
|
||||
@@ -296,7 +296,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
mLoJack.remove((LoJackFunctionAndID) id);
|
||||
break;
|
||||
case MDC1200:
|
||||
String mdc = ((MDC1200ID)id).getIdent();
|
||||
String mdc = ((MDC1200ID) id).getIdent();
|
||||
|
||||
if(mdc != null)
|
||||
{
|
||||
@@ -309,7 +309,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case MPT1327:
|
||||
String mpt = ((MPT1327ID)id).getIdent();
|
||||
String mpt = ((MPT1327ID) id).getIdent();
|
||||
|
||||
if(mpt != null)
|
||||
{
|
||||
@@ -322,7 +322,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
}
|
||||
break;
|
||||
case MIN:
|
||||
String min = ((Min)id).getMin();
|
||||
String min = ((Min) id).getMin();
|
||||
|
||||
if(min != null)
|
||||
{
|
||||
@@ -344,7 +344,7 @@ public class AliasList implements Listener<AliasEvent>
|
||||
mStatus.remove(((StatusID) id).getStatus());
|
||||
break;
|
||||
case TALKGROUP:
|
||||
String tgid = ((TalkgroupID)id).getTalkgroup();
|
||||
String tgid = ((TalkgroupID) id).getTalkgroup();
|
||||
|
||||
if(tgid != null)
|
||||
{
|
||||
@@ -378,11 +378,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
private String getWildcardMatch(String id, List<WildcardID> wildcards)
|
||||
{
|
||||
if (id != null)
|
||||
if(id != null)
|
||||
{
|
||||
for (WildcardID wildcard : wildcards)
|
||||
for(WildcardID wildcard : wildcards)
|
||||
{
|
||||
if (wildcard.matches(id))
|
||||
if(wildcard.matches(id))
|
||||
{
|
||||
return wildcard.value();
|
||||
}
|
||||
@@ -399,15 +399,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (siteID != null)
|
||||
if(siteID != null)
|
||||
{
|
||||
alias = mSiteID.get(siteID);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(siteID, mSiteWildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mSiteID.get(wildcard);
|
||||
}
|
||||
@@ -440,15 +440,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (esn != null)
|
||||
if(esn != null)
|
||||
{
|
||||
alias = mESN.get(esn);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(esn, mESNWildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mESN.get(wildcard);
|
||||
}
|
||||
@@ -465,15 +465,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (ident != null)
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mFleetsync.get(ident);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mFleetsyncWildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mFleetsync.get(wildcard);
|
||||
}
|
||||
@@ -488,11 +488,11 @@ public class AliasList implements Listener<AliasEvent>
|
||||
*/
|
||||
public Alias getLoJackAlias(Function function, String id)
|
||||
{
|
||||
if (id != null)
|
||||
if(id != null)
|
||||
{
|
||||
for (LoJackFunctionAndID lojack : mLoJack.keySet())
|
||||
for(LoJackFunctionAndID lojack : mLoJack.keySet())
|
||||
{
|
||||
if (lojack.matches(function, id))
|
||||
if(lojack.matches(function, id))
|
||||
{
|
||||
return mLoJack.get(lojack);
|
||||
}
|
||||
@@ -509,15 +509,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (ident != null)
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMDC1200.get(ident);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMDC1200Wildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMDC1200.get(wildcard);
|
||||
}
|
||||
@@ -534,15 +534,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (ident != null)
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMPT1327.get(ident);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMPT1327Wildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMPT1327.get(wildcard);
|
||||
}
|
||||
@@ -559,15 +559,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (ident != null)
|
||||
if(ident != null)
|
||||
{
|
||||
alias = mMobileID.get(ident);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(ident, mMobileIDWildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mMobileID.get(wildcard);
|
||||
}
|
||||
@@ -584,15 +584,15 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (tgid != null)
|
||||
if(tgid != null)
|
||||
{
|
||||
alias = mTalkgroup.get(tgid);
|
||||
|
||||
if (alias == null)
|
||||
if(alias == null)
|
||||
{
|
||||
String wildcard = getWildcardMatch(tgid, mTalkgroupWildcards);
|
||||
|
||||
if (wildcard != null)
|
||||
if(wildcard != null)
|
||||
{
|
||||
alias = mTalkgroup.get(wildcard);
|
||||
}
|
||||
@@ -619,61 +619,6 @@ public class AliasList implements Listener<AliasEvent>
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup an alias by metadata type and string value
|
||||
*/
|
||||
public Alias getAlias(String value, MetadataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ESN:
|
||||
return getESNAlias(value);
|
||||
case FLEETSYNC:
|
||||
return getFleetsyncAlias(value);
|
||||
case MDC1200:
|
||||
return getMDC1200Alias(value);
|
||||
case MOBILE_ID:
|
||||
return getMobileIDNumberAlias(value);
|
||||
case MPT1327:
|
||||
return getMPT1327Alias(value);
|
||||
case SITE_ID:
|
||||
return getSiteID(value);
|
||||
case STATUS:
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getStatus(Integer.valueOf(value));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//do nothing, we couldn't parse the int value
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FROM:
|
||||
case TO:
|
||||
return getTalkgroupAlias(value);
|
||||
case UNIQUE_ID:
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getUniqueID(Integer.valueOf(value));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//do nothing, we couldn't parse the int value
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive alias change event notifications and modify this list accordingly
|
||||
*/
|
||||
@@ -682,22 +627,22 @@ public class AliasList implements Listener<AliasEvent>
|
||||
{
|
||||
Alias alias = event.getAlias();
|
||||
|
||||
switch (event.getEvent())
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case ADD:
|
||||
if (alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
{
|
||||
addAlias(alias);
|
||||
}
|
||||
break;
|
||||
case CHANGE:
|
||||
if (alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
{
|
||||
addAlias(alias);
|
||||
}
|
||||
break;
|
||||
case DELETE:
|
||||
if (alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
|
||||
{
|
||||
removeAlias(alias);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
package audio;
|
||||
|
||||
import alias.Alias;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import audio.output.AudioOutput;
|
||||
import channel.metadata.Metadata;
|
||||
import icon.IconManager;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import sample.Listener;
|
||||
@@ -50,12 +48,12 @@ public class AudioChannelPanel extends JPanel
|
||||
|
||||
private JLabel mChannelName = new JLabel(" ");
|
||||
private JLabel mToLabel = new JLabel("TO:");
|
||||
private JLabel mTo = new JLabel("");
|
||||
private JLabel mTo = new JLabel("-----");
|
||||
private JLabel mToAlias = new JLabel("");
|
||||
|
||||
private JLabel mMutedLabel = new JLabel(" ");
|
||||
private JLabel mFromLabel = new JLabel("FROM:");
|
||||
private JLabel mFrom = new JLabel("");
|
||||
private JLabel mFrom = new JLabel("-----");
|
||||
private JLabel mFromAlias = new JLabel("");
|
||||
|
||||
private boolean mConfigured = false;
|
||||
@@ -71,7 +69,7 @@ public class AudioChannelPanel extends JPanel
|
||||
if(mAudioOutput != null)
|
||||
{
|
||||
mAudioOutput.addAudioEventListener(this);
|
||||
mAudioOutput.setAudioMetadataListener(new AudioMetadataProcessor());
|
||||
mAudioOutput.setMetadataListener(new AudioMetadataProcessor());
|
||||
}
|
||||
|
||||
mLabelColor = mSettingsManager.getColorSetting(
|
||||
@@ -173,11 +171,8 @@ public class AudioChannelPanel extends JPanel
|
||||
*/
|
||||
private void resetLabels()
|
||||
{
|
||||
mFrom.setText("");
|
||||
updateAlias(mFromAlias, null);
|
||||
|
||||
mTo.setText("");
|
||||
updateAlias(mToAlias, null);
|
||||
updateLabel(mFromLabel, null, mFromAlias, null);
|
||||
updateLabel(mToLabel, null, mToAlias, null);
|
||||
|
||||
mConfigured = false;
|
||||
}
|
||||
@@ -187,27 +182,25 @@ public class AudioChannelPanel extends JPanel
|
||||
* does not occur on the Swing event thread -- wrap any calls to this
|
||||
* method with an event thread call.
|
||||
*/
|
||||
private void updateAlias(JLabel label, Alias alias)
|
||||
private void updateLabel(JLabel valueLabel, String value, JLabel aliasLabel, Alias alias)
|
||||
{
|
||||
if(alias != null)
|
||||
if(value != null)
|
||||
{
|
||||
label.setText(alias.getName());
|
||||
valueLabel.setText(value);
|
||||
|
||||
String icon = alias.getIconName();
|
||||
|
||||
if(icon != null)
|
||||
if(alias != null)
|
||||
{
|
||||
label.setIcon(mIconManager.getIcon(icon, IconManager.DEFAULT_ICON_SIZE));
|
||||
aliasLabel.setIcon(mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setIcon(null);
|
||||
aliasLabel.setIcon(null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setText("");
|
||||
label.setIcon(null);
|
||||
valueLabel.setText("-----");
|
||||
aliasLabel.setIcon(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,45 +208,28 @@ public class AudioChannelPanel extends JPanel
|
||||
/**
|
||||
* Processes audio metadata to update this panel's display values
|
||||
*/
|
||||
public class AudioMetadataProcessor implements Listener<AudioMetadata>
|
||||
public class AudioMetadataProcessor implements Listener<Metadata>
|
||||
{
|
||||
@Override
|
||||
public void receive(AudioMetadata audioMetadata)
|
||||
public void receive(final Metadata metadata)
|
||||
{
|
||||
if(!mConfigured || audioMetadata.isUpdated())
|
||||
if(metadata.isUpdated() || !mConfigured)
|
||||
{
|
||||
final Metadata from = audioMetadata.getMetadata(MetadataType.FROM);
|
||||
|
||||
final Metadata to = audioMetadata.getMetadata(MetadataType.TO);
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(from != null)
|
||||
{
|
||||
mFrom.setText(from.getValue());
|
||||
updateAlias(mFromAlias, from.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrom.setText("-----");
|
||||
}
|
||||
updateLabel(mFromLabel, metadata.getPrimaryAddressFrom().getIdentifier(),
|
||||
mFromAlias, metadata.getPrimaryAddressFrom().getAlias());
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
mTo.setText(to.getValue());
|
||||
updateAlias(mToAlias, to.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
mTo.setText("-----");
|
||||
}
|
||||
updateLabel(mToLabel, metadata.getPrimaryAddressTo().getIdentifier(),
|
||||
mToAlias, metadata.getPrimaryAddressTo().getAlias());
|
||||
|
||||
mConfigured = true;
|
||||
}
|
||||
});
|
||||
|
||||
mConfigured = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* 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 audio;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.SquelchState;
|
||||
import channel.metadata.Metadata;
|
||||
import dsp.filter.design.FilterDesignException;
|
||||
import dsp.filter.fir.FIRFilterSpecification;
|
||||
import dsp.filter.fir.remez.RemezFIRFilterDesigner;
|
||||
import dsp.filter.polyphase.PolyphaseFIRDecimatingFilter_RB;
|
||||
import module.Module;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.IMetadataListener;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.SquelchState;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.IChannelEventListener;
|
||||
import dsp.filter.Filters;
|
||||
import dsp.filter.fir.real.RealFIRFilter_R_R;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* Provides packaging of demodulated audio sample buffers into audio packets for
|
||||
@@ -33,12 +42,8 @@ import dsp.filter.fir.real.RealFIRFilter_R_R;
|
||||
* Incorporates audio squelch state listener to control if audio packets are
|
||||
* broadcast or ignored.
|
||||
*/
|
||||
public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
IChannelEventListener,
|
||||
IMetadataListener,
|
||||
IFilteredRealBufferListener,
|
||||
ISquelchStateListener,
|
||||
Listener<RealBuffer>
|
||||
public class AudioModule extends Module implements IAudioPacketProvider, IFilteredRealBufferListener,
|
||||
ISquelchStateListener, Listener<RealBuffer>
|
||||
{
|
||||
protected static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
|
||||
|
||||
@@ -48,48 +53,41 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
{
|
||||
//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)
|
||||
.build();
|
||||
.sampleRate(48000)
|
||||
.stopFrequency1(150)
|
||||
.passFrequencyBegin(300)
|
||||
.passFrequencyEnd(3500)
|
||||
.stopFrequency2(4000)
|
||||
.stopRipple(0.0004)
|
||||
.passRipple(0.008)
|
||||
.build();
|
||||
|
||||
RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification);
|
||||
|
||||
try
|
||||
{
|
||||
if (!designer.isValid())
|
||||
if(!designer.isValid())
|
||||
{
|
||||
throw new FilterDesignException("Couldn't design the audio decimation filter");
|
||||
}
|
||||
|
||||
mDecimationCoefficients = designer.getImpulseResponse();
|
||||
}
|
||||
catch (FilterDesignException e)
|
||||
catch(FilterDesignException e)
|
||||
{
|
||||
mLog.debug("Error designing filter", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Provides a unique identifier for this audio module instance to use as a
|
||||
* source identifier for all audio packets */
|
||||
private static int UNIQUE_ID = 0;
|
||||
private int mSourceID;
|
||||
|
||||
private AudioMetadata mAudioMetadata;
|
||||
private ChannelEventListener mChannelEventListener = new ChannelEventListener();
|
||||
private SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
||||
private SquelchState mSquelchState = SquelchState.SQUELCH;
|
||||
private Listener<AudioPacket> mAudioPacketListener;
|
||||
private PolyphaseFIRDecimatingFilter_RB mAudioDecimationFilter;
|
||||
private Metadata mMetadata;
|
||||
|
||||
public AudioModule(boolean record)
|
||||
public AudioModule(Metadata metadata)
|
||||
{
|
||||
mSourceID = ++UNIQUE_ID;
|
||||
mAudioMetadata = new AudioMetadata(mSourceID, record);
|
||||
mMetadata = metadata;
|
||||
|
||||
mAudioDecimationFilter = new PolyphaseFIRDecimatingFilter_RB(mDecimationCoefficients, 6, 2.0f);
|
||||
mAudioDecimationFilter.setListener(new Listener<RealBuffer>()
|
||||
@@ -97,9 +95,9 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
@Override
|
||||
public void receive(RealBuffer realBuffer)
|
||||
{
|
||||
if (mAudioPacketListener != null)
|
||||
if(mAudioPacketListener != null)
|
||||
{
|
||||
AudioPacket packet = new AudioPacket(realBuffer.getSamples(), mAudioMetadata.copyOf());
|
||||
AudioPacket packet = new AudioPacket(realBuffer.getSamples(), mMetadata.copyOf());
|
||||
mAudioPacketListener.receive(packet);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +114,6 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mAudioMetadata.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,11 +125,10 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
@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(mAudioPacketListener != null)
|
||||
{
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END,
|
||||
mAudioMetadata.copyOf()));
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END, mMetadata.copyOf()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,15 +139,9 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
@Override
|
||||
public void receive(RealBuffer buffer)
|
||||
{
|
||||
if (mAudioPacketListener != null && mSquelchState == SquelchState.UNSQUELCH)
|
||||
if(mAudioPacketListener != null && mSquelchState == SquelchState.UNSQUELCH)
|
||||
{
|
||||
mAudioDecimationFilter.receive(buffer);
|
||||
|
||||
// /* We make a copy of the samples, so that we don't affect any other
|
||||
// * processes that might be concurrently processing the same buffer */
|
||||
// float[] audio = Arrays.copyOf( buffer.getSamples(), buffer.getSamples().length );
|
||||
//
|
||||
// mAudioFilter.filter( audio );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,12 +151,6 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<Metadata> getMetadataListener()
|
||||
{
|
||||
return mAudioMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAudioPacketListener(Listener<AudioPacket> listener)
|
||||
{
|
||||
@@ -179,41 +163,12 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
mAudioPacketListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<ChannelEvent> getChannelEventListener()
|
||||
{
|
||||
return mChannelEventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<SquelchState> getSquelchStateListener()
|
||||
{
|
||||
return mSquelchStateListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for channel event listener. Responds to channel state reset
|
||||
* events to remove/cleanup current audio metadata
|
||||
*/
|
||||
public class ChannelEventListener implements Listener<ChannelEvent>
|
||||
{
|
||||
@Override
|
||||
public void receive(ChannelEvent event)
|
||||
{
|
||||
switch (event.getEvent())
|
||||
{
|
||||
case NOTIFICATION_STATE_RESET:
|
||||
mAudioMetadata.reset();
|
||||
break;
|
||||
case NOTIFICATION_SELECTION_CHANGE:
|
||||
mAudioMetadata.setSelected(event.getChannel().isSelected());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for squelch state listener
|
||||
*/
|
||||
@@ -222,10 +177,9 @@ public class AudioModule extends Module implements IAudioPacketProvider,
|
||||
@Override
|
||||
public void receive(SquelchState state)
|
||||
{
|
||||
if (state == SquelchState.SQUELCH && mAudioPacketListener != null)
|
||||
if(state == SquelchState.SQUELCH && mAudioPacketListener != null)
|
||||
{
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END,
|
||||
mAudioMetadata.copyOf()));
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END, mMetadata.copyOf()));
|
||||
}
|
||||
|
||||
mSquelchState = state;
|
||||
|
||||
@@ -1,77 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* 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 audio;
|
||||
|
||||
import channel.metadata.Metadata;
|
||||
import sample.real.RealBuffer;
|
||||
import audio.metadata.AudioMetadata;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
public class AudioPacket
|
||||
{
|
||||
private Type mType;
|
||||
private RealBuffer mAudioData;
|
||||
private AudioMetadata mAudioMetadata;
|
||||
|
||||
public AudioPacket( Type type, AudioMetadata metadata )
|
||||
{
|
||||
mType = type;
|
||||
mAudioMetadata = metadata;
|
||||
}
|
||||
|
||||
public AudioPacket( float[] audio, AudioMetadata metadata )
|
||||
{
|
||||
this( Type.AUDIO, metadata );
|
||||
private Type mType;
|
||||
private RealBuffer mAudioData;
|
||||
private Metadata mMetadata;
|
||||
|
||||
mAudioData = new RealBuffer( audio );
|
||||
}
|
||||
|
||||
public boolean hasAudioMetadata()
|
||||
{
|
||||
return mAudioMetadata != null;
|
||||
}
|
||||
|
||||
public AudioMetadata getAudioMetadata()
|
||||
{
|
||||
return mAudioMetadata;
|
||||
}
|
||||
|
||||
public void setMetadata( AudioMetadata metadata )
|
||||
{
|
||||
mAudioMetadata = metadata;
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
public RealBuffer getAudioBuffer()
|
||||
{
|
||||
return mAudioData;
|
||||
}
|
||||
|
||||
public boolean hasAudioBuffer()
|
||||
{
|
||||
return mAudioData != null;
|
||||
}
|
||||
|
||||
public enum Type
|
||||
{
|
||||
AUDIO,
|
||||
END;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -18,14 +18,11 @@
|
||||
******************************************************************************/
|
||||
package audio.broadcast;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketListener;
|
||||
import audio.convert.ISilenceGenerator;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import sample.Listener;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -34,14 +31,13 @@ import java.nio.file.Files;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( AudioBroadcaster.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AudioBroadcaster.class);
|
||||
|
||||
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
|
||||
|
||||
@@ -107,9 +103,10 @@ 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
|
||||
*/
|
||||
protected void broadcastMetadata(AudioMetadata metadata)
|
||||
protected void broadcastMetadata(Metadata metadata)
|
||||
{
|
||||
IBroadcastMetadataUpdater metadataUpdater = getMetadataUpdater();
|
||||
|
||||
@@ -136,7 +133,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
if(mThreadPoolManager != null)
|
||||
{
|
||||
mScheduledTask = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
|
||||
mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS );
|
||||
mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,6 +157,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
|
||||
/**
|
||||
* Stream name for the broadcast configuration for this broadcaster
|
||||
*
|
||||
* @return stream name or null
|
||||
*/
|
||||
public String getStreamName()
|
||||
@@ -246,7 +244,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
if(mBroadcastState != state)
|
||||
{
|
||||
mLog.info("[" + getStreamName() + "] status: " + state);
|
||||
mLog.info("[" + getStreamName() + "] status: " + state);
|
||||
mBroadcastState = state;
|
||||
|
||||
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
|
||||
@@ -386,7 +384,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
mStreamedAudioCount++;
|
||||
broadcast(new BroadcastEvent(AudioBroadcaster.this,
|
||||
BroadcastEvent.Event.BROADCASTER_STREAMED_COUNT_CHANGE));
|
||||
BroadcastEvent.Event.BROADCASTER_STREAMED_COUNT_CHANGE));
|
||||
metadataUpdateRequired = true;
|
||||
}
|
||||
|
||||
@@ -431,7 +429,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
|
||||
if(connected())
|
||||
{
|
||||
broadcastMetadata(nextRecording.getAudioMetadata());
|
||||
broadcastMetadata(nextRecording.getMetadata());
|
||||
}
|
||||
|
||||
metadataUpdateRequired = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -18,7 +18,7 @@
|
||||
******************************************************************************/
|
||||
package audio.broadcast;
|
||||
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -30,22 +30,23 @@ public class AudioRecording implements Comparable<AudioRecording>
|
||||
private final static Logger mLog = LoggerFactory.getLogger(StreamManager.class);
|
||||
|
||||
private Path mPath;
|
||||
private AudioMetadata mAudioMetadata;
|
||||
private long mStartTime;
|
||||
private long mRecordingLength;
|
||||
private AtomicInteger mPendingReplayCount = new AtomicInteger();
|
||||
private Metadata mMetadata;
|
||||
|
||||
/**
|
||||
* Audio recording that is ready to be streamed
|
||||
*
|
||||
* @param path to the audio recording file
|
||||
* @param audioMetadata associated with the recording
|
||||
* @param metadata associated with the recording
|
||||
* @param start time of recording in milliseconds since epoch
|
||||
* @param recordingLength in milliseconds
|
||||
*/
|
||||
public AudioRecording(Path path, AudioMetadata audioMetadata, long start, long recordingLength)
|
||||
public AudioRecording(Path path, Metadata metadata, long start, long recordingLength)
|
||||
{
|
||||
mPath = path;
|
||||
mAudioMetadata = audioMetadata;
|
||||
mMetadata = metadata;
|
||||
mStartTime = start;
|
||||
mRecordingLength = recordingLength;
|
||||
}
|
||||
@@ -61,9 +62,9 @@ public class AudioRecording implements Comparable<AudioRecording>
|
||||
/**
|
||||
* Optional audio metadata for the recording.
|
||||
*/
|
||||
public AudioMetadata getAudioMetadata()
|
||||
public Metadata getMetadata()
|
||||
{
|
||||
return mAudioMetadata;
|
||||
return mMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ package audio.broadcast;
|
||||
|
||||
import alias.id.broadcast.BroadcastChannel;
|
||||
import audio.AudioPacket;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import icon.IconManager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -48,7 +48,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class BroadcastModel extends AbstractTableModel implements Listener<AudioPacket>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( BroadcastModel.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(BroadcastModel.class);
|
||||
|
||||
public static final String TEMPORARY_STREAM_DIRECTORY = "streaming";
|
||||
public static final String TEMPORARY_STREAM_FILE_SUFFIX = "temporary_streaming_file_";
|
||||
@@ -84,7 +84,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
//Monitor to remove temporary recording files that have been streamed by all audio broadcasters
|
||||
mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_RECORDING,
|
||||
new RecordingDeletionMonitor(), 15l, TimeUnit.SECONDS );
|
||||
new RecordingDeletionMonitor(), 15l, TimeUnit.SECONDS);
|
||||
|
||||
removeOrphanedTemporaryRecordings();
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
{
|
||||
List<String> names = new ArrayList<>();
|
||||
|
||||
for(BroadcastConfiguration configuration: mBroadcastConfigurations)
|
||||
for(BroadcastConfiguration configuration : mBroadcastConfigurations)
|
||||
{
|
||||
names.add(configuration.getName());
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
*/
|
||||
public void addBroadcastConfigurations(List<BroadcastConfiguration> configurations)
|
||||
{
|
||||
for(BroadcastConfiguration configuration: configurations)
|
||||
for(BroadcastConfiguration configuration : configurations)
|
||||
{
|
||||
addBroadcastConfiguration(configuration);
|
||||
}
|
||||
@@ -138,11 +138,11 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
int index = mBroadcastConfigurations.size() - 1;
|
||||
|
||||
fireTableRowsInserted( index, index );
|
||||
fireTableRowsInserted(index, index);
|
||||
|
||||
mBroadcastConfigurationMap.put(configuration.getName(), configuration);
|
||||
|
||||
process( new BroadcastEvent( configuration, BroadcastEvent.Event.CONFIGURATION_ADD) );
|
||||
process(new BroadcastEvent(configuration, BroadcastEvent.Event.CONFIGURATION_ADD));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,6 +164,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
/**
|
||||
* Updates the configuration's name so that it is unique among all other broadcast configurations
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
private void ensureUniqueName(BroadcastConfiguration configuration)
|
||||
@@ -235,11 +236,11 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
return false;
|
||||
}
|
||||
|
||||
for(BroadcastConfiguration configurationToCompare: mBroadcastConfigurations)
|
||||
for(BroadcastConfiguration configurationToCompare : mBroadcastConfigurations)
|
||||
{
|
||||
if(configurationToCompare != configuration &&
|
||||
configurationToCompare.getName() != null &&
|
||||
configurationToCompare.getName().equals(name))
|
||||
configurationToCompare.getName() != null &&
|
||||
configurationToCompare.getName().equals(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -258,9 +259,9 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
mBroadcastConfigurationMap.remove(broadcastConfiguration.getName());
|
||||
|
||||
process(new BroadcastEvent( broadcastConfiguration, BroadcastEvent.Event.CONFIGURATION_DELETE));
|
||||
process(new BroadcastEvent(broadcastConfiguration, BroadcastEvent.Event.CONFIGURATION_DELETE));
|
||||
|
||||
fireTableRowsDeleted( index, index );
|
||||
fireTableRowsDeleted(index, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +276,8 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
{
|
||||
if (audioPacket.hasAudioMetadata() &&
|
||||
audioPacket.getAudioMetadata().isStreamable())
|
||||
if(audioPacket.hasMetadata() &&
|
||||
audioPacket.getMetadata().isStreamable())
|
||||
{
|
||||
mStreamManager.receive(audioPacket);
|
||||
}
|
||||
@@ -287,7 +288,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
*/
|
||||
private void createBroadcaster(BroadcastConfiguration broadcastConfiguration)
|
||||
{
|
||||
if (broadcastConfiguration != null &&
|
||||
if(broadcastConfiguration != null &&
|
||||
broadcastConfiguration.isEnabled() &&
|
||||
broadcastConfiguration.isValid() &&
|
||||
!mBroadcasterMap.containsKey(broadcastConfiguration.getName()))
|
||||
@@ -295,7 +296,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(mThreadPoolManager,
|
||||
broadcastConfiguration);
|
||||
|
||||
if (audioBroadcaster != null)
|
||||
if(audioBroadcaster != null)
|
||||
{
|
||||
audioBroadcaster.setListener(new Listener<BroadcastEvent>()
|
||||
{
|
||||
@@ -377,7 +378,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
*/
|
||||
private void broadcast(BroadcastEvent event)
|
||||
{
|
||||
mBroadcastEventBroadcaster.broadcast( event );
|
||||
mBroadcastEventBroadcaster.broadcast(event);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,7 +396,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
case CONFIGURATION_CHANGE:
|
||||
BroadcastConfiguration broadcastConfiguration = broadcastEvent.getBroadcastConfiguration();
|
||||
int index = mBroadcastConfigurations.indexOf(broadcastConfiguration);
|
||||
fireTableRowsUpdated( index, index );
|
||||
fireTableRowsUpdated(index, index);
|
||||
|
||||
//Delete and recreate the broadcaster for any broadcast configuration changes
|
||||
String previousChannelName = cleanupMapAssociations(broadcastConfiguration);
|
||||
@@ -452,7 +453,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
{
|
||||
String oldName = null;
|
||||
|
||||
for(Map.Entry<String,BroadcastConfiguration> entry: mBroadcastConfigurationMap.entrySet())
|
||||
for(Map.Entry<String,BroadcastConfiguration> entry : mBroadcastConfigurationMap.entrySet())
|
||||
{
|
||||
if(entry.getValue() == broadcastConfiguration)
|
||||
{
|
||||
@@ -488,7 +489,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
{
|
||||
try
|
||||
{
|
||||
if( rowIndex <= mBroadcastConfigurations.size())
|
||||
if(rowIndex <= mBroadcastConfigurations.size())
|
||||
{
|
||||
BroadcastConfiguration configuration = mBroadcastConfigurations.get(rowIndex);
|
||||
|
||||
@@ -686,19 +687,19 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
@Override
|
||||
public void receive(AudioRecording audioRecording)
|
||||
{
|
||||
AudioMetadata metadata = audioRecording.getAudioMetadata();
|
||||
Metadata metadata = audioRecording.getMetadata();
|
||||
|
||||
if(metadata != null && metadata.isStreamable())
|
||||
{
|
||||
for (BroadcastChannel broadcastChannel : metadata.getBroadcastChannels())
|
||||
for(BroadcastChannel broadcastChannel : metadata.getBroadcastChannels())
|
||||
{
|
||||
String channelName = broadcastChannel.getChannelName();
|
||||
|
||||
if (channelName != null)
|
||||
if(channelName != null)
|
||||
{
|
||||
AudioBroadcaster audioBroadcaster = getBroadcaster(channelName);
|
||||
|
||||
if (audioBroadcaster != null)
|
||||
if(audioBroadcaster != null)
|
||||
{
|
||||
audioRecording.addPendingReplay();
|
||||
audioBroadcaster.receive(audioRecording);
|
||||
@@ -739,7 +740,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
if(!recordingsToDelete.isEmpty())
|
||||
{
|
||||
for(AudioRecording recordingToDelete: recordingsToDelete)
|
||||
for(AudioRecording recordingToDelete : recordingsToDelete)
|
||||
{
|
||||
mRecordingQueue.remove(recordingToDelete);
|
||||
removeRecording(recordingToDelete);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
******************************************************************************/
|
||||
package audio.broadcast;
|
||||
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
|
||||
public interface IBroadcastMetadataUpdater
|
||||
{
|
||||
@@ -27,5 +27,5 @@ public interface IBroadcastMetadataUpdater
|
||||
*
|
||||
* @param metadata containing metadata attributes
|
||||
*/
|
||||
void update(AudioMetadata metadata);
|
||||
void update(Metadata metadata);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -48,7 +48,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
private Listener<AudioRecording> mAudioRecordingListener;
|
||||
private BroadcastFormat mBroadcastFormat;
|
||||
private Path mTempDirectory;
|
||||
private Map<Integer, AudioRecorder> mStreamRecorders = new HashMap<>();
|
||||
private Map<Integer,AudioRecorder> mStreamRecorders = new HashMap<>();
|
||||
private Runnable mRecorderMonitor;
|
||||
private ScheduledFuture<?> mRecorderMonitorFuture;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
@@ -68,8 +68,8 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
public StreamManager(ThreadPoolManager threadPoolManager, Listener<AudioRecording> listener,
|
||||
BroadcastFormat broadcastFormat, Path tempDirectory)
|
||||
{
|
||||
assert(tempDirectory != null && Files.isDirectory(tempDirectory));
|
||||
assert(mThreadPoolManager != null);
|
||||
assert (tempDirectory != null && Files.isDirectory(tempDirectory));
|
||||
assert (mThreadPoolManager != null);
|
||||
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mAudioRecordingListener = listener;
|
||||
@@ -91,7 +91,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
}
|
||||
|
||||
mRecorderMonitorFuture = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
|
||||
mRecorderMonitor, 2, TimeUnit.SECONDS);
|
||||
mRecorderMonitor, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,11 +107,11 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
mRecorderMonitorFuture.cancel(true);
|
||||
}
|
||||
|
||||
synchronized (mStreamRecorders)
|
||||
synchronized(mStreamRecorders)
|
||||
{
|
||||
List<Integer> streamKeys = new ArrayList<>(mStreamRecorders.keySet());
|
||||
|
||||
for(Integer streamKey: streamKeys)
|
||||
for(Integer streamKey : streamKeys)
|
||||
{
|
||||
removeRecorder(streamKey);
|
||||
}
|
||||
@@ -122,19 +122,19 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
{
|
||||
if(mRunning.get() && audioPacket.hasAudioMetadata())
|
||||
if(mRunning.get() && audioPacket.hasMetadata())
|
||||
{
|
||||
synchronized (mStreamRecorders)
|
||||
synchronized(mStreamRecorders)
|
||||
{
|
||||
int sourceChannelID = audioPacket.getAudioMetadata().getSource();
|
||||
int channelMetadataID = audioPacket.getMetadata().getMetadataID();
|
||||
|
||||
AudioPacket.Type type = audioPacket.getType();
|
||||
|
||||
if(type == AudioPacket.Type.AUDIO)
|
||||
{
|
||||
if(mStreamRecorders.containsKey(sourceChannelID))
|
||||
if(mStreamRecorders.containsKey(channelMetadataID))
|
||||
{
|
||||
AudioRecorder recorder = mStreamRecorders.get(sourceChannelID);
|
||||
AudioRecorder recorder = mStreamRecorders.get(channelMetadataID);
|
||||
|
||||
if(recorder != null)
|
||||
{
|
||||
@@ -144,15 +144,15 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
else
|
||||
{
|
||||
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
|
||||
mBroadcastFormat);
|
||||
mBroadcastFormat);
|
||||
recorder.start(mThreadPoolManager.getScheduledExecutorService());
|
||||
recorder.receive(audioPacket);
|
||||
mStreamRecorders.put(sourceChannelID, recorder);
|
||||
mStreamRecorders.put(channelMetadataID, recorder);
|
||||
}
|
||||
}
|
||||
else if(type == AudioPacket.Type.END)
|
||||
{
|
||||
removeRecorder(sourceChannelID);
|
||||
removeRecorder(channelMetadataID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -203,8 +203,8 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(BroadcastModel.TEMPORARY_STREAM_FILE_SUFFIX);
|
||||
sb.append(sNextRecordingNumber.incrementAndGet()).append("_");
|
||||
sb.append( TimeStamp.getLongTimeStamp( "_" ) );
|
||||
sb.append( mBroadcastFormat.getFileExtension() );
|
||||
sb.append(TimeStamp.getLongTimeStamp("_"));
|
||||
sb.append(mBroadcastFormat.getFileExtension());
|
||||
|
||||
Path temporaryRecordingPath = mTempDirectory.resolve(sb.toString());
|
||||
|
||||
@@ -219,19 +219,19 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
synchronized (mStreamRecorders)
|
||||
synchronized(mStreamRecorders)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
mStreamRecorders.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().getTimeRecordingStart() + MAXIMUM_RECORDER_LIFESPAN_MILLIS < now)
|
||||
.forEach(entry ->
|
||||
{
|
||||
mLog.debug("Maximum recording time limit reached - removing recorder: " +
|
||||
entry.getValue().getPath().toString());
|
||||
{
|
||||
mLog.debug("Maximum recording time limit reached - removing recorder: " +
|
||||
entry.getValue().getPath().toString());
|
||||
|
||||
removeRecorder(entry.getKey());
|
||||
});
|
||||
removeRecorder(entry.getKey());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -19,9 +19,7 @@
|
||||
package audio.broadcast.icecast;
|
||||
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
@@ -58,7 +56,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private AtomicBoolean mUpdating = new AtomicBoolean();
|
||||
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
|
||||
private Map<String, String> mHTTPHeaders;
|
||||
private Map<String,String> mHTTPHeaders;
|
||||
private boolean mStackTraceLoggingSuppressed;
|
||||
|
||||
/**
|
||||
@@ -78,7 +76,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
*/
|
||||
private NioSocketConnector getSocketConnector()
|
||||
{
|
||||
if (mSocketConnector == null)
|
||||
if(mSocketConnector == null)
|
||||
{
|
||||
mSocketConnector = new NioSocketConnector();
|
||||
// mSocketConnector.getFilterChain().addLast("logger", new LoggingFilter(IcecastBroadcastMetadataUpdater.class));
|
||||
@@ -116,19 +114,19 @@ 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(AudioMetadata audioMetadata)
|
||||
public void update(Metadata metadata)
|
||||
{
|
||||
mMetadataQueue.offer(getSong(audioMetadata));
|
||||
mMetadataQueue.offer(getSong(metadata));
|
||||
|
||||
if (mUpdating.compareAndSet(false, true))
|
||||
if(mUpdating.compareAndSet(false, true))
|
||||
{
|
||||
String song = mMetadataQueue.poll();
|
||||
|
||||
while (song != null)
|
||||
while(song != null)
|
||||
{
|
||||
HttpRequest updateRequest = createUpdateRequest(song);
|
||||
|
||||
if (updateRequest != null)
|
||||
if(updateRequest != null)
|
||||
{
|
||||
mThreadPoolManager.scheduleOnce(new Runnable()
|
||||
{
|
||||
@@ -143,22 +141,22 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
connectFuture.awaitUninterruptibly();
|
||||
IoSession session = connectFuture.getSession();
|
||||
|
||||
if (session != null)
|
||||
if(session != null)
|
||||
{
|
||||
session.write(updateRequest);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch(Exception e)
|
||||
{
|
||||
Throwable throwableCause = e.getCause();
|
||||
|
||||
if (throwableCause instanceof ConnectException)
|
||||
if(throwableCause instanceof ConnectException)
|
||||
{
|
||||
//Do nothing, the server is unavailable
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mStackTraceLoggingSuppressed)
|
||||
if(!mStackTraceLoggingSuppressed)
|
||||
{
|
||||
mLog.error("Error sending metadata update. Future errors will " +
|
||||
"be suppressed", e);
|
||||
@@ -182,52 +180,45 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
/**
|
||||
* Creates the song information for a metadata update
|
||||
*/
|
||||
private static String getSong(AudioMetadata audioMetadata)
|
||||
private static String getSong(Metadata metadata)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(audioMetadata != null)
|
||||
if(metadata != null)
|
||||
{
|
||||
Metadata to = audioMetadata.getMetadata(MetadataType.TO);
|
||||
String to = metadata.getPrimaryAddressTo().getIdentifier();
|
||||
|
||||
sb.append("TO:");
|
||||
|
||||
if(to != null)
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
{
|
||||
if(to.hasAlias())
|
||||
{
|
||||
sb.append(to.getAlias().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(to.getValue());
|
||||
}
|
||||
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
}
|
||||
|
||||
Metadata from = audioMetadata.getMetadata(MetadataType.FROM);
|
||||
|
||||
sb.append(" FROM:");
|
||||
|
||||
if(from != null)
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
{
|
||||
|
||||
if(from.hasAlias())
|
||||
{
|
||||
sb.append(from.getAlias().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(from.getValue());
|
||||
}
|
||||
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -255,7 +246,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
|
||||
return request;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
//This should never happen
|
||||
mLog.error("UTF-8 encoding is not supported - can't update song metadata");
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
package audio.broadcast.shoutcast.v1;
|
||||
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
@@ -57,7 +55,6 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private AtomicBoolean mUpdating = new AtomicBoolean();
|
||||
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
|
||||
private Map<String, String> mHTTPHeaders;
|
||||
private boolean mStackTraceLoggingSuppressed;
|
||||
|
||||
/**
|
||||
@@ -77,7 +74,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
*/
|
||||
private NioSocketConnector getSocketConnector()
|
||||
{
|
||||
if (mSocketConnector == null)
|
||||
if(mSocketConnector == null)
|
||||
{
|
||||
mSocketConnector = new NioSocketConnector();
|
||||
|
||||
@@ -116,19 +113,19 @@ 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(AudioMetadata audioMetadata)
|
||||
public void update(Metadata metadata)
|
||||
{
|
||||
mMetadataQueue.offer(getSong(audioMetadata));
|
||||
mMetadataQueue.offer(getSong(metadata));
|
||||
|
||||
if (mUpdating.compareAndSet(false, true))
|
||||
if(mUpdating.compareAndSet(false, true))
|
||||
{
|
||||
String song = mMetadataQueue.poll();
|
||||
|
||||
while (song != null)
|
||||
while(song != null)
|
||||
{
|
||||
HttpRequest updateRequest = createUpdateRequest(song);
|
||||
|
||||
if (updateRequest != null)
|
||||
if(updateRequest != null)
|
||||
{
|
||||
mThreadPoolManager.scheduleOnce(new Runnable()
|
||||
{
|
||||
@@ -143,22 +140,22 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
connectFuture.awaitUninterruptibly();
|
||||
IoSession session = connectFuture.getSession();
|
||||
|
||||
if (session != null)
|
||||
if(session != null)
|
||||
{
|
||||
session.write(updateRequest);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch(Exception e)
|
||||
{
|
||||
Throwable throwableCause = e.getCause();
|
||||
|
||||
if (throwableCause instanceof ConnectException)
|
||||
if(throwableCause instanceof ConnectException)
|
||||
{
|
||||
//Do nothing, the server is unavailable
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mStackTraceLoggingSuppressed)
|
||||
if(!mStackTraceLoggingSuppressed)
|
||||
{
|
||||
mLog.error("Error sending metadata update. Future errors will " +
|
||||
"be suppressed", e);
|
||||
@@ -182,52 +179,45 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
/**
|
||||
* Creates the song information for a metadata update
|
||||
*/
|
||||
private static String getSong(AudioMetadata audioMetadata)
|
||||
private static String getSong(Metadata metadata)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(audioMetadata != null)
|
||||
if(metadata != null)
|
||||
{
|
||||
Metadata to = audioMetadata.getMetadata(MetadataType.TO);
|
||||
String to = metadata.getPrimaryAddressTo().getIdentifier();
|
||||
|
||||
sb.append("TO:");
|
||||
|
||||
if(to != null)
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
{
|
||||
if(to.hasAlias())
|
||||
{
|
||||
sb.append(to.getAlias().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(to.getValue());
|
||||
}
|
||||
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
}
|
||||
|
||||
Metadata from = audioMetadata.getMetadata(MetadataType.FROM);
|
||||
|
||||
sb.append(" FROM:");
|
||||
|
||||
if(from != null)
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
{
|
||||
|
||||
if(from.hasAlias())
|
||||
{
|
||||
sb.append(from.getAlias().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(from.getValue());
|
||||
}
|
||||
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("UNKNOWN");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -256,7 +246,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
|
||||
return request;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
//This should never happen
|
||||
mLog.error("UTF-8 encoding is not supported - can't update song metadata");
|
||||
|
||||
@@ -37,9 +37,7 @@ import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageFactory;
|
||||
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
|
||||
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
|
||||
import audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
@@ -62,7 +60,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBroadcastMetadataUpdater
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ShoutcastV2AudioBroadcaster.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV2AudioBroadcaster.class);
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
private int mMaxPayloadSize = 16377;
|
||||
|
||||
@@ -93,7 +91,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
public ShoutcastV2Configuration getConfiguration()
|
||||
{
|
||||
return (ShoutcastV2Configuration)getBroadcastConfiguration();
|
||||
return (ShoutcastV2Configuration) getBroadcastConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +120,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AudioMetadata metadata)
|
||||
public void update(Metadata metadata)
|
||||
{
|
||||
List<UltravoxMessage> metadataMessages = getMetadataMessages(metadata);
|
||||
|
||||
@@ -149,7 +147,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
private boolean connect()
|
||||
{
|
||||
if(!connected() && canConnect() &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
mConnecting.compareAndSet(false, true))
|
||||
{
|
||||
mLastConnectionAttempt = System.currentTimeMillis();
|
||||
@@ -242,7 +240,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
* @param metadata containing audio metadata tags and attributes
|
||||
* @return a sequence of CacheableXMLMetadata messages sufficient to carry the complete set of metadata
|
||||
*/
|
||||
private List<UltravoxMessage> getMetadataMessages(AudioMetadata metadata)
|
||||
private List<UltravoxMessage> getMetadataMessages(Metadata metadata)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -264,30 +262,22 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
if(metadata != null)
|
||||
{
|
||||
Metadata to = metadata.getMetadata(MetadataType.TO);
|
||||
if(to != null)
|
||||
if(metadata.getPrimaryAddressTo().hasAlias())
|
||||
{
|
||||
if(to.hasAlias())
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(to.getAlias().toString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(to.getValue()));
|
||||
}
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName()));
|
||||
}
|
||||
else if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
|
||||
}
|
||||
|
||||
Metadata from = metadata.getMetadata(MetadataType.FROM);
|
||||
if(from != null)
|
||||
if(metadata.getPrimaryAddressFrom().hasAlias())
|
||||
{
|
||||
if(from.hasAlias())
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From: " + from.getAlias().toString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From: " + from.getValue()));
|
||||
}
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName()));
|
||||
}
|
||||
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier()));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -301,7 +291,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
int pointer = 0;
|
||||
int messageCounter = 1;
|
||||
int messageCount = (int)Math.ceil((double)xml.length / (double)(mMaxPayloadSize - 6));
|
||||
int messageCount = (int) Math.ceil((double) xml.length / (double) (mMaxPayloadSize - 6));
|
||||
|
||||
if(messageCount > 32)
|
||||
{
|
||||
@@ -317,9 +307,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
|
||||
byte[] payload = new byte[payloadSize + 6];
|
||||
|
||||
payload[1] = (byte)(0x01);
|
||||
payload[3] = (byte)(messageCount & 0xFF);
|
||||
payload[5] = (byte)(messageCounter & 0xFF);
|
||||
payload[1] = (byte) (0x01);
|
||||
payload[3] = (byte) (messageCount & 0xFF);
|
||||
payload[5] = (byte) (messageCounter & 0xFF);
|
||||
|
||||
System.arraycopy(xml, pointer, payload, 6, payloadSize);
|
||||
|
||||
@@ -368,9 +358,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
|
||||
{
|
||||
if(cause instanceof IOException && ((IOException)cause).getMessage().startsWith("Connection reset"))
|
||||
if(cause instanceof IOException && ((IOException) cause).getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
IOException ioe = (IOException)cause;
|
||||
IOException ioe = (IOException) cause;
|
||||
|
||||
if(ioe.getMessage() != null && ioe.getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
@@ -398,12 +388,12 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
{
|
||||
if(object instanceof UltravoxMessage)
|
||||
{
|
||||
UltravoxMessage ultravoxMessage = (UltravoxMessage)object;
|
||||
UltravoxMessage ultravoxMessage = (UltravoxMessage) object;
|
||||
|
||||
switch (ultravoxMessage.getMessageType())
|
||||
switch(ultravoxMessage.getMessageType())
|
||||
{
|
||||
case REQUEST_CIPHER:
|
||||
String cipherKey = ((RequestCipher)ultravoxMessage).getCipher();
|
||||
String cipherKey = ((RequestCipher) ultravoxMessage).getCipher();
|
||||
|
||||
AuthenticateBroadcast authenticateBroadcast = new AuthenticateBroadcast();
|
||||
|
||||
@@ -476,7 +466,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaxPayloadSize = ((NegotiateMaxPayloadSize)ultravoxMessage).getMaximumPayloadSize();
|
||||
mMaxPayloadSize = ((NegotiateMaxPayloadSize) ultravoxMessage).getMaximumPayloadSize();
|
||||
|
||||
ConfigureIcyPublic configureIcyPublic = new ConfigureIcyPublic();
|
||||
configureIcyPublic.setPublic(getConfiguration().isPublic());
|
||||
|
||||
@@ -1,357 +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 audio.metadata;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import alias.id.broadcast.BroadcastChannel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import alias.Alias;
|
||||
import alias.id.priority.Priority;
|
||||
|
||||
public class AudioMetadata implements Listener<Metadata>
|
||||
{
|
||||
protected static final Logger mLog = LoggerFactory.getLogger(AudioMetadata.class);
|
||||
|
||||
private int mSource;
|
||||
private Map<MetadataType, Metadata> mMetadata = new HashMap<>();
|
||||
private boolean mUpdated = false;
|
||||
|
||||
/* Channel Selected == highest priority */
|
||||
private boolean mSelected = false;
|
||||
|
||||
/* Call Priority */
|
||||
private int mPriority = Priority.DEFAULT_PRIORITY;
|
||||
|
||||
/* Indicates if the overall source is recordable */
|
||||
private boolean mSourceRecordable = false;
|
||||
|
||||
/* Indicates the current recordable state */
|
||||
private boolean mRecordable = false;
|
||||
|
||||
/* Indicates the current streamable state */
|
||||
private boolean mStreamable = false;
|
||||
|
||||
/* A unique identifier for this metadata */
|
||||
private String mIdentifier;
|
||||
|
||||
public AudioMetadata(int source, boolean recordable)
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
setIdentifier(mSource);
|
||||
|
||||
mSourceRecordable = recordable;
|
||||
|
||||
setRecordable(mSourceRecordable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique identifier for this audio metadata that contains the
|
||||
* source id and optionally the TO metadata string.
|
||||
*/
|
||||
public String getIdentifier()
|
||||
{
|
||||
return mIdentifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(int source)
|
||||
{
|
||||
setIdentifier(source, null);
|
||||
}
|
||||
|
||||
public void setIdentifier(int source, String id)
|
||||
{
|
||||
mIdentifier = "SRC:" + source + " ID:" + (id == null ? "UNKNOWN" : id);
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the current audio metadata.
|
||||
*/
|
||||
public AudioMetadata copyOf()
|
||||
{
|
||||
AudioMetadata copy = new AudioMetadata(mSource, mSourceRecordable);
|
||||
|
||||
copy.mPriority = mPriority;
|
||||
copy.mSelected = mSelected;
|
||||
copy.mRecordable = mRecordable;
|
||||
copy.mStreamable = mStreamable;
|
||||
|
||||
copy.mMetadata.putAll(mMetadata);
|
||||
copy.mUpdated = mUpdated;
|
||||
copy.mIdentifier = new String(mIdentifier);
|
||||
|
||||
mUpdated = false;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any accumulated temporal metadata and returns to a default set.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
//Reset recordable state, identifier and audio call priority levels and reprocess the metadata
|
||||
mRecordable = mSourceRecordable;
|
||||
mStreamable = false;
|
||||
setIdentifier(mSource);
|
||||
mPriority = Priority.DEFAULT_PRIORITY;
|
||||
|
||||
List<MetadataType> toRemove = new ArrayList<>();
|
||||
|
||||
for (MetadataType type : mMetadata.keySet())
|
||||
{
|
||||
Metadata metadata = mMetadata.get(type);
|
||||
|
||||
if (metadata != null)
|
||||
{
|
||||
if (metadata.isTemporal())
|
||||
{
|
||||
toRemove.add(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
processMetadata(metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (MetadataType type : toRemove)
|
||||
{
|
||||
mMetadata.remove(type);
|
||||
}
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
private void processMetadata(Metadata metadata)
|
||||
{
|
||||
if (metadata.hasAlias())
|
||||
{
|
||||
Alias alias = metadata.getAlias();
|
||||
|
||||
if (metadata.getMetadataType() == MetadataType.FROM || metadata.getMetadataType() == MetadataType.TO)
|
||||
{
|
||||
if (!alias.isRecordable())
|
||||
{
|
||||
mRecordable = false;
|
||||
}
|
||||
|
||||
if (alias.isStreamable())
|
||||
{
|
||||
mStreamable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata.getMetadataType() == MetadataType.TO)
|
||||
{
|
||||
setIdentifier(mSource, metadata.getValue());
|
||||
}
|
||||
|
||||
if (alias != null && alias.getCallPriority() < mPriority)
|
||||
{
|
||||
mPriority = alias.getCallPriority();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this audio metadata contains updated information. The flag
|
||||
* will only be set when new data is added and will be reset by a copyOf()
|
||||
* method invocation.
|
||||
*/
|
||||
public boolean isUpdated()
|
||||
{
|
||||
return mUpdated;
|
||||
}
|
||||
|
||||
public void setUpdated(boolean updated)
|
||||
{
|
||||
mUpdated = updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the metadata. Any temporal metadata will be removed when the
|
||||
* dispose() method is invoked.
|
||||
*/
|
||||
@Override
|
||||
public void receive(Metadata metadata)
|
||||
{
|
||||
if (metadata.isReset())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
Metadata existing = mMetadata.get(metadata.getMetadataType());
|
||||
|
||||
if (existing == null || !existing.equals(metadata))
|
||||
{
|
||||
mMetadata.put(metadata.getMetadataType(), metadata);
|
||||
processMetadata(metadata);
|
||||
setUpdated(true);
|
||||
}
|
||||
}
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete set of metadata
|
||||
*/
|
||||
public Map<MetadataType, Metadata> getMetadata()
|
||||
{
|
||||
return mMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata object matching the type or null
|
||||
*/
|
||||
public Metadata getMetadata(MetadataType type)
|
||||
{
|
||||
return mMetadata.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Source channel ID
|
||||
*/
|
||||
public void setSource(int source)
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
public int getSource()
|
||||
{
|
||||
return mSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the priority of this audio packet within the defined min/max priority range
|
||||
*/
|
||||
public void setPriority(int priority)
|
||||
{
|
||||
mPriority = priority;
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the priority of this audio metadata
|
||||
*
|
||||
* @return - priority of audio packet where lower numbers are higher priority
|
||||
*/
|
||||
public int getPriority()
|
||||
{
|
||||
return mPriority;
|
||||
}
|
||||
|
||||
public boolean isDoNotMonitor()
|
||||
{
|
||||
return mPriority == Priority.DO_NOT_MONITOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selected audio channel. A selected channel will override the priority
|
||||
* level so that the audio can be listened to immediately.
|
||||
*/
|
||||
public void setSelected(boolean selected)
|
||||
{
|
||||
mSelected = selected;
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
public boolean isSelected()
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if audio associated with this metadata is recordable.
|
||||
*/
|
||||
public boolean isRecordable()
|
||||
{
|
||||
return mRecordable;
|
||||
}
|
||||
|
||||
public void setRecordable(boolean recordable)
|
||||
{
|
||||
mRecordable = recordable;
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the audio associated with this metadata is streamable
|
||||
*/
|
||||
public boolean isStreamable()
|
||||
{
|
||||
return mStreamable;
|
||||
}
|
||||
|
||||
public Collection<BroadcastChannel> getBroadcastChannels()
|
||||
{
|
||||
Set<BroadcastChannel> broadcastChannels = new TreeSet<>();
|
||||
|
||||
for(Metadata metadata: mMetadata.values())
|
||||
{
|
||||
if(metadata.hasAlias() && metadata.getAlias().isStreamable())
|
||||
{
|
||||
Alias alias = metadata.getAlias();
|
||||
|
||||
broadcastChannels.addAll(alias.getBroadcastChannels());
|
||||
}
|
||||
}
|
||||
|
||||
return broadcastChannels;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Audio Metadata - source:");
|
||||
sb.append(getSource());
|
||||
sb.append(" priority:");
|
||||
sb.append(getPriority());
|
||||
sb.append(" updated:" + isUpdated());
|
||||
sb.append(" ");
|
||||
|
||||
for (Entry<MetadataType, Metadata> entry : getMetadata().entrySet())
|
||||
{
|
||||
sb.append(entry.getValue().getKey());
|
||||
sb.append(":");
|
||||
sb.append(entry.getValue().getValue());
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package audio.metadata;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
public interface IMetadataListener
|
||||
{
|
||||
public Listener<Metadata> getMetadataListener();
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package audio.metadata;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
public interface IMetadataProvider
|
||||
{
|
||||
public void setMetadataListener( Listener<Metadata> listener );
|
||||
public void removeMetadataListener();
|
||||
}
|
||||
@@ -1,162 +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 audio.metadata;
|
||||
|
||||
import alias.Alias;
|
||||
|
||||
public class Metadata
|
||||
{
|
||||
private MetadataType mMetadataType;
|
||||
private String mValue;
|
||||
private Alias mValueAlias;
|
||||
private boolean mTemporal;
|
||||
|
||||
/**
|
||||
* Constucts a metadata object with the temporal settings. Temporal
|
||||
* indicates that this metadata will be removed at the end of a reset
|
||||
* event, or call end event.
|
||||
*/
|
||||
public Metadata( MetadataType metadataType, String value, Alias alias, boolean temporal )
|
||||
{
|
||||
mMetadataType = metadataType;
|
||||
mValue = value;
|
||||
mValueAlias = alias;
|
||||
mTemporal = temporal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constucts a metadata object with the temporal settings. Temporal
|
||||
* indicates that this metadata will be removed at the end of a reset
|
||||
* event, or call end event.
|
||||
*/
|
||||
public Metadata( MetadataType metadataType, String value, boolean temporal )
|
||||
{
|
||||
this( metadataType, value, null, temporal );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constucts a non-temporal metadata object
|
||||
*/
|
||||
public Metadata( MetadataType metadataType, String value, Alias alias )
|
||||
{
|
||||
this( metadataType, value, alias, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constucts a non-temporal metadata object
|
||||
*/
|
||||
public Metadata( MetadataType metadataType, String value )
|
||||
{
|
||||
this( metadataType, value, null, false );
|
||||
}
|
||||
|
||||
public MetadataType getMetadataType()
|
||||
{
|
||||
return mMetadataType;
|
||||
}
|
||||
|
||||
public String getKey()
|
||||
{
|
||||
return mMetadataType.getLabel();
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public Alias getAlias()
|
||||
{
|
||||
return mValueAlias;
|
||||
}
|
||||
|
||||
public boolean hasAlias()
|
||||
{
|
||||
return mValueAlias != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this piece of metadata is only valid for the duration of
|
||||
* a call event and should be removed during a reset
|
||||
*/
|
||||
public boolean isTemporal()
|
||||
{
|
||||
return mTemporal;
|
||||
}
|
||||
|
||||
public boolean isReset()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMetadataType.getLabel() );
|
||||
sb.append( ":" );
|
||||
sb.append( mValue );
|
||||
sb.append( " Alias:" );
|
||||
sb.append( mValueAlias == null ? "null" : getAlias().getName() );
|
||||
sb.append( " [" );
|
||||
sb.append( mMetadataType.name() );
|
||||
sb.append( "] temporal:" );
|
||||
sb.append( mTemporal );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean equals( Metadata other )
|
||||
{
|
||||
if( mMetadataType != other.getMetadataType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( mTemporal != other.isTemporal() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( mValue != null && other.getValue() != null &&
|
||||
!mValue.contentEquals( other.getValue() ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ( mValue == null && other.getValue() != null ) ||
|
||||
( mValue != null && other.getValue() == null ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( mValueAlias != null && other.getAlias() != null &&
|
||||
!mValueAlias.getName().contentEquals( other.getAlias().getName() ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ( mValueAlias == null && other.getAlias() != null ) ||
|
||||
( mValueAlias != null && other.getAlias() == null ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package audio.metadata;
|
||||
|
||||
public class MetadataReset extends Metadata
|
||||
{
|
||||
public MetadataReset()
|
||||
{
|
||||
super( MetadataType.TEMPORAL_RESET, "reset", true );
|
||||
}
|
||||
|
||||
public boolean isReset()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package audio.metadata;
|
||||
|
||||
public enum MetadataType
|
||||
{
|
||||
CHANNEL_NUMBER( "Channel Number" ),
|
||||
CHANNEL_NAME( "Channel Name" ),
|
||||
DETAILS( "Details" ),
|
||||
ESN( "ESN" ),
|
||||
FLEETSYNC( "Fleetsync" ),
|
||||
FREQUENCY( "Frequency" ),
|
||||
FROM( "From" ),
|
||||
MDC1200( "MDC-1200" ),
|
||||
MOBILE_ID( "Mobile ID" ),
|
||||
MPT1327( "MPT-1327" ),
|
||||
PROTOCOL( "Protocol" ),
|
||||
SITE_ID( "Site ID" ),
|
||||
STATUS( "Status" ),
|
||||
SYSTEM( "System" ),
|
||||
TO( "To" ),
|
||||
UNIQUE_ID( "Unique ID" ),
|
||||
|
||||
TEMPORAL_RESET( "Reset" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private MetadataType( String label )
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,34 @@
|
||||
/*******************************************************************************
|
||||
* 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-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 audio.output;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import audio.AudioEvent;
|
||||
import audio.AudioPacket;
|
||||
import audio.AudioPacket.Type;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import source.mixer.MixerChannel;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.BooleanControl;
|
||||
@@ -35,418 +40,412 @@ import javax.sound.sampled.LineListener;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.Mixer;
|
||||
import javax.sound.sampled.SourceDataLine;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import source.mixer.MixerChannel;
|
||||
import audio.AudioEvent;
|
||||
import audio.AudioPacket;
|
||||
import audio.AudioPacket.Type;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( AudioOutput.class );
|
||||
|
||||
private LinkedTransferQueue<AudioPacket> mBuffer = new LinkedTransferQueue<>();
|
||||
private int mBufferStartThreshold;
|
||||
private int mBufferStopThreshold;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AudioOutput.class);
|
||||
|
||||
private Listener<AudioMetadata> mAudioMetadataListener;
|
||||
private Broadcaster<AudioEvent> mAudioEventBroadcaster = new Broadcaster<>();
|
||||
private LinkedTransferQueue<AudioPacket> mBuffer = new LinkedTransferQueue<>();
|
||||
private int mBufferStartThreshold;
|
||||
private int mBufferStopThreshold;
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture<?> mProcessorTask;
|
||||
private Listener<Metadata> mMetadataListener;
|
||||
private Broadcaster<AudioEvent> mAudioEventBroadcaster = new Broadcaster<>();
|
||||
|
||||
private SourceDataLine mOutput;
|
||||
private Mixer mMixer;
|
||||
private MixerChannel mMixerChannel;
|
||||
private FloatControl mGainControl;
|
||||
private BooleanControl mMuteControl;
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture<?> mProcessorTask;
|
||||
|
||||
private AudioEvent mAudioStartEvent;
|
||||
private AudioEvent mAudioStopEvent;
|
||||
private SourceDataLine mOutput;
|
||||
private Mixer mMixer;
|
||||
private MixerChannel mMixerChannel;
|
||||
private FloatControl mGainControl;
|
||||
private BooleanControl mMuteControl;
|
||||
|
||||
private boolean mCanProcessAudio = false;
|
||||
private long mLastActivity = System.currentTimeMillis();
|
||||
private AudioEvent mAudioStartEvent;
|
||||
private AudioEvent mAudioStopEvent;
|
||||
|
||||
/**
|
||||
* Single audio channel playback with automatic starting and stopping of the
|
||||
* underlying sourcedataline specified by the mixer and mixer channel
|
||||
* arguments.
|
||||
*
|
||||
* Maintains an internal non-blocking audio packet queue and processes this
|
||||
* queue 25 times a second (every 40 ms).
|
||||
*
|
||||
* @param threadPoolManager for assigning buffer processing schedule task
|
||||
* @param mixer to obtain source data line
|
||||
* @param mixerChannel either mono or left/right stereo
|
||||
* @param audioFormat to use during playback
|
||||
* @param lineInfo to use when obtaining the source data line
|
||||
* @param requestedBufferSize of approximately 1 second of audio
|
||||
*/
|
||||
public AudioOutput( ThreadPoolManager threadPoolManager,
|
||||
Mixer mixer,
|
||||
MixerChannel mixerChannel,
|
||||
AudioFormat audioFormat,
|
||||
Line.Info lineInfo,
|
||||
int requestedBufferSize )
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mMixer = mixer;
|
||||
mMixerChannel = mixerChannel;
|
||||
|
||||
try
|
||||
{
|
||||
mOutput = (SourceDataLine)mMixer.getLine( lineInfo );
|
||||
|
||||
if( mOutput != null )
|
||||
{
|
||||
mOutput.open( audioFormat, requestedBufferSize );
|
||||
|
||||
//Start threshold: buffer is full with 10% or less of capacity remaining
|
||||
mBufferStartThreshold = (int)( mOutput.getBufferSize() * 0.10 );
|
||||
private boolean mCanProcessAudio = false;
|
||||
private long mLastActivity = System.currentTimeMillis();
|
||||
|
||||
//Stop threshold: buffer is empty with 90% or more capacity available
|
||||
mBufferStopThreshold = (int)( mOutput.getBufferSize() * 0.90 );
|
||||
/**
|
||||
* Single audio channel playback with automatic starting and stopping of the
|
||||
* underlying sourcedataline specified by the mixer and mixer channel
|
||||
* arguments.
|
||||
*
|
||||
* Maintains an internal non-blocking audio packet queue and processes this
|
||||
* queue 25 times a second (every 40 ms).
|
||||
*
|
||||
* @param threadPoolManager for assigning buffer processing schedule task
|
||||
* @param mixer to obtain source data line
|
||||
* @param mixerChannel either mono or left/right stereo
|
||||
* @param audioFormat to use during playback
|
||||
* @param lineInfo to use when obtaining the source data line
|
||||
* @param requestedBufferSize of approximately 1 second of audio
|
||||
*/
|
||||
public AudioOutput(ThreadPoolManager threadPoolManager,
|
||||
Mixer mixer,
|
||||
MixerChannel mixerChannel,
|
||||
AudioFormat audioFormat,
|
||||
Line.Info lineInfo,
|
||||
int requestedBufferSize)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mMixer = mixer;
|
||||
mMixerChannel = mixerChannel;
|
||||
|
||||
try
|
||||
{
|
||||
mOutput = (SourceDataLine) mMixer.getLine(lineInfo);
|
||||
|
||||
if(mOutput != null)
|
||||
{
|
||||
mOutput.open(audioFormat, requestedBufferSize);
|
||||
|
||||
//Start threshold: buffer is full with 10% or less of capacity remaining
|
||||
mBufferStartThreshold = (int) (mOutput.getBufferSize() * 0.10);
|
||||
|
||||
//Stop threshold: buffer is empty with 90% or more capacity available
|
||||
mBufferStopThreshold = (int) (mOutput.getBufferSize() * 0.90);
|
||||
|
||||
mOutput.addLineListener(this);
|
||||
|
||||
if(mOutput != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Control gain = mOutput.getControl(FloatControl.Type.MASTER_GAIN);
|
||||
mGainControl = (FloatControl) gain;
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
mLog.warn("Couldn't obtain MASTER GAIN control for stereo line [" +
|
||||
mixer.getMixerInfo().getName() + " | " + getChannelName() + "]");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Control mute = mOutput.getControl(BooleanControl.Type.MUTE);
|
||||
mMuteControl = (BooleanControl) mute;
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
mLog.warn("Couldn't obtain MUTE control for stereo line [" +
|
||||
mixer.getMixerInfo().getName() + " | " + getChannelName() + "]");
|
||||
}
|
||||
|
||||
mOutput.addLineListener( this );
|
||||
|
||||
if( mOutput != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
Control gain = mOutput.getControl( FloatControl.Type.MASTER_GAIN );
|
||||
mGainControl = (FloatControl)gain;
|
||||
}
|
||||
catch( IllegalArgumentException iae )
|
||||
{
|
||||
mLog.warn( "Couldn't obtain MASTER GAIN control for stereo line [" +
|
||||
mixer.getMixerInfo().getName() + " | " + getChannelName() + "]" );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Control mute = mOutput.getControl( BooleanControl.Type.MUTE );
|
||||
mMuteControl = (BooleanControl)mute;
|
||||
}
|
||||
catch( IllegalArgumentException iae )
|
||||
{
|
||||
mLog.warn( "Couldn't obtain MUTE control for stereo line [" +
|
||||
mixer.getMixerInfo().getName() + " | " + getChannelName() + "]" );
|
||||
}
|
||||
|
||||
/* Run the queue processor task every 40 milliseconds or 25 times a second */
|
||||
mProcessorTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.AUDIO_PROCESSING, new BufferProcessor(),
|
||||
40, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
|
||||
mAudioStartEvent = new AudioEvent( AudioEvent.Type.AUDIO_STARTED,
|
||||
getChannelName() );
|
||||
mAudioStopEvent = new AudioEvent( AudioEvent.Type.AUDIO_STOPPED,
|
||||
getChannelName() );
|
||||
mProcessorTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.AUDIO_PROCESSING, new BufferProcessor(),
|
||||
40, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
mCanProcessAudio = true;
|
||||
}
|
||||
}
|
||||
catch ( LineUnavailableException e )
|
||||
{
|
||||
mLog.error( "Couldn't obtain audio source data line for "
|
||||
+ "audio output - mixer [" + mMixer.getMixerInfo().getName() + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
broadcast( new AudioEvent( AudioEvent.Type.AUDIO_STOPPED, getChannelName() ) );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mCanProcessAudio = false;
|
||||
mAudioStartEvent = new AudioEvent(AudioEvent.Type.AUDIO_STARTED,
|
||||
getChannelName());
|
||||
mAudioStopEvent = new AudioEvent(AudioEvent.Type.AUDIO_STOPPED,
|
||||
getChannelName());
|
||||
|
||||
if( mProcessorTask != null && mThreadPoolManager != null )
|
||||
{
|
||||
mThreadPoolManager.cancel( mProcessorTask );
|
||||
}
|
||||
|
||||
mThreadPoolManager = null;
|
||||
mProcessorTask = null;
|
||||
mCanProcessAudio = true;
|
||||
}
|
||||
}
|
||||
catch(LineUnavailableException e)
|
||||
{
|
||||
mLog.error("Couldn't obtain audio source data line for "
|
||||
+ "audio output - mixer [" + mMixer.getMixerInfo().getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
mBuffer.clear();
|
||||
public void reset()
|
||||
{
|
||||
broadcast(new AudioEvent(AudioEvent.Type.AUDIO_STOPPED, getChannelName()));
|
||||
}
|
||||
|
||||
mAudioEventBroadcaster.dispose();
|
||||
mAudioEventBroadcaster = null;
|
||||
mAudioMetadataListener = null;
|
||||
|
||||
if( mOutput != null )
|
||||
{
|
||||
mOutput.close();
|
||||
}
|
||||
|
||||
mOutput = null;
|
||||
mGainControl = null;
|
||||
mMuteControl = null;
|
||||
}
|
||||
public void dispose()
|
||||
{
|
||||
mCanProcessAudio = false;
|
||||
|
||||
/**
|
||||
* Converts the audio packet data into a byte buffer format appropriate for
|
||||
* the underlying source data line.
|
||||
*/
|
||||
protected abstract ByteBuffer convert( AudioPacket packet );
|
||||
if(mProcessorTask != null && mThreadPoolManager != null)
|
||||
{
|
||||
mThreadPoolManager.cancel(mProcessorTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio output channel name
|
||||
*/
|
||||
public String getChannelName()
|
||||
{
|
||||
return mMixerChannel.getLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixer Channel for this audio output
|
||||
*/
|
||||
protected MixerChannel getMixerChannel()
|
||||
{
|
||||
return mMixerChannel;
|
||||
}
|
||||
mThreadPoolManager = null;
|
||||
mProcessorTask = null;
|
||||
|
||||
/**
|
||||
* Registers a single listener to receive audio start and audio stop events
|
||||
*/
|
||||
public void addAudioEventListener( Listener<AudioEvent> listener )
|
||||
{
|
||||
mAudioEventBroadcaster.addListener( listener );
|
||||
}
|
||||
|
||||
public void removeAudioEventListener( Listener<AudioEvent> listener )
|
||||
{
|
||||
mAudioEventBroadcaster.removeListener( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts an audio event to the registered listener
|
||||
*/
|
||||
private void broadcast( AudioEvent audioEvent )
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast( audioEvent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single listener to receive the audio metadata from each
|
||||
* audio packet
|
||||
*/
|
||||
public void setAudioMetadataListener( Listener<AudioMetadata> listener )
|
||||
{
|
||||
mAudioMetadataListener = listener;
|
||||
}
|
||||
|
||||
public void removeAudioMetadataListener()
|
||||
{
|
||||
mAudioMetadataListener = null;
|
||||
}
|
||||
mBuffer.clear();
|
||||
|
||||
/**
|
||||
* Broadcasts audio metadata to the registered listener
|
||||
*/
|
||||
private void broadcast( AudioMetadata metadata )
|
||||
{
|
||||
if( mAudioMetadataListener != null )
|
||||
{
|
||||
mAudioMetadataListener.receive( metadata );
|
||||
}
|
||||
}
|
||||
mAudioEventBroadcaster.dispose();
|
||||
mAudioEventBroadcaster = null;
|
||||
mMetadataListener = null;
|
||||
|
||||
/**
|
||||
* Timestamp of either last buffer received or last buffer processed
|
||||
*/
|
||||
public long getLastActivityTimestamp()
|
||||
{
|
||||
return mLastActivity;
|
||||
}
|
||||
if(mOutput != null)
|
||||
{
|
||||
mOutput.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last activity timestamp to current system time
|
||||
*/
|
||||
public void updateTimestamp()
|
||||
{
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( AudioPacket packet )
|
||||
{
|
||||
if( mCanProcessAudio )
|
||||
{
|
||||
//Update the activity timestamp so that this audio output doesn't
|
||||
//get disconnected before it starts processing the audio stream
|
||||
updateTimestamp();
|
||||
|
||||
mBuffer.add( packet );
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor implements Runnable
|
||||
{
|
||||
private AtomicBoolean mProcessing = new AtomicBoolean();
|
||||
|
||||
public BufferProcessor()
|
||||
{
|
||||
}
|
||||
mOutput = null;
|
||||
mGainControl = null;
|
||||
mMuteControl = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
/**
|
||||
* Converts the audio packet data into a byte buffer format appropriate for
|
||||
* the underlying source data line.
|
||||
*/
|
||||
protected abstract ByteBuffer convert(AudioPacket packet);
|
||||
|
||||
/**
|
||||
* Audio output channel name
|
||||
*/
|
||||
public String getChannelName()
|
||||
{
|
||||
return mMixerChannel.getLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixer Channel for this audio output
|
||||
*/
|
||||
protected MixerChannel getMixerChannel()
|
||||
{
|
||||
return mMixerChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single listener to receive audio start and audio stop events
|
||||
*/
|
||||
public void addAudioEventListener(Listener<AudioEvent> listener)
|
||||
{
|
||||
mAudioEventBroadcaster.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeAudioEventListener(Listener<AudioEvent> listener)
|
||||
{
|
||||
mAudioEventBroadcaster.removeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts an audio event to the registered listener
|
||||
*/
|
||||
private void broadcast(AudioEvent audioEvent)
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast(audioEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single listener to receive the audio metadata from each
|
||||
* audio packet
|
||||
*/
|
||||
public void setMetadataListener(Listener<Metadata> listener)
|
||||
{
|
||||
mMetadataListener = listener;
|
||||
}
|
||||
|
||||
public void removeAudioMetadataListener()
|
||||
{
|
||||
mMetadataListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts audio metadata to the registered listener
|
||||
*/
|
||||
private void broadcast(Metadata metadata)
|
||||
{
|
||||
if(mMetadataListener != null)
|
||||
{
|
||||
mMetadataListener.receive(metadata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of either last buffer received or last buffer processed
|
||||
*/
|
||||
public long getLastActivityTimestamp()
|
||||
{
|
||||
return mLastActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last activity timestamp to current system time
|
||||
*/
|
||||
public void updateTimestamp()
|
||||
{
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(AudioPacket packet)
|
||||
{
|
||||
if(mCanProcessAudio)
|
||||
{
|
||||
//Update the activity timestamp so that this audio output doesn't
|
||||
//get disconnected before it starts processing the audio stream
|
||||
updateTimestamp();
|
||||
|
||||
mBuffer.add(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor implements Runnable
|
||||
{
|
||||
private AtomicBoolean mProcessing = new AtomicBoolean();
|
||||
|
||||
public BufferProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
/* The processing flag ensures that only one instance of the
|
||||
* processor can run at any given time */
|
||||
if( mProcessing.compareAndSet( false, true ) )
|
||||
{
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
mBuffer.drainTo( packets );
|
||||
|
||||
for( AudioPacket packet: packets )
|
||||
{
|
||||
if( packet.getType() == Type.AUDIO )
|
||||
{
|
||||
broadcast( packet.getAudioMetadata() );
|
||||
if(mProcessing.compareAndSet(false, true))
|
||||
{
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
ByteBuffer buffer = convert( packet );
|
||||
|
||||
int wrote = 0;
|
||||
|
||||
if( !mOutput.isRunning() )
|
||||
{
|
||||
int toWrite = mOutput.available();
|
||||
|
||||
if( toWrite > buffer.array().length )
|
||||
{
|
||||
toWrite = buffer.array().length;
|
||||
}
|
||||
|
||||
//Top off the buffer and check if we can start it
|
||||
wrote += mOutput.write( buffer.array(), 0, toWrite );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
mBuffer.drainTo(packets);
|
||||
|
||||
if( mOutput.isRunning() && wrote < buffer.array().length )
|
||||
{
|
||||
//Blocking write
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
buffer.array().length - wrote );
|
||||
}
|
||||
|
||||
updateTimestamp();
|
||||
}
|
||||
}
|
||||
for(AudioPacket packet : packets)
|
||||
{
|
||||
if(packet.getType() == Type.AUDIO)
|
||||
{
|
||||
broadcast(packet.getMetadata());
|
||||
|
||||
checkStop();
|
||||
|
||||
mProcessing.set( false );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Error while processing audio buffers", e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts audio playback once audio buffer is almost full and remaining
|
||||
* capacity falls below the start threshold.
|
||||
*/
|
||||
private void checkStart()
|
||||
{
|
||||
if( mCanProcessAudio &&
|
||||
!mOutput.isRunning() &&
|
||||
mOutput.available() <= mBufferStartThreshold )
|
||||
{
|
||||
mOutput.start();
|
||||
}
|
||||
}
|
||||
ByteBuffer buffer = convert(packet);
|
||||
|
||||
/**
|
||||
* Stops audio playback and drains the audio buffer to empty when the
|
||||
* audio buffer is mostly empty and the available buffer capacity
|
||||
* exceeds the stop threshold
|
||||
*/
|
||||
private void checkStop()
|
||||
{
|
||||
if( mCanProcessAudio &&
|
||||
mOutput.isRunning() &&
|
||||
mOutput.available() >= mBufferStopThreshold )
|
||||
{
|
||||
mOutput.drain();
|
||||
mOutput.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mute state for this audio output channel
|
||||
*/
|
||||
public void setMuted( boolean muted )
|
||||
{
|
||||
if( mMuteControl != null )
|
||||
{
|
||||
mMuteControl.setValue( muted );
|
||||
|
||||
broadcast( new AudioEvent( muted ? AudioEvent.Type.AUDIO_MUTED :
|
||||
AudioEvent.Type.AUDIO_UNMUTED, getChannelName() ) );
|
||||
}
|
||||
}
|
||||
int wrote = 0;
|
||||
|
||||
/**
|
||||
* Current mute state for this audio output channel
|
||||
*/
|
||||
public boolean isMuted()
|
||||
{
|
||||
if( mMuteControl != null )
|
||||
{
|
||||
return mMuteControl.getValue();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if(!mOutput.isRunning())
|
||||
{
|
||||
int toWrite = mOutput.available();
|
||||
|
||||
/**
|
||||
* Gain/volume control for this audio output channel, if one is available.
|
||||
*/
|
||||
public FloatControl getGainControl()
|
||||
{
|
||||
return mGainControl;
|
||||
}
|
||||
if(toWrite > buffer.array().length)
|
||||
{
|
||||
toWrite = buffer.array().length;
|
||||
}
|
||||
|
||||
public boolean hasGainControl()
|
||||
{
|
||||
return mGainControl != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors the source data line playback state and broadcasts audio events
|
||||
* to the registered listener as the state changes
|
||||
*/
|
||||
@Override
|
||||
public void update( LineEvent event )
|
||||
{
|
||||
LineEvent.Type type = event.getType();
|
||||
//Top off the buffer and check if we can start it
|
||||
wrote += mOutput.write(buffer.array(), 0, toWrite);
|
||||
|
||||
if( type == LineEvent.Type.START )
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast( mAudioStartEvent );
|
||||
}
|
||||
else if( type == LineEvent.Type.STOP )
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast( mAudioStopEvent );
|
||||
}
|
||||
}
|
||||
checkStart();
|
||||
}
|
||||
|
||||
if(mOutput.isRunning() && wrote < buffer.array().length)
|
||||
{
|
||||
//Blocking write
|
||||
wrote += mOutput.write(buffer.array(), wrote,
|
||||
buffer.array().length - wrote);
|
||||
}
|
||||
|
||||
updateTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
checkStop();
|
||||
|
||||
mProcessing.set(false);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Error while processing audio buffers", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts audio playback once audio buffer is almost full and remaining
|
||||
* capacity falls below the start threshold.
|
||||
*/
|
||||
private void checkStart()
|
||||
{
|
||||
if(mCanProcessAudio &&
|
||||
!mOutput.isRunning() &&
|
||||
mOutput.available() <= mBufferStartThreshold)
|
||||
{
|
||||
mOutput.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops audio playback and drains the audio buffer to empty when the
|
||||
* audio buffer is mostly empty and the available buffer capacity
|
||||
* exceeds the stop threshold
|
||||
*/
|
||||
private void checkStop()
|
||||
{
|
||||
if(mCanProcessAudio &&
|
||||
mOutput.isRunning() &&
|
||||
mOutput.available() >= mBufferStopThreshold)
|
||||
{
|
||||
mOutput.drain();
|
||||
mOutput.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mute state for this audio output channel
|
||||
*/
|
||||
public void setMuted(boolean muted)
|
||||
{
|
||||
if(mMuteControl != null)
|
||||
{
|
||||
mMuteControl.setValue(muted);
|
||||
|
||||
broadcast(new AudioEvent(muted ? AudioEvent.Type.AUDIO_MUTED :
|
||||
AudioEvent.Type.AUDIO_UNMUTED, getChannelName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Current mute state for this audio output channel
|
||||
*/
|
||||
public boolean isMuted()
|
||||
{
|
||||
if(mMuteControl != null)
|
||||
{
|
||||
return mMuteControl.getValue();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain/volume control for this audio output channel, if one is available.
|
||||
*/
|
||||
public FloatControl getGainControl()
|
||||
{
|
||||
return mGainControl;
|
||||
}
|
||||
|
||||
public boolean hasGainControl()
|
||||
{
|
||||
return mGainControl != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors the source data line playback state and broadcasts audio events
|
||||
* to the registered listener as the state changes
|
||||
*/
|
||||
@Override
|
||||
public void update(LineEvent event)
|
||||
{
|
||||
LineEvent.Type type = event.getType();
|
||||
|
||||
if(type == LineEvent.Type.START)
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast(mAudioStartEvent);
|
||||
}
|
||||
else if(type == LineEvent.Type.STOP)
|
||||
{
|
||||
mAudioEventBroadcaster.broadcast(mAudioStopEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public enum Attribute
|
||||
CHANNEL_CONFIGURATION_LABEL_1,
|
||||
CHANNEL_CONFIGURATION_LABEL_2,
|
||||
CHANNEL_FREQUENCY,
|
||||
CHANNEL_ID,
|
||||
CHANNEL_FREQUENCY_LABEL,
|
||||
CHANNEL_STATE,
|
||||
MESSAGE,
|
||||
MESSAGE_TYPE,
|
||||
@@ -31,32 +31,7 @@ public enum Attribute
|
||||
NETWORK_ID_2,
|
||||
PRIMARY_ADDRESS_FROM,
|
||||
PRIMARY_ADDRESS_TO,
|
||||
PRIMARY_DECODER_TYPE,
|
||||
SECONDARY_ADDRESS_FROM,
|
||||
SECONDARY_ADDRESS_TO,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//TODO: remove all attributes below here ********************
|
||||
|
||||
CHANNEL_NUMBER,
|
||||
CHANNEL_NAME,
|
||||
CHANNEL_SITE_NUMBER,
|
||||
CHANNEL_SITE_NUMBER_ALIAS,
|
||||
DESCRIPTION,
|
||||
FROM_TALKGROUP,
|
||||
FROM_TALKGROUP_ALIAS,
|
||||
FROM_TALKGROUP_TYPE,
|
||||
NAC,
|
||||
SITE,
|
||||
SITE_ALIAS,
|
||||
SITE_NAME,
|
||||
SOURCE,
|
||||
SYSTEM,
|
||||
SYSTEM_NAME,
|
||||
TO_TALKGROUP,
|
||||
TO_TALKGROUP_ALIAS,
|
||||
TO_TALKGROUP_TYPE;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
package channel.metadata;
|
||||
|
||||
import alias.Alias;
|
||||
import module.decode.DecoderType;
|
||||
|
||||
public class AttributeChangeRequest<T>
|
||||
{
|
||||
@@ -89,6 +90,9 @@ public class AttributeChangeRequest<T>
|
||||
return mAlias != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as a String or null if the value is not a String instance.
|
||||
*/
|
||||
public String getStringValue()
|
||||
{
|
||||
if(mValue instanceof String)
|
||||
@@ -99,6 +103,9 @@ public class AttributeChangeRequest<T>
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as a Long or null if the value is not a Long instance.
|
||||
*/
|
||||
public Long getLongValue()
|
||||
{
|
||||
if(mValue instanceof Long)
|
||||
@@ -108,4 +115,17 @@ public class AttributeChangeRequest<T>
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as a DecoderType or null if the value is not a DecoderType instance.
|
||||
*/
|
||||
public DecoderType getDecoderTypeValue()
|
||||
{
|
||||
if(mValue instanceof DecoderType)
|
||||
{
|
||||
return (DecoderType)mValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
|
||||
fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION);
|
||||
break;
|
||||
case CHANNEL_FREQUENCY:
|
||||
case CHANNEL_ID:
|
||||
case CHANNEL_FREQUENCY_LABEL:
|
||||
fireTableCellUpdated(rowIndex, COLUMN_FREQUENCY);
|
||||
break;
|
||||
case CHANNEL_STATE:
|
||||
|
||||
@@ -20,42 +20,86 @@ package channel.metadata;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import icon.IconManager;
|
||||
import icon.IconTableModel;
|
||||
import module.decode.event.CallEventPanel;
|
||||
import module.decode.event.MessageActivityPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.SettingsManager;
|
||||
import spectrum.ChannelSpectrumPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class ChannelMetadataViewer extends JPanel
|
||||
{
|
||||
private ChannelMetadataModel mChannelMetadataModel;
|
||||
private IconTableModel mIconTableModel;
|
||||
private CallEventPanel mCallEventPanel;
|
||||
private MessageActivityPanel mMessageActivityPanel;
|
||||
private ChannelSpectrumPanel mChannelSpectrumPanel;
|
||||
private ChannelMetadataPanel mChannelMetadataPanel;
|
||||
|
||||
/**
|
||||
* GUI panel that combines the currently decoding channels metadata table and viewers for channel details,
|
||||
* messages, events, and spectral view.
|
||||
*/
|
||||
public ChannelMetadataViewer(ChannelMetadataModel channelMetadataModel, IconTableModel iconTableModel)
|
||||
public ChannelMetadataViewer(ChannelProcessingManager channelProcessingManager, IconManager iconManager,
|
||||
SettingsManager settingsManager)
|
||||
{
|
||||
mChannelMetadataModel = channelMetadataModel;
|
||||
mIconTableModel = iconTableModel;
|
||||
mCallEventPanel = new CallEventPanel(iconManager, channelProcessingManager);
|
||||
mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager);
|
||||
mChannelSpectrumPanel = new ChannelSpectrumPanel(settingsManager, channelProcessingManager);
|
||||
mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager.getChannelMetadataModel(),
|
||||
iconManager.getModel());
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "", "[grow,fill]", "[grow,fill]") );
|
||||
|
||||
ChannelMetadataPanel channelMetadataPanel = new ChannelMetadataPanel(mChannelMetadataModel, mIconTableModel);
|
||||
|
||||
JideTabbedPane tabbedPane = new JideTabbedPane();
|
||||
tabbedPane.addTab("Details", new JPanel());
|
||||
tabbedPane.addTab("Events", new JPanel());
|
||||
tabbedPane.addTab("Messages", new JPanel());
|
||||
tabbedPane.addTab("Spectrum", new JPanel());
|
||||
tabbedPane.addTab("Events", mCallEventPanel);
|
||||
tabbedPane.addTab("Messages", mMessageActivityPanel);
|
||||
tabbedPane.addTab("Spectrum", mChannelSpectrumPanel);
|
||||
|
||||
JideSplitPane splitPane = new JideSplitPane(JideSplitPane.VERTICAL_SPLIT);
|
||||
splitPane.add(channelMetadataPanel);
|
||||
splitPane.add(mChannelMetadataPanel);
|
||||
splitPane.add(tabbedPane);
|
||||
|
||||
//TODO: move this change listener to the metadata table view
|
||||
// /**
|
||||
// * Change listener to enable/disable the channel spectrum display
|
||||
// * only when the tab is visible, and a channel has been selected
|
||||
// */
|
||||
// mTabbedPane.addChangeListener(new ChangeListener()
|
||||
// {
|
||||
// @Override
|
||||
// public void stateChanged(ChangeEvent event)
|
||||
// {
|
||||
// int index = mTabbedPane.getSelectedIndex();
|
||||
//
|
||||
// Component component = mTabbedPane.getComponentAt(index);
|
||||
//
|
||||
// if(component instanceof ChannelSpectrumPanel)
|
||||
// {
|
||||
// mChannelSpectrumPanel.setEnabled(true);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mChannelSpectrumPanel.setEnabled(false);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
//TODO: call, message and spectrum should listen to the metadata table now
|
||||
//
|
||||
//
|
||||
// /* Register each of the components to receive channel events when the
|
||||
// * channels are selected or change */
|
||||
// mChannelModel.addListener(mCallEventPanel);
|
||||
// mChannelModel.addListener(mChannelSpectrumPanel);
|
||||
// mChannelModel.addListener(mMessageActivityPanel);
|
||||
|
||||
add(splitPane);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class Metadata
|
||||
|
||||
//Lazily constructed member variables.
|
||||
private Integer mAudioPriority;
|
||||
private Boolean mRecordable;
|
||||
protected Boolean mRecordable;
|
||||
private List<BroadcastChannel> mBroadcastChannels;
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ public class Metadata
|
||||
return mChannelConfigurationLabel1;
|
||||
case CHANNEL_CONFIGURATION_LABEL_2:
|
||||
return mChannelConfigurationLabel2;
|
||||
case CHANNEL_ID:
|
||||
case CHANNEL_FREQUENCY_LABEL:
|
||||
return mChannelFrequencyLabel;
|
||||
case CHANNEL_STATE:
|
||||
return mState.getDisplayValue();
|
||||
|
||||
@@ -47,6 +47,15 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
public void setSelected(boolean selected)
|
||||
{
|
||||
mSelected = selected;
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the recordable flag to the argument value and overrides any recordable settings in the enclosed aliases.
|
||||
*/
|
||||
public void setRecordable(boolean recordable)
|
||||
{
|
||||
mRecordable = recordable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +64,7 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
public void setPrimaryDecoderType(DecoderType decoderType)
|
||||
{
|
||||
mPrimaryDecoderType = decoderType;
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,9 +95,9 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
}
|
||||
broadcast(Attribute.CHANNEL_FREQUENCY);
|
||||
break;
|
||||
case CHANNEL_ID:
|
||||
case CHANNEL_FREQUENCY_LABEL:
|
||||
mChannelFrequencyLabel = request.getStringValue();
|
||||
broadcast(Attribute.CHANNEL_ID);
|
||||
broadcast(Attribute.CHANNEL_FREQUENCY_LABEL);
|
||||
break;
|
||||
case MESSAGE:
|
||||
mMessage = request.getStringValue();
|
||||
@@ -117,6 +127,10 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
mPrimaryAddressTo.setAlias(request.getAlias());
|
||||
broadcast(Attribute.PRIMARY_ADDRESS_TO);
|
||||
break;
|
||||
case PRIMARY_DECODER_TYPE:
|
||||
mPrimaryDecoderType = request.getDecoderTypeValue();
|
||||
broadcast(Attribute.PRIMARY_DECODER_TYPE);
|
||||
break;
|
||||
case SECONDARY_ADDRESS_FROM:
|
||||
mSecondaryAddressFrom.setIdentifier(request.getStringValue());
|
||||
mSecondaryAddressFrom.setAlias(request.getAlias());
|
||||
@@ -135,6 +149,8 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
throw new IllegalArgumentException("Unrecognized Metadata Attribute: " +
|
||||
request.getAttribute().name());
|
||||
}
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,6 +194,8 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
mSecondaryAddressTo.reset();
|
||||
broadcast(Attribute.SECONDARY_ADDRESS_TO);
|
||||
}
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,7 +220,7 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
if(hasChannelFrequencyLabel())
|
||||
{
|
||||
mChannelFrequencyLabel = null;
|
||||
broadcast(Attribute.CHANNEL_ID);
|
||||
broadcast(Attribute.CHANNEL_FREQUENCY_LABEL);
|
||||
}
|
||||
|
||||
if(hasChannelFrequency())
|
||||
@@ -211,6 +229,12 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
broadcast(Attribute.CHANNEL_FREQUENCY);
|
||||
}
|
||||
|
||||
if(hasPrimaryDecoderType())
|
||||
{
|
||||
mPrimaryDecoderType = null;
|
||||
broadcast(Attribute.PRIMARY_DECODER_TYPE);
|
||||
}
|
||||
|
||||
if(mNetworkID1.hasIdentifier())
|
||||
{
|
||||
mNetworkID1.reset();
|
||||
@@ -222,6 +246,8 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
|
||||
mNetworkID2.reset();
|
||||
broadcast(Attribute.NETWORK_ID_2);
|
||||
}
|
||||
|
||||
mUpdated = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,317 +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 channel.state;
|
||||
|
||||
import audio.AudioPanel;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import icon.IconManager;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.ColorSettingMenuItem;
|
||||
import settings.ColorSettingResetMenuItem;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Gui wrapper for the list of currently processing primary channels
|
||||
*/
|
||||
public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Map<Channel, ChannelPanel> mDisplayedPanels = new ConcurrentHashMap<>();
|
||||
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private IconManager mIconManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
private AudioPanel mAudioPanel;
|
||||
|
||||
public ChannelList(ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager,
|
||||
SettingsManager settingsManager,
|
||||
AudioPanel audioPanel)
|
||||
{
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mIconManager = iconManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mAudioPanel = audioPanel;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0,wrap 1", "[grow,fill]", "[]0[]"));
|
||||
setBackground(Color.BLACK);
|
||||
|
||||
addMouseListener(new ListSelectionListener());
|
||||
|
||||
add(mAudioPanel);
|
||||
|
||||
JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
|
||||
add(separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelChanged(ChannelEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case NOTIFICATION_PROCESSING_START:
|
||||
addChannelPanel(event.getChannel());
|
||||
break;
|
||||
case NOTIFICATION_PROCESSING_STOP:
|
||||
removeChannelPanel(event.getChannel());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void addChannelPanel(Channel channel)
|
||||
{
|
||||
if(!mDisplayedPanels.containsKey(channel))
|
||||
{
|
||||
ChannelPanel channelPanel = new ChannelPanel(mChannelModel,
|
||||
mChannelProcessingManager, mIconManager, mSettingsManager, channel);
|
||||
|
||||
add(channelPanel);
|
||||
|
||||
mDisplayedPanels.put(channel, channelPanel);
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeChannelPanel(Channel channel)
|
||||
{
|
||||
if(mDisplayedPanels.containsKey(channel))
|
||||
{
|
||||
ChannelPanel panel = mDisplayedPanels.remove(channel);
|
||||
|
||||
if(panel != null)
|
||||
{
|
||||
remove(panel);
|
||||
|
||||
panel.dispose();
|
||||
}
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public class ListSelectionListener implements MouseListener
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
Component component = getComponentAt(e.getPoint());
|
||||
|
||||
if(component instanceof ChannelPanel)
|
||||
{
|
||||
ChannelPanel panel = (ChannelPanel) component;
|
||||
|
||||
Channel channel = panel.getChannel();
|
||||
|
||||
if(e.getButton() == MouseEvent.BUTTON1)
|
||||
{
|
||||
if(channel.isSelected())
|
||||
{
|
||||
mChannelModel.broadcast(new ChannelEvent(channel, Event.REQUEST_DESELECT));
|
||||
}
|
||||
else
|
||||
{
|
||||
mChannelModel.broadcast(new ChannelEvent(channel, Event.REQUEST_SELECT));
|
||||
}
|
||||
}
|
||||
else if(e.getButton() == MouseEvent.BUTTON3)
|
||||
{
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
|
||||
JMenu menu = panel.getContextMenu();
|
||||
|
||||
if(menu != null)
|
||||
{
|
||||
popupMenu.add(menu);
|
||||
}
|
||||
|
||||
JMenu colorMenu = new JMenu("Color");
|
||||
popupMenu.add(colorMenu);
|
||||
|
||||
JMenu backgroundMenu = new JMenu("Background");
|
||||
colorMenu.add(backgroundMenu);
|
||||
|
||||
backgroundMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_BACKGROUND));
|
||||
backgroundMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_BACKGROUND));
|
||||
|
||||
JMenu channelsMenu = new JMenu("Channel State");
|
||||
colorMenu.add(channelsMenu);
|
||||
|
||||
JMenu callMenu = new JMenu("Call");
|
||||
channelsMenu.add(callMenu);
|
||||
|
||||
callMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CALL));
|
||||
callMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CALL));
|
||||
callMenu.add(new JSeparator());
|
||||
|
||||
callMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CALL));
|
||||
callMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CALL));
|
||||
|
||||
JMenu controlMenu = new JMenu("Control");
|
||||
channelsMenu.add(controlMenu);
|
||||
|
||||
controlMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL));
|
||||
controlMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL));
|
||||
controlMenu.add(new JSeparator());
|
||||
|
||||
controlMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CONTROL));
|
||||
controlMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CONTROL));
|
||||
|
||||
JMenu dataMenu = new JMenu("Data");
|
||||
channelsMenu.add(dataMenu);
|
||||
|
||||
dataMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_DATA));
|
||||
dataMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_DATA));
|
||||
dataMenu.add(new JSeparator());
|
||||
|
||||
dataMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_DATA));
|
||||
dataMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_DATA));
|
||||
|
||||
JMenu fadeMenu = new JMenu("Fade");
|
||||
channelsMenu.add(fadeMenu);
|
||||
|
||||
fadeMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_FADE));
|
||||
fadeMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_FADE));
|
||||
fadeMenu.add(new JSeparator());
|
||||
|
||||
fadeMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_FADE));
|
||||
fadeMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_FADE));
|
||||
|
||||
JMenu idleMenu = new JMenu("Idle");
|
||||
channelsMenu.add(idleMenu);
|
||||
|
||||
idleMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_IDLE));
|
||||
idleMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_IDLE));
|
||||
idleMenu.add(new JSeparator());
|
||||
|
||||
idleMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_IDLE));
|
||||
idleMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_IDLE));
|
||||
|
||||
JMenu noTunerMenu = new JMenu("No Tuner");
|
||||
channelsMenu.add(noTunerMenu);
|
||||
|
||||
noTunerMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER));
|
||||
noTunerMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER));
|
||||
noTunerMenu.add(new JSeparator());
|
||||
|
||||
noTunerMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER));
|
||||
noTunerMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER));
|
||||
|
||||
JMenu labelMenu = new JMenu("Labels");
|
||||
colorMenu.add(labelMenu);
|
||||
|
||||
labelMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER));
|
||||
labelMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER));
|
||||
labelMenu.add(new JSeparator());
|
||||
|
||||
labelMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DECODER));
|
||||
labelMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DECODER));
|
||||
labelMenu.add(new JSeparator());
|
||||
|
||||
labelMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DETAILS));
|
||||
labelMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DETAILS));
|
||||
|
||||
JMenu selectedMenu = new JMenu("Selected");
|
||||
colorMenu.add(selectedMenu);
|
||||
|
||||
selectedMenu.add(new ColorSettingMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_SELECTED_CHANNEL));
|
||||
selectedMenu.add(new ColorSettingResetMenuItem(mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_SELECTED_CHANNEL));
|
||||
|
||||
popupMenu.show(ChannelList.this, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,466 +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 channel.state;
|
||||
|
||||
import channel.metadata.Attribute;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.ChannelUtils;
|
||||
import icon.IconManager;
|
||||
import module.ProcessingChain;
|
||||
import module.decode.DecoderFactory;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import record.RecorderType;
|
||||
import record.config.RecordConfiguration;
|
||||
import sample.Listener;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChannelPanel extends JPanel
|
||||
implements Listener<Attribute>,
|
||||
SettingChangeListener,
|
||||
ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelPanel.class);
|
||||
|
||||
private Font mFontDetails = new Font(Font.MONOSPACED, Font.PLAIN, 12);
|
||||
private Font mFontDecoder = new Font(Font.MONOSPACED, Font.PLAIN, 12);
|
||||
|
||||
protected Color mColorChannelBackground;
|
||||
protected Color mColorChannelSelected;
|
||||
protected Color mColorTopCall;
|
||||
protected Color mColorMiddleCall;
|
||||
protected Color mColorTopControl;
|
||||
protected Color mColorMiddleControl;
|
||||
protected Color mColorTopData;
|
||||
protected Color mColorMiddleData;
|
||||
protected Color mColorTopFade;
|
||||
protected Color mColorMiddleFade;
|
||||
protected Color mColorTopIdle;
|
||||
protected Color mColorMiddleIdle;
|
||||
protected Color mColorTopNoTuner;
|
||||
protected Color mColorMiddleNoTuner;
|
||||
protected Color mColorLabelDetails;
|
||||
protected Color mColorLabelDecoder;
|
||||
protected Color mColorLabelAuxDecoder;
|
||||
|
||||
private JLabel mStateLabel;
|
||||
private JLabel mSourceLabel;
|
||||
private JLabel mOptionsLabel;
|
||||
|
||||
private JLabel mSystemLabel;
|
||||
private JLabel mSiteLabel;
|
||||
private JLabel mChannelLabel;
|
||||
|
||||
protected SettingsManager mSettingsManager;
|
||||
protected IconManager mIconManager;
|
||||
|
||||
private Channel mChannel;
|
||||
private ChannelState mChannelState;
|
||||
private List<DecoderPanel> mDecoderPanels = new ArrayList<>();
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
/**
|
||||
* Gui component to a channel state. Provides System, Site and channel
|
||||
* name, source and channel state visualization.
|
||||
*
|
||||
* Updates color background according to current channel state.
|
||||
*/
|
||||
public ChannelPanel(ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager,
|
||||
SettingsManager settingsManager,
|
||||
Channel channel)
|
||||
{
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mIconManager = iconManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mChannel = channel;
|
||||
|
||||
ProcessingChain processingChain =
|
||||
channelProcessingManager.getProcessingChain(mChannel);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
mChannelState = processingChain.getChannelState();
|
||||
|
||||
init();
|
||||
|
||||
for(DecoderState decoderState : processingChain.getDecoderStates())
|
||||
{
|
||||
DecoderPanel panel = DecoderFactory.getDecoderPanel(mIconManager, mSettingsManager, decoderState);
|
||||
mDecoderPanels.add(panel);
|
||||
add(panel, "grow,span");
|
||||
}
|
||||
|
||||
mChannelState.setChangedAttributeListener(this);
|
||||
mChannelModel.addListener(this);
|
||||
mSettingsManager.addListener(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Processing Chain was null!");
|
||||
}
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
getColors();
|
||||
|
||||
setLayout(new MigLayout("insets 1 1 1 1", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mSystemLabel = new JLabel(mChannel.getSystem());
|
||||
mSystemLabel.setFont(mFontDetails);
|
||||
mSystemLabel.setForeground(mColorLabelDetails);
|
||||
add(mSystemLabel);
|
||||
|
||||
mSiteLabel = new JLabel(mChannel.getSite());
|
||||
mSiteLabel.setFont(mFontDetails);
|
||||
mSiteLabel.setForeground(mColorLabelDetails);
|
||||
add(mSiteLabel);
|
||||
|
||||
mChannelLabel = new JLabel(mChannel.getName());
|
||||
mChannelLabel.setFont(mFontDetails);
|
||||
mChannelLabel.setForeground(mColorLabelDetails);
|
||||
add(mChannelLabel, "wrap");
|
||||
|
||||
mStateLabel = new JLabel(mChannelState.getState().getDisplayValue());
|
||||
mStateLabel.setFont(mFontDecoder);
|
||||
mStateLabel.setForeground(mColorLabelDecoder);
|
||||
add(mStateLabel);
|
||||
|
||||
mSourceLabel = new JLabel(mChannel.getSourceConfiguration().getDescription());
|
||||
mSourceLabel.setFont(mFontDetails);
|
||||
mSourceLabel.setForeground(mColorLabelDetails);
|
||||
add(mSourceLabel);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!mChannel.getEventLogConfiguration().getLoggers().isEmpty())
|
||||
{
|
||||
sb.append("LOG ");
|
||||
}
|
||||
|
||||
RecordConfiguration recordConfig = mChannel.getRecordConfiguration();
|
||||
|
||||
if(recordConfig.getRecorders().contains(RecorderType.AUDIO))
|
||||
{
|
||||
sb.append("AUDIO ");
|
||||
}
|
||||
|
||||
if(recordConfig.getRecorders().contains(RecorderType.BASEBAND) ||
|
||||
recordConfig.getRecorders().contains(RecorderType.TRAFFIC_BASEBAND))
|
||||
{
|
||||
sb.append("BASEBAND");
|
||||
}
|
||||
|
||||
mOptionsLabel = new JLabel(sb.toString());
|
||||
mOptionsLabel.setFont(mFontDetails);
|
||||
mOptionsLabel.setForeground(mColorLabelAuxDecoder);
|
||||
add(mOptionsLabel, "wrap");
|
||||
}
|
||||
|
||||
public Channel getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mChannelModel.removeListener(this);
|
||||
mChannelModel = null;
|
||||
|
||||
mChannelProcessingManager = null;
|
||||
|
||||
mSettingsManager.removeListener(this);
|
||||
mSettingsManager = null;
|
||||
|
||||
mChannelState.removeChangedAttributeListener();
|
||||
mChannelState = null;
|
||||
mChannel = null;
|
||||
|
||||
for(DecoderPanel panel : mDecoderPanels)
|
||||
{
|
||||
panel.dispose();
|
||||
remove(panel);
|
||||
}
|
||||
|
||||
mDecoderPanels.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case CHANNEL_STATE:
|
||||
if(mChannelState != null && mChannelState.getState() != null)
|
||||
{
|
||||
mStateLabel.setText(mChannelState.getState().getDisplayValue());
|
||||
}
|
||||
break;
|
||||
case SOURCE:
|
||||
mSourceLabel.setText(mChannel.getSourceConfiguration()
|
||||
.getDescription());
|
||||
break;
|
||||
case CHANNEL_NAME:
|
||||
case SITE_NAME:
|
||||
case SYSTEM_NAME:
|
||||
mChannelLabel.setText(mChannel.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g)
|
||||
{
|
||||
super.paintComponent(g);
|
||||
|
||||
setBackground(mColorChannelBackground);
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
|
||||
Paint p = null;
|
||||
|
||||
final Channel channel = mChannel;
|
||||
|
||||
if(mChannelState != null)
|
||||
{
|
||||
switch(mChannelState.getState())
|
||||
{
|
||||
case CALL:
|
||||
p = getGradient(mColorTopCall, mColorMiddleCall);
|
||||
break;
|
||||
case CONTROL:
|
||||
p = getGradient(mColorTopControl, mColorMiddleControl);
|
||||
break;
|
||||
case DATA:
|
||||
p = getGradient(mColorTopData, mColorMiddleData);
|
||||
break;
|
||||
case FADE:
|
||||
p = getGradient(mColorTopFade, mColorMiddleFade);
|
||||
break;
|
||||
case IDLE:
|
||||
default:
|
||||
p = getGradient(mColorTopIdle, mColorMiddleIdle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(p == null)
|
||||
{
|
||||
p = getGradient(mColorTopIdle, mColorMiddleIdle);
|
||||
}
|
||||
|
||||
g2.setPaint(p);
|
||||
g2.fillRect(0, 0, getWidth(), getHeight());
|
||||
|
||||
/* Draw bottom separator line */
|
||||
g2.setColor(Color.LIGHT_GRAY);
|
||||
g2.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);
|
||||
|
||||
/* Draw channel selected box */
|
||||
if(getChannel() != null && getChannel().isSelected())
|
||||
{
|
||||
g2.setColor(mColorChannelSelected);
|
||||
g2.drawRect(1, 1, getWidth() - 2, getHeight() - 2);
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
|
||||
private void getColors()
|
||||
{
|
||||
mColorChannelBackground = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_BACKGROUND).getColor();
|
||||
mColorChannelSelected = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_SELECTED_CHANNEL).getColor();
|
||||
mColorTopCall = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CALL).getColor();
|
||||
mColorMiddleCall = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CALL).getColor();
|
||||
mColorTopControl = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_CONTROL).getColor();
|
||||
mColorMiddleControl = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL).getColor();
|
||||
mColorTopData = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_DATA).getColor();
|
||||
mColorMiddleData = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_DATA).getColor();
|
||||
mColorTopFade = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_FADE).getColor();
|
||||
mColorMiddleFade = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_FADE).getColor();
|
||||
mColorTopIdle = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_IDLE).getColor();
|
||||
mColorMiddleIdle = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_IDLE).getColor();
|
||||
mColorTopNoTuner = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER).getColor();
|
||||
mColorMiddleNoTuner = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER).getColor();
|
||||
|
||||
mColorLabelDetails = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DETAILS).getColor();
|
||||
mColorLabelDecoder = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DECODER).getColor();
|
||||
mColorLabelAuxDecoder = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER).getColor();
|
||||
}
|
||||
|
||||
private GradientPaint getGradient(Color top, Color middle)
|
||||
{
|
||||
return new GradientPaint(0f, -50.0f, top,
|
||||
0f, (float) getHeight() / 2.2f, middle, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_BACKGROUND:
|
||||
mColorChannelBackground = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_CALL:
|
||||
mColorMiddleCall = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_CALL:
|
||||
mColorTopCall = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_CONTROL:
|
||||
mColorMiddleControl = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_CONTROL:
|
||||
mColorTopControl = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_DATA:
|
||||
mColorMiddleData = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_DATA:
|
||||
mColorTopData = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_FADE:
|
||||
mColorMiddleFade = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_FADE:
|
||||
mColorTopFade = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_IDLE:
|
||||
mColorMiddleIdle = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_IDLE:
|
||||
mColorTopIdle = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER:
|
||||
mColorMiddleNoTuner = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_GRADIENT_TOP_NO_TUNER:
|
||||
mColorTopNoTuner = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_AUX_DECODER:
|
||||
mColorLabelAuxDecoder = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
mColorLabelDecoder = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
mColorLabelDetails = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_SELECTED_CHANNEL:
|
||||
mColorChannelSelected = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingDeleted(Setting setting)
|
||||
{
|
||||
}
|
||||
|
||||
public JMenu getContextMenu()
|
||||
{
|
||||
return ChannelUtils.getContextMenu(mChannelModel, mChannelProcessingManager,
|
||||
mChannel, ChannelPanel.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelChanged(ChannelEvent event)
|
||||
{
|
||||
if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel() == mChannel)
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,163 +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 channel.state;
|
||||
|
||||
import alias.Alias;
|
||||
import channel.metadata.Attribute;
|
||||
import icon.IconManager;
|
||||
import sample.Listener;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class DecoderPanel extends JPanel
|
||||
implements Listener<Attribute>, SettingChangeListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected Font mFontDetails = new Font(Font.MONOSPACED, Font.PLAIN, 12);
|
||||
protected Font mFontDecoder = new Font(Font.MONOSPACED, Font.PLAIN, 12);
|
||||
protected Font mFontAuxDecoder = new Font(Font.MONOSPACED, Font.PLAIN, 10);
|
||||
public static final int ICON_SIZE = 12;
|
||||
|
||||
protected Color mColorLabelDetails;
|
||||
protected Color mColorLabelDecoder;
|
||||
protected Color mColorLabelAuxDecoder;
|
||||
|
||||
protected IconManager mIconManager;
|
||||
protected SettingsManager mSettingsManager;
|
||||
protected DecoderState mDecoderState;
|
||||
|
||||
public DecoderPanel(IconManager iconManager, SettingsManager settingsManager, DecoderState decoderState)
|
||||
{
|
||||
mIconManager = iconManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mSettingsManager.addListener(this);
|
||||
|
||||
mDecoderState = decoderState;
|
||||
|
||||
mDecoderState.setChangedAttributeListener(this);
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mSettingsManager.removeListener(this);
|
||||
mSettingsManager = null;
|
||||
|
||||
mDecoderState.removeChangedAttributeListener();
|
||||
mDecoderState = null;
|
||||
}
|
||||
|
||||
public DecoderState getDecoderState()
|
||||
{
|
||||
return mDecoderState;
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
getColors();
|
||||
|
||||
setOpaque(false); //Use the parent panel's background color
|
||||
}
|
||||
|
||||
private void getColors()
|
||||
{
|
||||
mColorLabelDetails = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DETAILS).getColor();
|
||||
mColorLabelDecoder = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DECODER).getColor();
|
||||
mColorLabelAuxDecoder = mSettingsManager.getColorSetting(
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER).getColor();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_AUX_DECODER:
|
||||
mColorLabelAuxDecoder = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
mColorLabelDecoder = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
mColorLabelDetails = colorSetting.getColor();
|
||||
repaint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingDeleted(Setting setting)
|
||||
{
|
||||
}
|
||||
|
||||
protected void setAliasLabel(final JLabel label, final Alias alias)
|
||||
{
|
||||
setAliasLabel(label, alias, true);
|
||||
}
|
||||
|
||||
protected void setAliasLabel(final JLabel label, final Alias alias, boolean includeIcon)
|
||||
{
|
||||
if(alias != null)
|
||||
{
|
||||
label.setText(alias.getName());
|
||||
|
||||
if(includeIcon)
|
||||
{
|
||||
String iconName = alias.getIconName();
|
||||
|
||||
if(iconName != null)
|
||||
{
|
||||
label.setIcon(mIconManager.getIcon(iconName, IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setIcon(null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setIcon(null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setText("");
|
||||
label.setIcon(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package channel.state;
|
||||
|
||||
import alias.AliasList;
|
||||
import audio.metadata.IMetadataProvider;
|
||||
import audio.metadata.Metadata;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.metadata.IAttributeChangeRequestProvider;
|
||||
import message.IMessageListener;
|
||||
@@ -193,4 +190,5 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
|
||||
{
|
||||
mAttributeChangeRequestListener = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package channel.state;
|
||||
|
||||
import channel.metadata.Attribute;
|
||||
import sample.Listener;
|
||||
|
||||
public interface IChangedAttributeProvider
|
||||
{
|
||||
public void setChangedAttributeListener( Listener<Attribute> listener );
|
||||
public void removeChangedAttributeListener();
|
||||
}
|
||||
@@ -1,58 +1,46 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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 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 controller;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import alias.AliasController;
|
||||
import alias.AliasModel;
|
||||
import audio.AudioManager;
|
||||
import audio.AudioPanel;
|
||||
import audio.broadcast.BroadcastModel;
|
||||
import audio.broadcast.BroadcastPanel;
|
||||
import channel.metadata.ChannelMetadataViewer;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
import controller.channel.ChannelController;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import icon.IconManager;
|
||||
import map.MapPanel;
|
||||
import map.MapService;
|
||||
import module.decode.event.CallEventPanel;
|
||||
import module.decode.event.MessageActivityPanel;
|
||||
import channel.state.ChannelList;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.SettingsManager;
|
||||
import source.SourceManager;
|
||||
import source.tuner.TunerModel;
|
||||
import source.tuner.TunerViewPanel;
|
||||
import spectrum.ChannelSpectrumPanel;
|
||||
import alias.AliasController;
|
||||
import alias.AliasModel;
|
||||
import audio.AudioManager;
|
||||
import audio.AudioPanel;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.channel.ChannelController;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class ControllerPanel extends JPanel
|
||||
{
|
||||
@@ -61,13 +49,10 @@ public class ControllerPanel extends JPanel
|
||||
private AliasController mAliasController;
|
||||
private AudioPanel mAudioPanel;
|
||||
private BroadcastPanel mBroadcastPanel;
|
||||
private CallEventPanel mCallEventPanel;
|
||||
private ChannelController mChannelController;
|
||||
private ChannelList mChannelStateList;
|
||||
private ChannelMetadataViewer mChannelMetadataViewer;
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelSpectrumPanel mChannelSpectrumPanel;
|
||||
private MapPanel mMapPanel;
|
||||
private MessageActivityPanel mMessageActivityPanel;
|
||||
private TunerViewPanel mTunerManagerPanel;
|
||||
|
||||
private JideTabbedPane mTabbedPane;
|
||||
@@ -89,24 +74,16 @@ public class ControllerPanel extends JPanel
|
||||
|
||||
mAudioPanel = new AudioPanel(iconManager, settingsManager, sourceManager, audioManager);
|
||||
|
||||
mMapPanel = new MapPanel(mapService, iconManager, settingsManager);
|
||||
mChannelMetadataViewer = new ChannelMetadataViewer(channelProcessingManager, iconManager, settingsManager);
|
||||
|
||||
mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager);
|
||||
mMapPanel = new MapPanel(mapService, iconManager, settingsManager);
|
||||
|
||||
mBroadcastPanel = new BroadcastPanel(broadcastModel, aliasModel, iconManager);
|
||||
|
||||
mCallEventPanel = new CallEventPanel(iconManager, channelProcessingManager);
|
||||
|
||||
mChannelSpectrumPanel = new ChannelSpectrumPanel(settingsManager,
|
||||
channelProcessingManager);
|
||||
|
||||
mChannelStateList = new ChannelList(channelModel, channelProcessingManager, iconManager,
|
||||
settingsManager, mAudioPanel);
|
||||
|
||||
mChannelController = new ChannelController(channelModel, channelMapModel,
|
||||
sourceManager, aliasModel);
|
||||
mChannelController = new ChannelController(channelModel, channelMapModel, sourceManager, aliasModel);
|
||||
|
||||
mAliasController = new AliasController(aliasModel, broadcastModel, iconManager);
|
||||
|
||||
mTunerManagerPanel = new TunerViewPanel(tunerModel);
|
||||
|
||||
init();
|
||||
@@ -114,66 +91,24 @@ public class ControllerPanel 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]", "[]0[grow,fill]"));
|
||||
|
||||
add(mAudioPanel);
|
||||
|
||||
//Tabbed View - configuration, calls, messages, map
|
||||
mTabbedPane = new JideTabbedPane();
|
||||
mTabbedPane.setFont(this.getFont());
|
||||
mTabbedPane.setForeground(Color.BLACK);
|
||||
mTabbedPane.addTab("Tuners", mTunerManagerPanel);
|
||||
mTabbedPane.addTab("Channels", mChannelController);
|
||||
mTabbedPane.addTab("Now Playing", mChannelMetadataViewer);
|
||||
mTabbedPane.addTab("Aliases", mAliasController);
|
||||
mTabbedPane.addTab("Channel Spectrum", mChannelSpectrumPanel);
|
||||
mTabbedPane.addTab("Events", mCallEventPanel);
|
||||
mTabbedPane.addTab("Channels", mChannelController);
|
||||
mTabbedPane.addTab("Map", mMapPanel);
|
||||
mTabbedPane.addTab("Messages", mMessageActivityPanel);
|
||||
mTabbedPane.addTab("Streaming", mBroadcastPanel);
|
||||
|
||||
/**
|
||||
* Change listener to enable/disable the channel spectrum display
|
||||
* only when the tab is visible, and a channel has been selected
|
||||
*/
|
||||
mTabbedPane.addChangeListener(new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent event)
|
||||
{
|
||||
int index = mTabbedPane.getSelectedIndex();
|
||||
|
||||
Component component = mTabbedPane.getComponentAt(index);
|
||||
|
||||
if (component instanceof ChannelSpectrumPanel)
|
||||
{
|
||||
mChannelSpectrumPanel.setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mChannelSpectrumPanel.setEnabled(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Register each of the components to receive channel events when the
|
||||
* channels are selected or change */
|
||||
mChannelModel.addListener(mCallEventPanel);
|
||||
mChannelModel.addListener(mChannelStateList);
|
||||
mChannelModel.addListener(mChannelSpectrumPanel);
|
||||
mChannelModel.addListener(mMessageActivityPanel);
|
||||
|
||||
JScrollPane channelStateListScroll = new JScrollPane();
|
||||
channelStateListScroll.getViewport().setView(mChannelStateList);
|
||||
channelStateListScroll.setPreferredSize(new Dimension(400, 500));
|
||||
mTabbedPane.addTab("Tuners", mTunerManagerPanel);
|
||||
|
||||
//Set preferred size to influence the split between these panels
|
||||
mTabbedPane.setPreferredSize(new Dimension(880, 500));
|
||||
|
||||
JideSplitPane channelSplit = new JideSplitPane(JideSplitPane.HORIZONTAL_SPLIT);
|
||||
channelSplit.setDividerSize(5);
|
||||
channelSplit.add(channelStateListScroll);
|
||||
channelSplit.add(mTabbedPane);
|
||||
|
||||
add(channelSplit);
|
||||
add(mTabbedPane);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -14,50 +14,51 @@
|
||||
*
|
||||
* 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 controller.channel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import alias.AliasModel;
|
||||
import audio.AudioPacket;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.metadata.ChannelMetadataModel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import filter.FilterSet;
|
||||
import message.Message;
|
||||
import module.Module;
|
||||
import module.ProcessingChain;
|
||||
import module.decode.DecoderFactory;
|
||||
import module.decode.event.MessageActivityModel;
|
||||
import module.log.EventLogManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import record.RecorderManager;
|
||||
import record.RecorderType;
|
||||
import sample.Listener;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.SourceManager;
|
||||
import alias.AliasModel;
|
||||
import audio.AudioPacket;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import filter.FilterSet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class ChannelProcessingManager implements ChannelEventListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelProcessingManager.class);
|
||||
|
||||
private Map<Integer, ProcessingChain> mProcessingChains = new HashMap<>();
|
||||
private Map<Integer,ProcessingChain> mProcessingChains = new HashMap<>();
|
||||
|
||||
private List<Listener<AudioPacket>> mAudioPacketListeners = new CopyOnWriteArrayList<>();
|
||||
private List<Listener<Message>> mMessageListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
private ChannelMetadataModel mChannelMetadataModel = new ChannelMetadataModel();
|
||||
private AliasModel mAliasModel;
|
||||
private EventLogManager mEventLogManager;
|
||||
private RecorderManager mRecorderManager;
|
||||
@@ -78,6 +79,14 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
mSourceManager = sourceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel metadata model containing metadata for each channel or channel time-slice that is currently processing.
|
||||
*/
|
||||
public ChannelMetadataModel getChannelMetadataModel()
|
||||
{
|
||||
return mChannelMetadataModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a processing chain is constructed for the channel and that
|
||||
* the processing chain is currently processing.
|
||||
@@ -85,7 +94,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
private boolean isProcessing(Channel channel)
|
||||
{
|
||||
return mProcessingChains.containsKey(channel.getChannelID()) &&
|
||||
mProcessingChains.get(channel.getChannelID()).isProcessing();
|
||||
mProcessingChains.get(channel.getChannelID()).isProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,19 +111,19 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
{
|
||||
Channel channel = event.getChannel();
|
||||
|
||||
switch (event.getEvent())
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case REQUEST_ENABLE:
|
||||
if (!mProcessingChains.containsKey(channel.getChannelID()) ||
|
||||
!mProcessingChains.get(channel.getChannelID()).isProcessing())
|
||||
if(!mProcessingChains.containsKey(channel.getChannelID()) ||
|
||||
!mProcessingChains.get(channel.getChannelID()).isProcessing())
|
||||
{
|
||||
startProcessing(event);
|
||||
}
|
||||
break;
|
||||
case REQUEST_DISABLE:
|
||||
if (channel.getEnabled())
|
||||
if(channel.getEnabled())
|
||||
{
|
||||
switch (channel.getChannelType())
|
||||
switch(channel.getChannelType())
|
||||
{
|
||||
case STANDARD:
|
||||
stopProcessing(channel, true);
|
||||
@@ -129,13 +138,13 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
}
|
||||
}
|
||||
case NOTIFICATION_DELETE:
|
||||
if (channel.getEnabled())
|
||||
if(channel.getEnabled())
|
||||
{
|
||||
stopProcessing(channel, true);
|
||||
}
|
||||
break;
|
||||
case NOTIFICATION_CONFIGURATION_CHANGE:
|
||||
if (isProcessing(channel))
|
||||
if(isProcessing(channel))
|
||||
{
|
||||
stopProcessing(channel, false);
|
||||
startProcessing(event);
|
||||
@@ -153,7 +162,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
ProcessingChain processingChain = mProcessingChains.get(channel.getChannelID());
|
||||
|
||||
//If we're already processing, ignore the request
|
||||
if (processingChain != null && processingChain.isProcessing())
|
||||
if(processingChain != null && processingChain.isProcessing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -164,63 +173,88 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
try
|
||||
{
|
||||
source = mSourceManager.getSource(channel.getSourceConfiguration(),
|
||||
channel.getDecodeConfiguration().getDecoderType().getChannelBandwidth());
|
||||
channel.getDecodeConfiguration().getDecoderType().getChannelBandwidth());
|
||||
}
|
||||
catch (SourceException se)
|
||||
catch(SourceException se)
|
||||
{
|
||||
mLog.debug("Error obtaining source for channel [" + channel.getName() + "]", se);
|
||||
}
|
||||
|
||||
if (source == null)
|
||||
if(source == null)
|
||||
{
|
||||
channel.setEnabled(false);
|
||||
|
||||
mChannelModel.broadcast(
|
||||
new ChannelEvent(channel, Event.NOTIFICATION_ENABLE_REJECTED));
|
||||
new ChannelEvent(channel, Event.NOTIFICATION_ENABLE_REJECTED));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (processingChain == null)
|
||||
if(processingChain == null)
|
||||
{
|
||||
processingChain = new ProcessingChain(channel.getName(),
|
||||
channel.getChannelType());
|
||||
channel.getChannelType());
|
||||
|
||||
/* Register global listeners */
|
||||
for (Listener<AudioPacket> listener : mAudioPacketListeners)
|
||||
for(Listener<AudioPacket> listener : mAudioPacketListeners)
|
||||
{
|
||||
processingChain.addAudioPacketListener(listener);
|
||||
}
|
||||
|
||||
for (Listener<Message> listener : mMessageListeners)
|
||||
for(Listener<Message> listener : mMessageListeners)
|
||||
{
|
||||
processingChain.addMessageListener(listener);
|
||||
}
|
||||
|
||||
/* Processing Modules */
|
||||
List<Module> modules = DecoderFactory.getModules(mChannelModel,
|
||||
mChannelMapModel, this, mAliasModel, channel);
|
||||
List<Module> modules = DecoderFactory.getModules(mChannelModel, mChannelMapModel, this,
|
||||
mAliasModel, channel, processingChain.getChannelState().getMutableMetadata());
|
||||
processingChain.addModules(modules);
|
||||
|
||||
/* Setup message activity model with filtering */
|
||||
FilterSet<Message> messageFilter = DecoderFactory.getMessageFilters(modules);
|
||||
MessageActivityModel messageModel = new MessageActivityModel(messageFilter);
|
||||
processingChain.setMessageActivityModel(messageModel);
|
||||
|
||||
/* Inject channel metadata that will be inserted into audio packets
|
||||
* for the recorder manager and streaming */
|
||||
processingChain.broadcast(
|
||||
new Metadata(MetadataType.SYSTEM, channel.getSystem()));
|
||||
processingChain.broadcast(
|
||||
new Metadata(MetadataType.SITE_ID, channel.getSite()));
|
||||
processingChain.broadcast(
|
||||
new Metadata(MetadataType.CHANNEL_NAME, channel.getName()));
|
||||
|
||||
//Override recordable flag in metadata if user has specified audio recording
|
||||
if(channel.getRecordConfiguration() != null &&
|
||||
channel.getRecordConfiguration().getRecorders().contains(RecorderType.AUDIO))
|
||||
{
|
||||
processingChain.getChannelState().getMutableMetadata().setRecordable(true);
|
||||
}
|
||||
|
||||
//Inject channel metadata that will be inserted into audio packets for recorder manager and streaming
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(channel.getSystem() != null)
|
||||
{
|
||||
sb.append(channel.getSystem());
|
||||
}
|
||||
|
||||
if(channel.getSite() != null)
|
||||
{
|
||||
if(sb.length() > 0)
|
||||
{
|
||||
sb.append(" - ");
|
||||
}
|
||||
|
||||
sb.append(channel.getSite());
|
||||
}
|
||||
|
||||
if(sb.length() > 0)
|
||||
{
|
||||
processingChain.getChannelState().getMutableMetadata()
|
||||
.receive(new AttributeChangeRequest<String>(Attribute.CHANNEL_CONFIGURATION_LABEL_1, sb.toString()));
|
||||
}
|
||||
|
||||
processingChain.getChannelState().getMutableMetadata()
|
||||
.receive(new AttributeChangeRequest<String>(Attribute.CHANNEL_CONFIGURATION_LABEL_2, channel.getName()));
|
||||
}
|
||||
|
||||
/* Setup event logging */
|
||||
List<Module> loggers = mEventLogManager.getLoggers(channel.getEventLogConfiguration(), channel.getName());
|
||||
|
||||
if (!loggers.isEmpty())
|
||||
if(!loggers.isEmpty())
|
||||
{
|
||||
processingChain.addModules(loggers);
|
||||
}
|
||||
@@ -228,16 +262,16 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
/* Setup recorders */
|
||||
List<RecorderType> recorders = channel.getRecordConfiguration().getRecorders();
|
||||
|
||||
if (!recorders.isEmpty())
|
||||
if(!recorders.isEmpty())
|
||||
{
|
||||
/* Add baseband recorder */
|
||||
if ((recorders.contains(RecorderType.BASEBAND) && channel.getChannelType() == ChannelType.STANDARD))
|
||||
/* Add baseband recorder */
|
||||
if((recorders.contains(RecorderType.BASEBAND) && channel.getChannelType() == ChannelType.STANDARD))
|
||||
{
|
||||
processingChain.addModule(mRecorderManager.getBasebandRecorder(channel.toString()));
|
||||
}
|
||||
|
||||
/* Add traffic channel baseband recorder */
|
||||
if (recorders.contains(RecorderType.TRAFFIC_BASEBAND) && channel.getChannelType() == ChannelType.TRAFFIC)
|
||||
if(recorders.contains(RecorderType.TRAFFIC_BASEBAND) && channel.getChannelType() == ChannelType.TRAFFIC)
|
||||
{
|
||||
processingChain.addModule(mRecorderManager.getBasebandRecorder(channel.toString()));
|
||||
}
|
||||
@@ -245,13 +279,13 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
|
||||
processingChain.setSource(source);
|
||||
|
||||
if (event instanceof TrafficChannelEvent)
|
||||
if(event instanceof TrafficChannelEvent)
|
||||
{
|
||||
TrafficChannelEvent trafficChannelEvent = (TrafficChannelEvent) event;
|
||||
|
||||
processingChain.getChannelState().configureAsTrafficChannel(
|
||||
trafficChannelEvent.getTrafficChannelManager(),
|
||||
trafficChannelEvent.getCallEvent());
|
||||
trafficChannelEvent.getTrafficChannelManager(),
|
||||
trafficChannelEvent.getCallEvent());
|
||||
}
|
||||
|
||||
processingChain.start();
|
||||
@@ -261,14 +295,14 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
mProcessingChains.put(channel.getChannelID(), processingChain);
|
||||
|
||||
mChannelModel.broadcast(
|
||||
new ChannelEvent(channel, Event.NOTIFICATION_PROCESSING_START));
|
||||
new ChannelEvent(channel, Event.NOTIFICATION_PROCESSING_START));
|
||||
}
|
||||
|
||||
private void stopProcessing(Channel channel, boolean remove)
|
||||
{
|
||||
channel.setEnabled(false);
|
||||
|
||||
if (mProcessingChains.containsKey(channel.getChannelID()))
|
||||
if(mProcessingChains.containsKey(channel.getChannelID()))
|
||||
{
|
||||
ProcessingChain processingChain = mProcessingChains.get(channel.getChannelID());
|
||||
|
||||
@@ -281,7 +315,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
||||
|
||||
mChannelModel.broadcast(new ChannelEvent(channel, Event.NOTIFICATION_PROCESSING_STOP));
|
||||
|
||||
if (remove)
|
||||
if(remove)
|
||||
{
|
||||
mProcessingChains.remove(channel.getChannelID());
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
* 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 instrument.gui;
|
||||
|
||||
import alias.AliasModel;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import instrument.Instrumentable;
|
||||
import instrument.InstrumentableProcessingChain;
|
||||
import instrument.tap.Tap;
|
||||
@@ -38,8 +44,21 @@ import instrument.tap.stream.QPSKTap;
|
||||
import instrument.tap.stream.QPSKTapPanel;
|
||||
import instrument.tap.stream.SymbolEventTap;
|
||||
import instrument.tap.stream.SymbolEventTapViewPanel;
|
||||
import message.Message;
|
||||
import module.Module;
|
||||
import module.decode.DecoderFactory;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.log.EventLogManager;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import playlist.PlaylistManager;
|
||||
import sample.Listener;
|
||||
import source.IControllableFileSource;
|
||||
import source.Source;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
@@ -47,312 +66,290 @@ import java.awt.event.MouseListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import message.Message;
|
||||
import module.Module;
|
||||
import module.decode.DecoderFactory;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.log.EventLogManager;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import playlist.PlaylistManager;
|
||||
import sample.Listener;
|
||||
import source.IControllableFileSource;
|
||||
import source.Source;
|
||||
import alias.AliasModel;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
|
||||
public class DecoderViewFrame extends JInternalFrame
|
||||
implements Listener<Message>
|
||||
public class DecoderViewFrame extends JInternalFrame implements Listener<Message>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( DecoderViewFrame.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(DecoderViewFrame.class);
|
||||
|
||||
private DecodeConfiguration mDecodeConfig;
|
||||
private DecodeConfiguration mDecodeConfig;
|
||||
private InstrumentableProcessingChain mProcessingChain;
|
||||
private IControllableFileSource mSource;
|
||||
|
||||
private HashMap<Tap,TapViewPanel> mPanelMap =
|
||||
new HashMap<Tap,TapViewPanel>();
|
||||
|
||||
public DecoderViewFrame( PlaylistManager playlistManager,
|
||||
Channel channel,
|
||||
IControllableFileSource source )
|
||||
{
|
||||
mSource = source;
|
||||
private IControllableFileSource mSource;
|
||||
|
||||
mDecodeConfig = channel.getDecodeConfiguration();
|
||||
|
||||
mProcessingChain = new InstrumentableProcessingChain();
|
||||
private HashMap<Tap,TapViewPanel> mPanelMap = new HashMap<Tap,TapViewPanel>();
|
||||
|
||||
ChannelModel channelModel = new ChannelModel();
|
||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||
|
||||
ChannelProcessingManager channelProcessingManager =
|
||||
new ChannelProcessingManager( channelModel, channelMapModel,
|
||||
new AliasModel(), new EventLogManager(), null, null );
|
||||
|
||||
List<Module> modules = DecoderFactory.getModules( channelModel,
|
||||
channelMapModel, channelProcessingManager, new AliasModel(), channel );
|
||||
public DecoderViewFrame(PlaylistManager playlistManager, Channel channel, IControllableFileSource source)
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
mProcessingChain.addModules( modules );
|
||||
mDecodeConfig = channel.getDecodeConfiguration();
|
||||
|
||||
mProcessingChain.addMessageListener( this );
|
||||
|
||||
mProcessingChain.setSource( (Source)mSource );
|
||||
|
||||
mProcessingChain.start();
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]" ) );
|
||||
mProcessingChain = new InstrumentableProcessingChain();
|
||||
|
||||
setTitle( "Decoder [" + mDecodeConfig.getDecoderType().getDisplayString() + "]" );
|
||||
setPreferredSize( new Dimension( 450, 250 ) );
|
||||
setSize( 450, 250 );
|
||||
ChannelModel channelModel = new ChannelModel();
|
||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||
|
||||
setResizable( true );
|
||||
setClosable( true );
|
||||
setIconifiable( true );
|
||||
setMaximizable( false );
|
||||
ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(channelModel, channelMapModel,
|
||||
new AliasModel(), new EventLogManager(), null, null);
|
||||
|
||||
addMouseListener( new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent me )
|
||||
List<Module> modules = DecoderFactory.getModules(channelModel, channelMapModel, channelProcessingManager,
|
||||
new AliasModel(), channel, mProcessingChain.getChannelState().getMutableMetadata());
|
||||
|
||||
mProcessingChain.addModules(modules);
|
||||
|
||||
mProcessingChain.addMessageListener(this);
|
||||
|
||||
mProcessingChain.setSource((Source) mSource);
|
||||
|
||||
mProcessingChain.start();
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
setTitle("Decoder [" + mDecodeConfig.getDecoderType().getDisplayString() + "]");
|
||||
setPreferredSize(new Dimension(450, 250));
|
||||
setSize(450, 250);
|
||||
|
||||
setResizable(true);
|
||||
setClosable(true);
|
||||
setIconifiable(true);
|
||||
setMaximizable(false);
|
||||
|
||||
addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent me)
|
||||
{
|
||||
if( me.getButton() == MouseEvent.BUTTON3 )
|
||||
{
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
if(me.getButton() == MouseEvent.BUTTON3)
|
||||
{
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
|
||||
popup.add( getTapContextMenu() );
|
||||
popup.add(getTapContextMenu());
|
||||
|
||||
if( !mPanelMap.values().isEmpty() )
|
||||
{
|
||||
popup.add( new JSeparator() );
|
||||
|
||||
for( TapViewPanel panel: mPanelMap.values() )
|
||||
{
|
||||
popup.add( panel.getContextMenu() );
|
||||
}
|
||||
}
|
||||
|
||||
popup.show( DecoderViewFrame.this, me.getX(), me.getY() );
|
||||
}
|
||||
if(!mPanelMap.values().isEmpty())
|
||||
{
|
||||
popup.add(new JSeparator());
|
||||
|
||||
for(TapViewPanel panel : mPanelMap.values())
|
||||
{
|
||||
popup.add(panel.getContextMenu());
|
||||
}
|
||||
}
|
||||
|
||||
popup.show(DecoderViewFrame.this, me.getX(), me.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent arg0 ) {}
|
||||
@Override
|
||||
public void mouseExited( MouseEvent arg0 ) {}
|
||||
@Override
|
||||
public void mousePressed( MouseEvent arg0 ) {}
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent arg0 ) {}
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
private JMenu getTapContextMenu()
|
||||
{
|
||||
JMenu menu = new JMenu( "Modules" );
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
if( mProcessingChain != null )
|
||||
{
|
||||
for( Module module: mProcessingChain.getModules() )
|
||||
{
|
||||
if( module instanceof Instrumentable )
|
||||
{
|
||||
List<TapGroup> groups = ((Instrumentable)module).getTapGroups();
|
||||
|
||||
for( TapGroup group: groups )
|
||||
{
|
||||
menu.add( new TapGroupMenu( group ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void add( Tap tap )
|
||||
{
|
||||
TapViewPanel panel = null;
|
||||
|
||||
switch( tap.getType() )
|
||||
{
|
||||
case EVENT_SYNC_DETECT:
|
||||
break;
|
||||
case STREAM_BINARY:
|
||||
panel = new BinaryTapViewPanel( (BinaryTap)tap );
|
||||
break;
|
||||
case STREAM_COMPLEX:
|
||||
panel = new ComplexTapViewPanel( (ComplexTap)tap );
|
||||
break;
|
||||
case STREAM_COMPLEX_SAMPLE:
|
||||
panel = new ComplexSampleTapViewPanel( (ComplexSampleTap)tap );
|
||||
break;
|
||||
case STREAM_DIBIT:
|
||||
panel = new DibitTapViewPanel( (DibitTap)tap );
|
||||
break;
|
||||
case STREAM_EYE_DIAGRAM:
|
||||
panel = new EyeDiagramDataTapPanel( (EyeDiagramDataTap)tap ) ;
|
||||
break;
|
||||
case STREAM_FLOAT:
|
||||
panel = new FloatTapViewPanel( (FloatTap)tap );
|
||||
break;
|
||||
case STREAM_QPSK:
|
||||
panel = new QPSKTapPanel( (QPSKTap)tap );
|
||||
break;
|
||||
case STREAM_SYMBOL:
|
||||
panel = new SymbolEventTapViewPanel( (SymbolEventTap)tap );
|
||||
break;
|
||||
}
|
||||
|
||||
if( panel != null )
|
||||
{
|
||||
add( panel, "span" );
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.put( tap, panel );
|
||||
@Override
|
||||
public void mousePressed(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
for( Module module: mProcessingChain.getModules() )
|
||||
{
|
||||
if( module instanceof Instrumentable )
|
||||
{
|
||||
((Instrumentable)module).registerTap( tap );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info( "Tap panel is null, couldn't add for tap " +
|
||||
tap.getName() + "[" + tap.getType().toString() + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( Tap tap )
|
||||
{
|
||||
for( Module module: mProcessingChain.getModules() )
|
||||
{
|
||||
if( module instanceof Instrumentable )
|
||||
{
|
||||
((Instrumentable)module).unregisterTap( tap );
|
||||
}
|
||||
}
|
||||
|
||||
TapViewPanel panel = mPanelMap.get( tap );
|
||||
|
||||
remove( panel );
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.remove( tap );
|
||||
}
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public class AddAllTapsItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Tap> mTaps;
|
||||
|
||||
public AddAllTapsItem( final List<Tap> taps )
|
||||
{
|
||||
super( "All Taps" );
|
||||
|
||||
mTaps = taps;
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
for( Tap tap: mTaps )
|
||||
{
|
||||
DecoderViewFrame.this.add( tap );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class TapSelectionItem extends JCheckBoxMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Tap mTap;
|
||||
|
||||
public TapSelectionItem( Tap tap )
|
||||
{
|
||||
super( tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
|
||||
if( mPanelMap.keySet().contains( tap ) )
|
||||
{
|
||||
setSelected( true );
|
||||
}
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
if( mPanelMap.keySet().contains( mTap ) )
|
||||
{
|
||||
DecoderViewFrame.this.remove( mTap );
|
||||
}
|
||||
else
|
||||
{
|
||||
DecoderViewFrame.this.add( mTap );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
mLog.info( message.toString() );
|
||||
});
|
||||
}
|
||||
|
||||
private JMenu getTapContextMenu()
|
||||
{
|
||||
JMenu menu = new JMenu("Modules");
|
||||
|
||||
if(mProcessingChain != null)
|
||||
{
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
List<TapGroup> groups = ((Instrumentable) module).getTapGroups();
|
||||
|
||||
for(TapGroup group : groups)
|
||||
{
|
||||
menu.add(new TapGroupMenu(group));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void add(Tap tap)
|
||||
{
|
||||
TapViewPanel panel = null;
|
||||
|
||||
switch(tap.getType())
|
||||
{
|
||||
case EVENT_SYNC_DETECT:
|
||||
break;
|
||||
case STREAM_BINARY:
|
||||
panel = new BinaryTapViewPanel((BinaryTap) tap);
|
||||
break;
|
||||
case STREAM_COMPLEX:
|
||||
panel = new ComplexTapViewPanel((ComplexTap) tap);
|
||||
break;
|
||||
case STREAM_COMPLEX_SAMPLE:
|
||||
panel = new ComplexSampleTapViewPanel((ComplexSampleTap) tap);
|
||||
break;
|
||||
case STREAM_DIBIT:
|
||||
panel = new DibitTapViewPanel((DibitTap) tap);
|
||||
break;
|
||||
case STREAM_EYE_DIAGRAM:
|
||||
panel = new EyeDiagramDataTapPanel((EyeDiagramDataTap) tap);
|
||||
break;
|
||||
case STREAM_FLOAT:
|
||||
panel = new FloatTapViewPanel((FloatTap) tap);
|
||||
break;
|
||||
case STREAM_QPSK:
|
||||
panel = new QPSKTapPanel((QPSKTap) tap);
|
||||
break;
|
||||
case STREAM_SYMBOL:
|
||||
panel = new SymbolEventTapViewPanel((SymbolEventTap) tap);
|
||||
break;
|
||||
}
|
||||
|
||||
if(panel != null)
|
||||
{
|
||||
add(panel, "span");
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.put(tap, panel);
|
||||
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable) module).registerTap(tap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info("Tap panel is null, couldn't add for tap " +
|
||||
tap.getName() + "[" + tap.getType().toString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Tap tap)
|
||||
{
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable) module).unregisterTap(tap);
|
||||
}
|
||||
}
|
||||
|
||||
TapViewPanel panel = mPanelMap.get(tap);
|
||||
|
||||
remove(panel);
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.remove(tap);
|
||||
}
|
||||
|
||||
public class AddAllTapsItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Tap> mTaps;
|
||||
|
||||
public AddAllTapsItem(final List<Tap> taps)
|
||||
{
|
||||
super("All Taps");
|
||||
|
||||
mTaps = taps;
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
for(Tap tap : mTaps)
|
||||
{
|
||||
DecoderViewFrame.this.add(tap);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class TapSelectionItem extends JCheckBoxMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Tap mTap;
|
||||
|
||||
public TapSelectionItem(Tap tap)
|
||||
{
|
||||
super(tap.getName());
|
||||
|
||||
mTap = tap;
|
||||
|
||||
if(mPanelMap.keySet().contains(tap))
|
||||
{
|
||||
setSelected(true);
|
||||
}
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
if(mPanelMap.keySet().contains(mTap))
|
||||
{
|
||||
DecoderViewFrame.this.remove(mTap);
|
||||
}
|
||||
else
|
||||
{
|
||||
DecoderViewFrame.this.add(mTap);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
mLog.info(message.toString());
|
||||
}
|
||||
|
||||
public class TapGroupMenu extends JMenu
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private TapGroup mTapGroup;
|
||||
|
||||
public TapGroupMenu(TapGroup tapGroup)
|
||||
{
|
||||
super(tapGroup.getName());
|
||||
|
||||
mTapGroup = tapGroup;
|
||||
|
||||
add(new AddAllTapsItem(mTapGroup.getTaps()));
|
||||
|
||||
add(new JSeparator());
|
||||
|
||||
for(Tap tap : mTapGroup.getTaps())
|
||||
{
|
||||
add(new TapSelectionItem(tap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TapGroupMenu extends JMenu
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private TapGroup mTapGroup;
|
||||
|
||||
public TapGroupMenu( TapGroup tapGroup )
|
||||
{
|
||||
super( tapGroup.getName() );
|
||||
|
||||
mTapGroup = tapGroup;
|
||||
|
||||
add( new AddAllTapsItem( mTapGroup.getTaps() ) );
|
||||
|
||||
add( new JSeparator() );
|
||||
|
||||
for( Tap tap: mTapGroup.getTaps() )
|
||||
{
|
||||
add( new TapSelectionItem( tap ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015-2016 Dennis Sheirer
|
||||
* 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 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 module;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketListener;
|
||||
import audio.IAudioPacketProvider;
|
||||
import audio.metadata.IMetadataListener;
|
||||
import audio.metadata.IMetadataProvider;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.ISquelchStateProvider;
|
||||
import audio.squelch.SquelchState;
|
||||
import channel.state.ChannelState;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.IDecoderStateEventListener;
|
||||
import channel.state.IDecoderStateEventProvider;
|
||||
import channel.state.State;
|
||||
import controller.NamingThreadFactory;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelEvent;
|
||||
@@ -39,13 +44,6 @@ import module.decode.event.CallEventModel;
|
||||
import module.decode.event.ICallEventListener;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.event.MessageActivityModel;
|
||||
import channel.state.ChannelState;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.IDecoderStateEventListener;
|
||||
import channel.state.IDecoderStateEventProvider;
|
||||
import channel.state.State;
|
||||
import module.log.EventLogger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -98,7 +96,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ProcessingChain.class);
|
||||
|
||||
private Broadcaster<AudioPacket> mAudioPacketBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<Metadata> mMetadataBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<CallEvent> mCallEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<ChannelEvent> mChannelEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<ComplexBuffer> mComplexBufferBroadcaster = new Broadcaster<>();
|
||||
@@ -186,17 +183,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the metadata to any registered listeners
|
||||
*/
|
||||
public void broadcast(Metadata metadata)
|
||||
{
|
||||
if(mMetadataBroadcaster != null)
|
||||
{
|
||||
mMetadataBroadcaster.broadcast(metadata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this processing chain is currently receiving samples from
|
||||
* a source and sending those samples to the decoders.
|
||||
@@ -227,9 +213,8 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
if(isProcessing())
|
||||
{
|
||||
throw new IllegalStateException("Processing chain is currently "
|
||||
+ "processing. Invoke stop() on the processing chain before "
|
||||
+ "applying a new sample source");
|
||||
throw new IllegalStateException("Processing chain is currently processing. Invoke stop() on the " +
|
||||
"processing chain before applying a new sample source");
|
||||
}
|
||||
|
||||
mSource = source;
|
||||
@@ -314,68 +299,52 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
if(module instanceof IAudioPacketListener)
|
||||
{
|
||||
mAudioPacketBroadcaster.addListener(
|
||||
((IAudioPacketListener) module).getAudioPacketListener());
|
||||
mAudioPacketBroadcaster.addListener(((IAudioPacketListener) module).getAudioPacketListener());
|
||||
}
|
||||
|
||||
if(module instanceof ICallEventListener)
|
||||
{
|
||||
mCallEventBroadcaster.addListener(
|
||||
((ICallEventListener) module).getCallEventListener());
|
||||
mCallEventBroadcaster.addListener(((ICallEventListener) module).getCallEventListener());
|
||||
}
|
||||
|
||||
if(module instanceof IChannelEventListener)
|
||||
{
|
||||
mChannelEventBroadcaster.addListener(
|
||||
((IChannelEventListener) module).getChannelEventListener());
|
||||
mChannelEventBroadcaster.addListener(((IChannelEventListener) module).getChannelEventListener());
|
||||
}
|
||||
|
||||
if(module instanceof IComplexBufferListener)
|
||||
{
|
||||
mComplexBufferBroadcaster.addListener(
|
||||
((IComplexBufferListener) module).getComplexBufferListener());
|
||||
mComplexBufferBroadcaster.addListener(((IComplexBufferListener) module).getComplexBufferListener());
|
||||
}
|
||||
|
||||
if(module instanceof IDecoderStateEventListener)
|
||||
{
|
||||
mDecoderStateEventBroadcaster.addListener(
|
||||
((IDecoderStateEventListener) module).getDecoderStateListener());
|
||||
mDecoderStateEventBroadcaster.addListener(((IDecoderStateEventListener) module).getDecoderStateListener());
|
||||
}
|
||||
|
||||
if(module instanceof IFrequencyChangeListener)
|
||||
{
|
||||
mFrequencyChangeEventBroadcaster.addListener(
|
||||
((IFrequencyChangeListener) module).getFrequencyChangeListener());
|
||||
mFrequencyChangeEventBroadcaster.addListener(((IFrequencyChangeListener) module).getFrequencyChangeListener());
|
||||
}
|
||||
|
||||
if(module instanceof IMessageListener)
|
||||
{
|
||||
mMessageBroadcaster.addListener(
|
||||
((IMessageListener) module).getMessageListener());
|
||||
}
|
||||
|
||||
if(module instanceof IMetadataListener)
|
||||
{
|
||||
mMetadataBroadcaster.addListener(
|
||||
((IMetadataListener) module).getMetadataListener());
|
||||
mMessageBroadcaster.addListener(((IMessageListener) module).getMessageListener());
|
||||
}
|
||||
|
||||
if(module instanceof IFilteredRealBufferListener)
|
||||
{
|
||||
mFilteredRealBufferBroadcaster.addListener(
|
||||
((IFilteredRealBufferListener) module).getFilteredRealBufferListener());
|
||||
mFilteredRealBufferBroadcaster.addListener(((IFilteredRealBufferListener) module).getFilteredRealBufferListener());
|
||||
}
|
||||
|
||||
if(module instanceof ISquelchStateListener)
|
||||
{
|
||||
mSquelchStateBroadcaster.addListener(
|
||||
((ISquelchStateListener) module).getSquelchStateListener());
|
||||
mSquelchStateBroadcaster.addListener(((ISquelchStateListener) module).getSquelchStateListener());
|
||||
}
|
||||
|
||||
if(module instanceof IUnFilteredRealBufferListener)
|
||||
{
|
||||
mUnFilteredRealBufferBroadcaster.addListener(
|
||||
((IUnFilteredRealBufferListener) module).getUnFilteredRealBufferListener());
|
||||
mUnFilteredRealBufferBroadcaster.addListener(((IUnFilteredRealBufferListener) module).getUnFilteredRealBufferListener());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,38 +356,32 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
if(module instanceof IAudioPacketListener)
|
||||
{
|
||||
mAudioPacketBroadcaster.removeListener(
|
||||
((IAudioPacketListener) module).getAudioPacketListener());
|
||||
mAudioPacketBroadcaster.removeListener(((IAudioPacketListener) module).getAudioPacketListener());
|
||||
}
|
||||
|
||||
if(module instanceof ICallEventListener)
|
||||
{
|
||||
mCallEventBroadcaster.removeListener(
|
||||
((ICallEventListener) module).getCallEventListener());
|
||||
mCallEventBroadcaster.removeListener(((ICallEventListener) module).getCallEventListener());
|
||||
}
|
||||
|
||||
if(module instanceof IChannelEventListener)
|
||||
{
|
||||
mChannelEventBroadcaster.removeListener(
|
||||
((IChannelEventListener) module).getChannelEventListener());
|
||||
mChannelEventBroadcaster.removeListener(((IChannelEventListener) module).getChannelEventListener());
|
||||
}
|
||||
|
||||
if(module instanceof IComplexBufferListener)
|
||||
{
|
||||
mComplexBufferBroadcaster.removeListener(
|
||||
((IComplexBufferListener) module).getComplexBufferListener());
|
||||
mComplexBufferBroadcaster.removeListener(((IComplexBufferListener) module).getComplexBufferListener());
|
||||
}
|
||||
|
||||
if(module instanceof IDecoderStateEventListener)
|
||||
{
|
||||
mDecoderStateEventBroadcaster.removeListener(
|
||||
((IDecoderStateEventListener) module).getDecoderStateListener());
|
||||
mDecoderStateEventBroadcaster.removeListener(((IDecoderStateEventListener) module).getDecoderStateListener());
|
||||
}
|
||||
|
||||
if(module instanceof IFrequencyChangeListener)
|
||||
{
|
||||
mFrequencyChangeEventBroadcaster.removeListener(
|
||||
((IFrequencyChangeListener) module).getFrequencyChangeListener());
|
||||
mFrequencyChangeEventBroadcaster.removeListener(((IFrequencyChangeListener) module).getFrequencyChangeListener());
|
||||
}
|
||||
|
||||
if(module instanceof IMessageListener)
|
||||
@@ -426,27 +389,19 @@ public class ProcessingChain implements IChannelEventListener
|
||||
mMessageBroadcaster.removeListener(((IMessageListener) module).getMessageListener());
|
||||
}
|
||||
|
||||
if(module instanceof IMetadataListener)
|
||||
{
|
||||
mMetadataBroadcaster.removeListener(((IMetadataListener) module).getMetadataListener());
|
||||
}
|
||||
|
||||
if(module instanceof IFilteredRealBufferListener)
|
||||
{
|
||||
mFilteredRealBufferBroadcaster.removeListener(
|
||||
((IFilteredRealBufferListener) module).getFilteredRealBufferListener());
|
||||
mFilteredRealBufferBroadcaster.removeListener(((IFilteredRealBufferListener) module).getFilteredRealBufferListener());
|
||||
}
|
||||
|
||||
if(module instanceof ISquelchStateListener)
|
||||
{
|
||||
mSquelchStateBroadcaster.removeListener(
|
||||
((ISquelchStateListener) module).getSquelchStateListener());
|
||||
mSquelchStateBroadcaster.removeListener(((ISquelchStateListener) module).getSquelchStateListener());
|
||||
}
|
||||
|
||||
if(module instanceof IUnFilteredRealBufferListener)
|
||||
{
|
||||
mUnFilteredRealBufferBroadcaster.removeListener(
|
||||
((IUnFilteredRealBufferListener) module).getUnFilteredRealBufferListener());
|
||||
mUnFilteredRealBufferBroadcaster.removeListener(((IUnFilteredRealBufferListener) module).getUnFilteredRealBufferListener());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,8 +413,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
if(module instanceof IAudioPacketProvider)
|
||||
{
|
||||
((IAudioPacketProvider) module).setAudioPacketListener(
|
||||
mAudioPacketBroadcaster);
|
||||
((IAudioPacketProvider) module).setAudioPacketListener(mAudioPacketBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof ICallEventProvider)
|
||||
@@ -469,20 +423,17 @@ public class ProcessingChain implements IChannelEventListener
|
||||
|
||||
if(module instanceof IChannelEventProvider)
|
||||
{
|
||||
((IChannelEventProvider) module).setChannelEventListener(
|
||||
mChannelEventBroadcaster);
|
||||
((IChannelEventProvider) module).setChannelEventListener(mChannelEventBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IDecoderStateEventProvider)
|
||||
{
|
||||
((IDecoderStateEventProvider) module).setDecoderStateListener(
|
||||
mDecoderStateEventBroadcaster);
|
||||
((IDecoderStateEventProvider) module).setDecoderStateListener(mDecoderStateEventBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IFrequencyChangeProvider)
|
||||
{
|
||||
((IFrequencyChangeProvider) module).setFrequencyChangeListener(
|
||||
mFrequencyChangeEventBroadcaster);
|
||||
((IFrequencyChangeProvider) module).setFrequencyChangeListener(mFrequencyChangeEventBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IMessageProvider)
|
||||
@@ -490,28 +441,19 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((IMessageProvider) module).setMessageListener(mMessageBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IMetadataProvider)
|
||||
{
|
||||
((IMetadataProvider) module).setMetadataListener(
|
||||
mMetadataBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IFilteredRealBufferProvider)
|
||||
{
|
||||
((IFilteredRealBufferProvider) module)
|
||||
.setFilteredRealBufferListener(mFilteredRealBufferBroadcaster);
|
||||
((IFilteredRealBufferProvider) module).setFilteredRealBufferListener(mFilteredRealBufferBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof ISquelchStateProvider)
|
||||
{
|
||||
((ISquelchStateProvider) module).setSquelchStateListener(
|
||||
mSquelchStateBroadcaster);
|
||||
((ISquelchStateProvider) module).setSquelchStateListener(mSquelchStateBroadcaster);
|
||||
}
|
||||
|
||||
if(module instanceof IUnFilteredRealBufferProvider)
|
||||
{
|
||||
((IUnFilteredRealBufferProvider) module)
|
||||
.setUnFilteredRealBufferListener(mUnFilteredRealBufferBroadcaster);
|
||||
((IUnFilteredRealBufferProvider) module).setUnFilteredRealBufferListener(mUnFilteredRealBufferBroadcaster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,11 +493,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((IMessageProvider) module).setMessageListener(null);
|
||||
}
|
||||
|
||||
if(module instanceof IMetadataProvider)
|
||||
{
|
||||
((IMetadataProvider) module).setMetadataListener(null);
|
||||
}
|
||||
|
||||
if(module instanceof IFilteredRealBufferProvider)
|
||||
{
|
||||
((IFilteredRealBufferProvider) module).setFilteredRealBufferListener(null);
|
||||
@@ -587,7 +524,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
module.reset();
|
||||
}
|
||||
|
||||
|
||||
/* Register with the source to receive sample data. Setup a
|
||||
* timer task to process the buffer queues 50 times a second
|
||||
* (every 20 ms) */
|
||||
@@ -615,8 +552,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
long frequency = tcs.getFrequency();
|
||||
|
||||
mDecoderStateEventBroadcaster.broadcast(
|
||||
new DecoderStateEvent(this, Event.SOURCE_FREQUENCY,
|
||||
State.IDLE, frequency));
|
||||
new DecoderStateEvent(this, Event.SOURCE_FREQUENCY, State.IDLE, frequency));
|
||||
}
|
||||
catch(SourceException e)
|
||||
{
|
||||
@@ -697,7 +633,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
List<Module> eventLoggingModules = new ArrayList<>();
|
||||
|
||||
for(Module module: mModules)
|
||||
for(Module module : mModules)
|
||||
{
|
||||
if(module instanceof EventLogger)
|
||||
{
|
||||
@@ -705,7 +641,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
}
|
||||
}
|
||||
|
||||
for(Module eventLoggingModule: eventLoggingModules)
|
||||
for(Module eventLoggingModule : eventLoggingModules)
|
||||
{
|
||||
removeModule(eventLoggingModule);
|
||||
}
|
||||
@@ -718,7 +654,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
List<Module> recordingModules = new ArrayList<>();
|
||||
|
||||
for(Module module: mModules)
|
||||
for(Module module : mModules)
|
||||
{
|
||||
if(module instanceof RealBufferWaveRecorder || module instanceof ComplexBufferWaveRecorder)
|
||||
{
|
||||
@@ -726,7 +662,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
}
|
||||
}
|
||||
|
||||
for(Module recordingModule: recordingModules)
|
||||
for(Module recordingModule : recordingModules)
|
||||
{
|
||||
removeModule(recordingModule);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ package module.decode;
|
||||
import alias.AliasList;
|
||||
import alias.AliasModel;
|
||||
import audio.AudioModule;
|
||||
import channel.metadata.Metadata;
|
||||
import channel.state.AlwaysUnsquelchedDecoderState;
|
||||
import channel.traffic.TrafficChannelManager;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelModel;
|
||||
@@ -32,55 +35,45 @@ import filter.FilterSet;
|
||||
import filter.IFilter;
|
||||
import gui.editor.EmptyValidatingEditor;
|
||||
import gui.editor.ValidatingEditor;
|
||||
import icon.IconManager;
|
||||
import message.Message;
|
||||
import message.MessageDirection;
|
||||
import module.Module;
|
||||
import module.decode.am.AMDecoder;
|
||||
import module.decode.am.AMDecoderEditor;
|
||||
import module.decode.am.AMDecoderPanel;
|
||||
import module.decode.am.DecodeConfigAM;
|
||||
import module.decode.config.AuxDecodeConfiguration;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.fleetsync2.Fleetsync2Decoder;
|
||||
import module.decode.fleetsync2.Fleetsync2DecoderPanel;
|
||||
import module.decode.fleetsync2.Fleetsync2DecoderState;
|
||||
import module.decode.fleetsync2.FleetsyncMessageFilter;
|
||||
import module.decode.lj1200.LJ1200Decoder;
|
||||
import module.decode.lj1200.LJ1200DecoderPanel;
|
||||
import module.decode.lj1200.LJ1200DecoderState;
|
||||
import module.decode.lj1200.LJ1200MessageFilter;
|
||||
import module.decode.ltrnet.DecodeConfigLTRNet;
|
||||
import module.decode.ltrnet.LTRNetDecoder;
|
||||
import module.decode.ltrnet.LTRNetDecoderEditor;
|
||||
import module.decode.ltrnet.LTRNetDecoderPanel;
|
||||
import module.decode.ltrnet.LTRNetDecoderState;
|
||||
import module.decode.ltrnet.LTRNetMessageFilter;
|
||||
import module.decode.ltrstandard.DecodeConfigLTRStandard;
|
||||
import module.decode.ltrstandard.LTRStandardDecoder;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderEditor;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderPanel;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderState;
|
||||
import module.decode.ltrstandard.LTRStandardMessageFilter;
|
||||
import module.decode.mdc1200.MDCDecoder;
|
||||
import module.decode.mdc1200.MDCDecoderPanel;
|
||||
import module.decode.mdc1200.MDCDecoderState;
|
||||
import module.decode.mdc1200.MDCMessageFilter;
|
||||
import module.decode.mpt1327.DecodeConfigMPT1327;
|
||||
import module.decode.mpt1327.MPT1327Decoder;
|
||||
import module.decode.mpt1327.MPT1327Decoder.Sync;
|
||||
import module.decode.mpt1327.MPT1327DecoderEditor;
|
||||
import module.decode.mpt1327.MPT1327DecoderPanel;
|
||||
import module.decode.mpt1327.MPT1327DecoderState;
|
||||
import module.decode.mpt1327.MPT1327MessageFilter;
|
||||
import module.decode.nbfm.DecodeConfigNBFM;
|
||||
import module.decode.nbfm.NBFMDecoder;
|
||||
import module.decode.nbfm.NBFMDecoderEditor;
|
||||
import module.decode.nbfm.NBFMDecoderPanel;
|
||||
import module.decode.p25.DecodeConfigP25Phase1;
|
||||
import module.decode.p25.P25Decoder.Modulation;
|
||||
import module.decode.p25.P25DecoderEditor;
|
||||
import module.decode.p25.P25DecoderPanel;
|
||||
import module.decode.p25.P25DecoderState;
|
||||
import module.decode.p25.P25_C4FMDecoder;
|
||||
import module.decode.p25.P25_LSMDecoder;
|
||||
@@ -89,26 +82,14 @@ import module.decode.p25.message.filter.P25MessageFilterSet;
|
||||
import module.decode.passport.DecodeConfigPassport;
|
||||
import module.decode.passport.PassportDecoder;
|
||||
import module.decode.passport.PassportDecoderEditor;
|
||||
import module.decode.passport.PassportDecoderPanel;
|
||||
import module.decode.passport.PassportDecoderState;
|
||||
import module.decode.passport.PassportMessageFilter;
|
||||
import channel.state.AlwaysUnsquelchedDecoderState;
|
||||
import channel.state.DecoderPanel;
|
||||
import channel.state.DecoderState;
|
||||
import channel.traffic.TrafficChannelManager;
|
||||
import module.decode.tait.Tait1200Decoder;
|
||||
import module.decode.tait.Tait1200DecoderPanel;
|
||||
import module.decode.tait.Tait1200DecoderState;
|
||||
import module.demodulate.am.AMDemodulatorModule;
|
||||
import module.demodulate.audio.DemodulatedAudioFilterModule;
|
||||
import module.demodulate.fm.FMDemodulatorModule;
|
||||
import properties.SystemProperties;
|
||||
import record.RecorderType;
|
||||
import record.config.RecordConfiguration;
|
||||
import settings.SettingsManager;
|
||||
import util.TimeStamp;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -129,14 +110,15 @@ public class DecoderFactory
|
||||
ChannelMapModel channelMapModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
AliasModel aliasModel,
|
||||
Channel channel)
|
||||
Channel channel,
|
||||
Metadata metadata)
|
||||
{
|
||||
|
||||
/* Get the optional alias list for the decode modules to use */
|
||||
AliasList aliasList = aliasModel.getAliasList(channel.getAliasListName());
|
||||
|
||||
List<Module> modules = getPrimaryModules(channelModel, channelMapModel,
|
||||
channelProcessingManager, aliasList, channel);
|
||||
List<Module> modules = getPrimaryModules(channelModel, channelMapModel, channelProcessingManager, aliasList,
|
||||
channel, metadata);
|
||||
|
||||
modules.addAll(getAuxiliaryDecoders(channel.getAuxDecodeConfiguration(), aliasList));
|
||||
|
||||
@@ -150,7 +132,7 @@ public class DecoderFactory
|
||||
ChannelMapModel channelMapModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
AliasList aliasList,
|
||||
Channel channel)
|
||||
Channel channel, Metadata metadata)
|
||||
{
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
|
||||
@@ -162,11 +144,6 @@ public class DecoderFactory
|
||||
int iqPass = decodeConfig.getDecoderType().getChannelBandwidth() / 2;
|
||||
int iqStop = iqPass + 1250;
|
||||
|
||||
RecordConfiguration recordConfig = channel.getRecordConfiguration();
|
||||
|
||||
boolean recordAudio = recordConfig == null ? false :
|
||||
recordConfig.getRecorders().contains(RecorderType.AUDIO);
|
||||
|
||||
switch(decodeConfig.getDecoderType())
|
||||
{
|
||||
case AM:
|
||||
@@ -174,14 +151,14 @@ public class DecoderFactory
|
||||
modules.add(new AlwaysUnsquelchedDecoderState(DecoderType.AM, channel.getName()));
|
||||
modules.add(new AMDemodulatorModule());
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case NBFM:
|
||||
modules.add(new NBFMDecoder(decodeConfig));
|
||||
modules.add(new AlwaysUnsquelchedDecoderState(DecoderType.NBFM, channel.getName()));
|
||||
modules.add(new FMDemodulatorModule(iqPass, iqStop));
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case LTR_STANDARD:
|
||||
MessageDirection direction = ((DecodeConfigLTRStandard) decodeConfig).getMessageDirection();
|
||||
@@ -189,49 +166,46 @@ public class DecoderFactory
|
||||
modules.add(new LTRStandardDecoderState(aliasList));
|
||||
modules.add(new FMDemodulatorModule(iqPass, iqStop));
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case LTR_NET:
|
||||
modules.add(new LTRNetDecoder((DecodeConfigLTRNet) decodeConfig, aliasList));
|
||||
modules.add(new LTRNetDecoderState(aliasList));
|
||||
modules.add(new FMDemodulatorModule(iqPass, iqStop));
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case MPT1327:
|
||||
DecodeConfigMPT1327 mptConfig = (DecodeConfigMPT1327) decodeConfig;
|
||||
|
||||
ChannelMap channelMap = channelMapModel
|
||||
.getChannelMap(mptConfig.getChannelMapName());
|
||||
ChannelMap channelMap = channelMapModel.getChannelMap(mptConfig.getChannelMapName());
|
||||
|
||||
Sync sync = mptConfig.getSync();
|
||||
|
||||
modules.add(new MPT1327Decoder(aliasList, sync));
|
||||
|
||||
|
||||
modules.add(new MPT1327DecoderState(aliasList, channelMap,
|
||||
channelType, mptConfig.getCallTimeout() * 1000));
|
||||
modules.add(new MPT1327DecoderState(aliasList, channelMap, channelType, mptConfig.getCallTimeout() * 1000));
|
||||
|
||||
if(channelType == ChannelType.STANDARD)
|
||||
{
|
||||
long timeout = mptConfig.getCallTimeout() * 1000; //convert to milliseconds
|
||||
|
||||
modules.add(new TrafficChannelManager(channelModel, channelProcessingManager,
|
||||
decodeConfig, recordConfig, channel.getSystem(),
|
||||
channel.getSite(), (aliasList != null ? aliasList.getName() : null), timeout,
|
||||
mptConfig.getTrafficChannelPoolSize()));
|
||||
modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig,
|
||||
channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(),
|
||||
(aliasList != null ? aliasList.getName() : null), timeout, mptConfig.getTrafficChannelPoolSize()));
|
||||
}
|
||||
|
||||
modules.add(new FMDemodulatorModule(iqPass, iqStop));
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case PASSPORT:
|
||||
modules.add(new PassportDecoder(decodeConfig, aliasList));
|
||||
modules.add(new PassportDecoderState(aliasList));
|
||||
modules.add(new FMDemodulatorModule(iqPass, iqStop));
|
||||
modules.add(new DemodulatedAudioFilterModule(4000, 6000));
|
||||
modules.add(new AudioModule(recordAudio));
|
||||
modules.add(new AudioModule(metadata));
|
||||
break;
|
||||
case P25_PHASE1:
|
||||
DecodeConfigP25Phase1 p25Config = (DecodeConfigP25Phase1) decodeConfig;
|
||||
@@ -244,17 +218,15 @@ public class DecoderFactory
|
||||
case C4FM:
|
||||
modules.add(new FMDemodulatorModule(6750, 7500));
|
||||
modules.add(new P25_C4FMDecoder(aliasList, decodeConfig.getAFCMaximumCorrection()));
|
||||
modules.add(new P25DecoderState(aliasList, channelType,
|
||||
Modulation.C4FM, p25Config.getIgnoreDataCalls()));
|
||||
modules.add(new P25DecoderState(aliasList, channelType, Modulation.C4FM,
|
||||
p25Config.getIgnoreDataCalls()));
|
||||
break;
|
||||
case CQPSK:
|
||||
modules.add(new P25_LSMDecoder(aliasList));
|
||||
modules.add(new P25DecoderState(aliasList, channelType,
|
||||
Modulation.CQPSK, p25Config.getIgnoreDataCalls()));
|
||||
modules.add(new P25DecoderState(aliasList, channelType, Modulation.CQPSK, p25Config.getIgnoreDataCalls()));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized P25 "
|
||||
+ "Phase 1 Modulation [" + modulation + "]");
|
||||
throw new IllegalArgumentException("Unrecognized P25 Phase 1 Modulation [" + modulation + "]");
|
||||
}
|
||||
|
||||
if(channelType == ChannelType.STANDARD)
|
||||
@@ -262,19 +234,15 @@ public class DecoderFactory
|
||||
//Set call timeout to 3 seconds for P25 traffic channels
|
||||
long timeout = 3000;
|
||||
|
||||
modules.add(new TrafficChannelManager(channelModel,
|
||||
channelProcessingManager, decodeConfig,
|
||||
recordConfig, channel.getSystem(), channel.getSite(),
|
||||
(aliasList != null ? aliasList.getName() : null), timeout,
|
||||
p25Config.getTrafficChannelPoolSize()));
|
||||
modules.add(new TrafficChannelManager(channelModel, channelProcessingManager, decodeConfig,
|
||||
channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(),
|
||||
(aliasList != null ? aliasList.getName() : null), timeout, p25Config.getTrafficChannelPoolSize()));
|
||||
}
|
||||
|
||||
modules.add(new P25AudioModule(recordAudio));
|
||||
modules.add(new P25AudioModule(metadata));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown decoder type [" +
|
||||
decodeConfig.getDecoderType().toString() + "]");
|
||||
throw new IllegalArgumentException("Unknown decoder type [" + decodeConfig.getDecoderType().toString() + "]");
|
||||
}
|
||||
|
||||
return modules;
|
||||
@@ -324,39 +292,6 @@ public class DecoderFactory
|
||||
return modules;
|
||||
}
|
||||
|
||||
public static DecoderPanel getDecoderPanel(IconManager iconManager, SettingsManager settingsManager,
|
||||
DecoderState decoderState)
|
||||
{
|
||||
switch(decoderState.getDecoderType())
|
||||
{
|
||||
case AM:
|
||||
return new AMDecoderPanel(iconManager, settingsManager, decoderState);
|
||||
case FLEETSYNC2:
|
||||
return new Fleetsync2DecoderPanel(iconManager, settingsManager, (Fleetsync2DecoderState) decoderState);
|
||||
case LJ_1200:
|
||||
return new LJ1200DecoderPanel(iconManager, settingsManager, (LJ1200DecoderState) decoderState);
|
||||
case LTR_NET:
|
||||
return new LTRNetDecoderPanel(iconManager, settingsManager, (LTRNetDecoderState) decoderState);
|
||||
case LTR_STANDARD:
|
||||
return new LTRStandardDecoderPanel(iconManager, settingsManager, (LTRStandardDecoderState) decoderState);
|
||||
case MDC1200:
|
||||
return new MDCDecoderPanel(iconManager, settingsManager, (MDCDecoderState) decoderState);
|
||||
case MPT1327:
|
||||
return new MPT1327DecoderPanel(iconManager, settingsManager, (MPT1327DecoderState) decoderState);
|
||||
case NBFM:
|
||||
return new NBFMDecoderPanel(iconManager, settingsManager, decoderState);
|
||||
case P25_PHASE1:
|
||||
return new P25DecoderPanel(iconManager, settingsManager, (P25DecoderState) decoderState);
|
||||
case PASSPORT:
|
||||
return new PassportDecoderPanel(iconManager, settingsManager, (PassportDecoderState) decoderState);
|
||||
case TAIT_1200:
|
||||
return new Tait1200DecoderPanel(iconManager, settingsManager, (Tait1200DecoderState) decoderState);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized decoder: " +
|
||||
decoderState.getDecoderType().getDisplayString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a filter set containing filters for the primary channel
|
||||
* decoder and each of the auxiliary decoders
|
||||
@@ -451,8 +386,7 @@ public class DecoderFactory
|
||||
case P25_PHASE1:
|
||||
return new DecodeConfigP25Phase1();
|
||||
default:
|
||||
throw new IllegalArgumentException("DecodeConfigFactory - unknown decoder type ["
|
||||
+ decoder.toString() + "]");
|
||||
throw new IllegalArgumentException("DecodeConfigFactory - unknown decoder type [" + decoder.toString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,25 +476,10 @@ public class DecoderFactory
|
||||
copyPass.setAFCMaximumCorrection(originalPass.getAFCMaximumCorrection());
|
||||
return copyPass;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized decoder "
|
||||
+ "configuration type:" + config.getDecoderType());
|
||||
throw new IllegalArgumentException("Unrecognized decoder configuration type:" + config.getDecoderType());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getRecordingFilename(String token)
|
||||
{
|
||||
//Get the base recording filename
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(SystemProperties.getInstance()
|
||||
.getApplicationFolder("recordings"));
|
||||
sb.append(File.separator);
|
||||
sb.append(TimeStamp.getTimeStamp("_"));
|
||||
sb.append("_");
|
||||
sb.append(token);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +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 module.decode.am;
|
||||
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import channel.state.DecoderState;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class AMDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("AM");
|
||||
|
||||
public AMDecoderPanel(IconManager iconManager, SettingsManager settingsManager, DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,324 +1,309 @@
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
* 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 module.decode.event;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import module.decode.DecoderType;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import module.decode.DecoderType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import audio.metadata.MetadataType;
|
||||
|
||||
public abstract class CallEvent implements Comparable<CallEvent>
|
||||
{
|
||||
protected long mEventStart = System.currentTimeMillis();
|
||||
protected long mEventEnd;
|
||||
|
||||
private SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd','HHmmss" );
|
||||
protected long mEventStart = System.currentTimeMillis();
|
||||
protected long mEventEnd;
|
||||
|
||||
protected DecoderType mDecoderType;
|
||||
protected CallEventType mCallEventType;
|
||||
protected AliasList mAliasList;
|
||||
protected String mFromID;
|
||||
protected String mToID;
|
||||
protected String mDetails;
|
||||
|
||||
private boolean mValid = true;
|
||||
|
||||
public CallEvent( DecoderType decoder,
|
||||
CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
String details )
|
||||
{
|
||||
mDecoderType = decoder;
|
||||
mCallEventType = callEventType;
|
||||
mAliasList = aliasList;
|
||||
mFromID = fromID;
|
||||
mToID = toID;
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this event is valid. Use this method to mark a previously
|
||||
* dispatched event as invalid and resend it so that any downstream
|
||||
* processing can remove the invalid event.
|
||||
*/
|
||||
public void setValid( boolean valid )
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
private SimpleDateFormat mSDF = new SimpleDateFormat("yyyyMMdd','HHmmss");
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mValid;
|
||||
}
|
||||
|
||||
public void setEnd( long end )
|
||||
{
|
||||
mEventEnd = end;
|
||||
}
|
||||
|
||||
public void end()
|
||||
{
|
||||
setEnd( System.currentTimeMillis() );
|
||||
}
|
||||
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return mDecoderType;
|
||||
}
|
||||
|
||||
public CallEventType getCallEventType()
|
||||
{
|
||||
return mCallEventType;
|
||||
}
|
||||
|
||||
public void setCallEventType( CallEventType type )
|
||||
{
|
||||
mCallEventType = type;
|
||||
}
|
||||
protected DecoderType mDecoderType;
|
||||
protected CallEventType mCallEventType;
|
||||
protected AliasList mAliasList;
|
||||
protected String mFromID;
|
||||
protected String mToID;
|
||||
protected String mDetails;
|
||||
|
||||
public AliasList getAliasList()
|
||||
{
|
||||
return mAliasList;
|
||||
}
|
||||
|
||||
public void setAliasList( AliasList aliasList )
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
}
|
||||
|
||||
public boolean hasAliasList()
|
||||
{
|
||||
return mAliasList != null;
|
||||
}
|
||||
|
||||
public long getEventStartTime()
|
||||
{
|
||||
return mEventStart;
|
||||
}
|
||||
|
||||
public long getEventEndTime()
|
||||
{
|
||||
return mEventEnd;
|
||||
}
|
||||
|
||||
public String getFromID()
|
||||
{
|
||||
return mFromID;
|
||||
}
|
||||
|
||||
public boolean hasFromID()
|
||||
{
|
||||
return mFromID != null;
|
||||
}
|
||||
|
||||
public MetadataType getFromIDType()
|
||||
{
|
||||
return MetadataType.FROM;
|
||||
}
|
||||
|
||||
public void setFromID( String id )
|
||||
{
|
||||
mFromID = id;
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
{
|
||||
return mToID;
|
||||
}
|
||||
|
||||
public boolean hasToID()
|
||||
{
|
||||
return mToID != null;
|
||||
}
|
||||
|
||||
public void setToID( String id )
|
||||
{
|
||||
mToID = id;
|
||||
}
|
||||
private boolean mValid = true;
|
||||
|
||||
public MetadataType getToIDType()
|
||||
{
|
||||
return MetadataType.TO;
|
||||
}
|
||||
|
||||
public String getDetails()
|
||||
{
|
||||
return mDetails;
|
||||
}
|
||||
|
||||
public void setDetails( String details )
|
||||
{
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
public abstract Alias getFromIDAlias();
|
||||
|
||||
public abstract Alias getToIDAlias();
|
||||
|
||||
public abstract String getChannel();
|
||||
public CallEvent(DecoderType decoder, CallEventType callEventType, AliasList aliasList, String fromID,
|
||||
String toID, String details)
|
||||
{
|
||||
mDecoderType = decoder;
|
||||
mCallEventType = callEventType;
|
||||
mAliasList = aliasList;
|
||||
mFromID = fromID;
|
||||
mToID = toID;
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
public abstract long getFrequency();
|
||||
|
||||
public static String getCSVHeader()
|
||||
{
|
||||
return "START_DATE,START_TIME,END_DATE,END_TIME,"
|
||||
+ "DECODER,EVENT,FROM,FROM_ALIAS,TO,TO_ALIAS,"
|
||||
+ "CHANNEL,FREQUENCY,DETAILS";
|
||||
}
|
||||
|
||||
public String toCSV()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
/**
|
||||
* Indicates if this event is valid. Use this method to mark a previously
|
||||
* dispatched event as invalid and resend it so that any downstream
|
||||
* processing can remove the invalid event.
|
||||
*/
|
||||
public void setValid(boolean valid)
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
|
||||
sb.append( "'" );
|
||||
sb.append( mSDF.format( new Date( getEventStartTime() ) ) );
|
||||
sb.append( "','" );
|
||||
if( mEventEnd != 0 )
|
||||
{
|
||||
sb.append( mSDF.format( new Date( getEventEndTime() ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "','" );
|
||||
}
|
||||
sb.append( "','" );
|
||||
sb.append( getDecoderType().toString() );
|
||||
sb.append( "','" );
|
||||
sb.append( getCallEventType().toString() );
|
||||
sb.append( "'," );
|
||||
if( getFromID() != null )
|
||||
{
|
||||
sb.append( "'" );
|
||||
sb.append( getFromID() );
|
||||
sb.append( "'" );
|
||||
}
|
||||
sb.append( "," );
|
||||
|
||||
Alias fromAlias = getFromIDAlias();
|
||||
|
||||
if( fromAlias != null )
|
||||
{
|
||||
sb.append( "'" );
|
||||
sb.append( fromAlias.getName() );
|
||||
sb.append( "'" );
|
||||
}
|
||||
sb.append( "," );
|
||||
public boolean isValid()
|
||||
{
|
||||
return mValid;
|
||||
}
|
||||
|
||||
if( getToID() != null )
|
||||
{
|
||||
sb.append( "'" );
|
||||
sb.append( getToID() );
|
||||
sb.append( "'" );
|
||||
}
|
||||
sb.append( "," );
|
||||
|
||||
Alias toAlias = getToIDAlias();
|
||||
|
||||
if( toAlias != null )
|
||||
{
|
||||
sb.append( "'" );
|
||||
sb.append( toAlias.getName() );
|
||||
sb.append( "'" );
|
||||
}
|
||||
sb.append( ",'" );
|
||||
sb.append( getChannel() );
|
||||
sb.append( "','" );
|
||||
sb.append( getFrequency() );
|
||||
sb.append( "'," );
|
||||
if( getDetails() != null )
|
||||
{
|
||||
sb.append( "'" );
|
||||
sb.append( getDetails() );
|
||||
sb.append( "'" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public enum CallEventType
|
||||
{
|
||||
ANNOUNCEMENT( "Announcement" ),
|
||||
CALL( "Call" ),
|
||||
CALL_ALERT( "Call Alert" ),
|
||||
CALL_DETECT( "Call Detect" ),
|
||||
CALL_DO_NOT_MONITOR( "Call-Do Not Monitor" ),
|
||||
CALL_END( "Call End" ),
|
||||
CALL_UNIQUE_ID( "UID Call" ),
|
||||
CALL_NO_TUNER( "Call - No Tuner" ),
|
||||
CALL_TIMEOUT( "Call Timeout" ),
|
||||
COMMAND( "Command" ),
|
||||
DATA_CALL( "Data Call" ),
|
||||
DEREGISTER( "Deregister" ),
|
||||
EMERGENCY( "EMERGENCY" ),
|
||||
ENCRYPTED_CALL( "Encrypted Call" ),
|
||||
FUNCTION( "Function" ),
|
||||
GPS( "GPS" ),
|
||||
GROUP_CALL( "Group Call" ),
|
||||
ID_ANI( "ANI" ),
|
||||
ID_UNIQUE( "Unique ID" ),
|
||||
NOTIFICATION( "Notification" ),
|
||||
PAGE( "Page" ),
|
||||
PATCH_GROUP_ADD( "Patch Group Add"),
|
||||
PATCH_GROUP_CALL( "Patch Group Call" ),
|
||||
PATCH_GROUP_DELETE( "Patch Group Delete"),
|
||||
QUERY( "Query" ),
|
||||
REGISTER( "Register" ),
|
||||
REGISTER_ESN( "ESN" ),
|
||||
RESPONSE( "Response" ),
|
||||
SDM( "Short Data Message" ),
|
||||
STATION_ID( "Station ID" ),
|
||||
STATUS( "Status" ),
|
||||
TELEPHONE_INTERCONNECT( "Telephone Interconnect" ),
|
||||
UNIT_TO_UNIT_CALL( "Unit To Unit Call" ),
|
||||
UNKNOWN( "Unknown" ),
|
||||
INVALID( "Invalid" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private CallEventType( String label )
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
public void setEnd(long end)
|
||||
{
|
||||
mEventEnd = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( CallEvent other )
|
||||
{
|
||||
if( other != null && other == this )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Long.compare( mEventStart, other.getEventStartTime() );
|
||||
}
|
||||
public void end()
|
||||
{
|
||||
setEnd(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return mDecoderType;
|
||||
}
|
||||
|
||||
public CallEventType getCallEventType()
|
||||
{
|
||||
return mCallEventType;
|
||||
}
|
||||
|
||||
public void setCallEventType(CallEventType type)
|
||||
{
|
||||
mCallEventType = type;
|
||||
}
|
||||
|
||||
public AliasList getAliasList()
|
||||
{
|
||||
return mAliasList;
|
||||
}
|
||||
|
||||
public void setAliasList(AliasList aliasList)
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
}
|
||||
|
||||
public boolean hasAliasList()
|
||||
{
|
||||
return mAliasList != null;
|
||||
}
|
||||
|
||||
public long getEventStartTime()
|
||||
{
|
||||
return mEventStart;
|
||||
}
|
||||
|
||||
public long getEventEndTime()
|
||||
{
|
||||
return mEventEnd;
|
||||
}
|
||||
|
||||
public String getFromID()
|
||||
{
|
||||
return mFromID;
|
||||
}
|
||||
|
||||
public boolean hasFromID()
|
||||
{
|
||||
return mFromID != null;
|
||||
}
|
||||
|
||||
public void setFromID(String id)
|
||||
{
|
||||
mFromID = id;
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
{
|
||||
return mToID;
|
||||
}
|
||||
|
||||
public boolean hasToID()
|
||||
{
|
||||
return mToID != null;
|
||||
}
|
||||
|
||||
public void setToID(String id)
|
||||
{
|
||||
mToID = id;
|
||||
}
|
||||
|
||||
public String getDetails()
|
||||
{
|
||||
return mDetails;
|
||||
}
|
||||
|
||||
public void setDetails(String details)
|
||||
{
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
public abstract Alias getFromIDAlias();
|
||||
|
||||
public abstract Alias getToIDAlias();
|
||||
|
||||
public abstract String getChannel();
|
||||
|
||||
public abstract long getFrequency();
|
||||
|
||||
public static String getCSVHeader()
|
||||
{
|
||||
return "START_DATE,START_TIME,END_DATE,END_TIME,DECODER,EVENT,FROM,FROM_ALIAS,TO,TO_ALIAS,CHANNEL," +
|
||||
"FREQUENCY,DETAILS";
|
||||
}
|
||||
|
||||
public String toCSV()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("'");
|
||||
sb.append(mSDF.format(new Date(getEventStartTime())));
|
||||
sb.append("','");
|
||||
if(mEventEnd != 0)
|
||||
{
|
||||
sb.append(mSDF.format(new Date(getEventEndTime())));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("','");
|
||||
}
|
||||
sb.append("','");
|
||||
sb.append(getDecoderType().toString());
|
||||
sb.append("','");
|
||||
sb.append(getCallEventType().toString());
|
||||
sb.append("',");
|
||||
if(getFromID() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getFromID());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
Alias fromAlias = getFromIDAlias();
|
||||
|
||||
if(fromAlias != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(fromAlias.getName());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
if(getToID() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getToID());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
Alias toAlias = getToIDAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(toAlias.getName());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",'");
|
||||
sb.append(getChannel());
|
||||
sb.append("','");
|
||||
sb.append(getFrequency());
|
||||
sb.append("',");
|
||||
if(getDetails() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getDetails());
|
||||
sb.append("'");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public enum CallEventType
|
||||
{
|
||||
ANNOUNCEMENT("Announcement"),
|
||||
CALL("Call"),
|
||||
CALL_ALERT("Call Alert"),
|
||||
CALL_DETECT("Call Detect"),
|
||||
CALL_DO_NOT_MONITOR("Call-Do Not Monitor"),
|
||||
CALL_END("Call End"),
|
||||
CALL_UNIQUE_ID("UID Call"),
|
||||
CALL_NO_TUNER("Call - No Tuner"),
|
||||
CALL_TIMEOUT("Call Timeout"),
|
||||
COMMAND("Command"),
|
||||
DATA_CALL("Data Call"),
|
||||
DEREGISTER("Deregister"),
|
||||
EMERGENCY("EMERGENCY"),
|
||||
ENCRYPTED_CALL("Encrypted Call"),
|
||||
FUNCTION("Function"),
|
||||
GPS("GPS"),
|
||||
GROUP_CALL("Group Call"),
|
||||
ID_ANI("ANI"),
|
||||
ID_UNIQUE("Unique ID"),
|
||||
NOTIFICATION("Notification"),
|
||||
PAGE("Page"),
|
||||
PATCH_GROUP_ADD("Patch Group Add"),
|
||||
PATCH_GROUP_CALL("Patch Group Call"),
|
||||
PATCH_GROUP_DELETE("Patch Group Delete"),
|
||||
QUERY("Query"),
|
||||
REGISTER("Register"),
|
||||
REGISTER_ESN("ESN"),
|
||||
RESPONSE("Response"),
|
||||
SDM("Short Data Message"),
|
||||
STATION_ID("Station ID"),
|
||||
STATUS("Status"),
|
||||
TELEPHONE_INTERCONNECT("Telephone Interconnect"),
|
||||
UNIT_TO_UNIT_CALL("Unit To Unit Call"),
|
||||
UNKNOWN("Unknown"),
|
||||
INVALID("Invalid");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private CallEventType(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CallEvent other)
|
||||
{
|
||||
if(other != null && other == this)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Long.compare(mEventStart, other.getEventStartTime());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,25 @@
|
||||
/*******************************************************************************
|
||||
* 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-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 module.decode.event;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import message.Message;
|
||||
import module.ProcessingChain;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jidesoft.swing.JideButton;
|
||||
import com.jidesoft.swing.JideSplitButton;
|
||||
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
@@ -52,278 +27,297 @@ import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import filter.FilterEditorPanel;
|
||||
import filter.FilterSet;
|
||||
import message.Message;
|
||||
import module.ProcessingChain;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( MessageActivityPanel.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MessageActivityPanel.class);
|
||||
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
|
||||
private JTable mMessageTable;
|
||||
|
||||
|
||||
private Channel mDisplayedChannel;
|
||||
private MessageActivityModel mDisplayedModel = EMPTY_MODEL;
|
||||
|
||||
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
public MessageActivityPanel( ChannelProcessingManager channelProcessingManager )
|
||||
{
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
|
||||
setLayout( new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]") );
|
||||
|
||||
add( mManagementPanel, "span,growx" );
|
||||
|
||||
mMessageTable = new JTable( mDisplayedModel );
|
||||
|
||||
add( new JScrollPane( mMessageTable ), "span,grow" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelChanged( ChannelEvent event )
|
||||
public MessageActivityPanel(ChannelProcessingManager channelProcessingManager)
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
if( event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel().isSelected() )
|
||||
{
|
||||
if( mDisplayedChannel == null ||
|
||||
( mDisplayedChannel != null &&
|
||||
mDisplayedChannel != event.getChannel() ) )
|
||||
{
|
||||
mDisplayedChannel = event.getChannel();
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
|
||||
ProcessingChain chain = mChannelProcessingManager
|
||||
.getProcessingChain( mDisplayedChannel );
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]"));
|
||||
|
||||
if( chain != null )
|
||||
{
|
||||
mDisplayedModel = chain.getMessageActivityModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDisplayedModel = EMPTY_MODEL;
|
||||
}
|
||||
add(mManagementPanel, "span,growx");
|
||||
|
||||
mMessageTable.setModel( mDisplayedModel );
|
||||
mMessageTable = new JTable(mDisplayedModel);
|
||||
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
mManagementPanel.enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
mManagementPanel.disable();
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if( event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP ||
|
||||
event.getEvent() == Event.REQUEST_DISABLE )
|
||||
{
|
||||
if( mDisplayedChannel != null &&
|
||||
mDisplayedChannel == event.getChannel() )
|
||||
{
|
||||
mDisplayedChannel = null;
|
||||
|
||||
mMessageTable.setModel( EMPTY_MODEL );
|
||||
|
||||
mManagementPanel.disable();
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( changed )
|
||||
{
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
add(new JScrollPane(mMessageTable), "span,grow");
|
||||
}
|
||||
|
||||
public class MessageManagementPanel extends JPanel
|
||||
{
|
||||
|
||||
@Override
|
||||
public void channelChanged(ChannelEvent event)
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel().isSelected())
|
||||
{
|
||||
if(mDisplayedChannel == null || (mDisplayedChannel != null && mDisplayedChannel != event.getChannel()))
|
||||
{
|
||||
mDisplayedChannel = event.getChannel();
|
||||
|
||||
ProcessingChain chain = mChannelProcessingManager.getProcessingChain(mDisplayedChannel);
|
||||
|
||||
if(chain != null)
|
||||
{
|
||||
mDisplayedModel = chain.getMessageActivityModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDisplayedModel = EMPTY_MODEL;
|
||||
}
|
||||
|
||||
mMessageTable.setModel(mDisplayedModel);
|
||||
|
||||
if(mDisplayedChannel != null)
|
||||
{
|
||||
mManagementPanel.enableButtons();
|
||||
}
|
||||
else
|
||||
{
|
||||
mManagementPanel.disableButtons();
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if(event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP || event.getEvent() == Event.REQUEST_DISABLE)
|
||||
{
|
||||
if(mDisplayedChannel != null && mDisplayedChannel == event.getChannel())
|
||||
{
|
||||
mDisplayedChannel = null;
|
||||
|
||||
mMessageTable.setModel(EMPTY_MODEL);
|
||||
|
||||
mManagementPanel.disableButtons();
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(changed)
|
||||
{
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageManagementPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MessageHistoryButton mHistoryButton = new MessageHistoryButton();
|
||||
private MessageFilterButton mFilterButton = new MessageFilterButton();
|
||||
|
||||
|
||||
public MessageManagementPanel()
|
||||
{
|
||||
setLayout( new MigLayout("insets 2 2 5 5", "[]5[left,grow]", "") );
|
||||
setLayout(new MigLayout("insets 2 2 5 5", "[]5[left,grow]", ""));
|
||||
|
||||
disable();
|
||||
|
||||
add( mFilterButton );
|
||||
add( mHistoryButton );
|
||||
disableButtons();
|
||||
|
||||
add(mFilterButton);
|
||||
add(mHistoryButton);
|
||||
}
|
||||
|
||||
public void enable()
|
||||
|
||||
public void enableButtons()
|
||||
{
|
||||
mHistoryButton.setEnabled( true );
|
||||
mFilterButton.setEnabled( true );
|
||||
mHistoryButton.setEnabled(true);
|
||||
mFilterButton.setEnabled(true);
|
||||
}
|
||||
|
||||
public void disable()
|
||||
|
||||
public void disableButtons()
|
||||
{
|
||||
mHistoryButton.setEnabled( false );
|
||||
mFilterButton.setEnabled( false );
|
||||
mHistoryButton.setEnabled(false);
|
||||
mFilterButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageHistoryButton extends JideSplitButton
|
||||
{
|
||||
}
|
||||
|
||||
public class MessageHistoryButton extends JideSplitButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
public MessageHistoryButton()
|
||||
{
|
||||
super( "Clear" );
|
||||
|
||||
JPanel historyPanel = new JPanel();
|
||||
|
||||
historyPanel.add( new JLabel( "Message History:" ) );
|
||||
|
||||
final JSlider slider = new JSlider();
|
||||
slider.setMinimum( 0 );
|
||||
slider.setMaximum( 2000 );
|
||||
slider.setMajorTickSpacing( 500 );
|
||||
slider.setPaintTicks( true );
|
||||
slider.setPaintLabels( true );
|
||||
|
||||
slider.addMouseListener( new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent arg0 )
|
||||
super("Clear");
|
||||
|
||||
JPanel historyPanel = new JPanel();
|
||||
|
||||
historyPanel.add(new JLabel("Message History:"));
|
||||
|
||||
final JSlider slider = new JSlider();
|
||||
slider.setMinimum(0);
|
||||
slider.setMaximum(2000);
|
||||
slider.setMajorTickSpacing(500);
|
||||
slider.setPaintTicks(true);
|
||||
slider.setPaintLabels(true);
|
||||
|
||||
slider.addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent arg0)
|
||||
{
|
||||
if( SwingUtilities.isLeftMouseButton( arg0 ) &&
|
||||
arg0.getClickCount() == 2 )
|
||||
{
|
||||
slider.setValue( 500 ); //default
|
||||
}
|
||||
if(SwingUtilities.isLeftMouseButton(arg0) &&
|
||||
arg0.getClickCount() == 2)
|
||||
{
|
||||
slider.setValue(500); //default
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseEntered( MouseEvent arg0 ) {}
|
||||
public void mouseExited( MouseEvent arg0 ) {}
|
||||
public void mousePressed( MouseEvent arg0 ) {}
|
||||
public void mouseReleased( MouseEvent arg0 ) {}
|
||||
} );
|
||||
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
slider.setValue( mDisplayedModel.getMaxMessageCount() );
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.setValue( 500 );
|
||||
}
|
||||
|
||||
slider.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent arg0 )
|
||||
public void mouseEntered(MouseEvent arg0)
|
||||
{
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
mDisplayedModel.setMaxMessageCount( slider.getValue() );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
historyPanel.add( slider );
|
||||
|
||||
add( historyPanel );
|
||||
public void mouseExited(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
if(mDisplayedModel != null)
|
||||
{
|
||||
slider.setValue(mDisplayedModel.getMaxMessageCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.setValue(500);
|
||||
}
|
||||
|
||||
slider.addChangeListener(new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent arg0)
|
||||
{
|
||||
if(mDisplayedModel != null)
|
||||
{
|
||||
mDisplayedModel.setMaxMessageCount(slider.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
historyPanel.add(slider);
|
||||
|
||||
add(historyPanel);
|
||||
|
||||
/* Clear messages */
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
mDisplayedModel.clear();
|
||||
}
|
||||
}
|
||||
} );
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
if(mDisplayedModel != null)
|
||||
{
|
||||
mDisplayedModel.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageFilterButton extends JideButton
|
||||
{
|
||||
public class MessageFilterButton extends JideButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
public MessageFilterButton()
|
||||
{
|
||||
super( "Filter" );
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
if( mDisplayedChannel == null )
|
||||
{
|
||||
JOptionPane.showMessageDialog( MessageFilterButton.this,
|
||||
"Please enable and select a decoding channel to "
|
||||
+ "adjust the channel's message display filter" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
editor.setTitle( "Message Filter Editor" );
|
||||
editor.setSize( 600, 400 );
|
||||
editor.setLocationRelativeTo( MessageFilterButton.this );
|
||||
editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
editor.setLayout( new MigLayout( "", "[grow,fill]",
|
||||
"[grow,fill][][]" ) );
|
||||
super("Filter");
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
FilterSet<Message> filter = (FilterSet<Message>)
|
||||
mDisplayedModel.getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel =
|
||||
new FilterEditorPanel<Message>( filter );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( panel );
|
||||
scroller.setViewportView( panel );
|
||||
|
||||
editor.add( scroller, "wrap" );
|
||||
|
||||
editor.add( new JLabel( "Right-click to select/deselect "
|
||||
+ "all nodes" ), "wrap" );
|
||||
|
||||
JButton close = new JButton( "Close" );
|
||||
close.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
} );
|
||||
|
||||
editor.add( close );
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
if(mDisplayedChannel == null)
|
||||
{
|
||||
JOptionPane.showMessageDialog(MessageFilterButton.this,
|
||||
"Please enable and select a decoding channel to "
|
||||
+ "adjust the channel's message display filter");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mDisplayedModel != null)
|
||||
{
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
editor.setTitle("Message Filter Editor");
|
||||
editor.setSize(600, 400);
|
||||
editor.setLocationRelativeTo(MessageFilterButton.this);
|
||||
editor.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
editor.setLayout(new MigLayout("", "[grow,fill]",
|
||||
"[grow,fill][][]"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
FilterSet<Message> filter = (FilterSet<Message>)
|
||||
mDisplayedModel.getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel =
|
||||
new FilterEditorPanel<Message>(filter);
|
||||
|
||||
JScrollPane scroller = new JScrollPane(panel);
|
||||
scroller.setViewportView(panel);
|
||||
|
||||
editor.add(scroller, "wrap");
|
||||
|
||||
editor.add(new JLabel("Right-click to select/deselect "
|
||||
+ "all nodes"), "wrap");
|
||||
|
||||
JButton close = new JButton("Close");
|
||||
close.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
editor.add(close);
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,201 +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 module.decode.fleetsync2;
|
||||
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Fleetsync2DecoderPanel extends DecoderPanel
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(Fleetsync2DecoderPanel.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PROTOCOL = "FSync II";
|
||||
|
||||
private JLabel mToLabel = new JLabel(" ");
|
||||
private JLabel mTo = new JLabel(" ");
|
||||
private JLabel mToAlias = new JLabel(" ");
|
||||
|
||||
private JLabel mFromLabel = new JLabel(" ");
|
||||
private JLabel mFrom = new JLabel(" ");
|
||||
private JLabel mFromAlias = new JLabel(" ");
|
||||
|
||||
private JLabel mProtocol = new JLabel(PROTOCOL);
|
||||
private JLabel mMessage = new JLabel(" ");
|
||||
private JLabel mMessageType = new JLabel(" ");
|
||||
|
||||
public Fleetsync2DecoderPanel(IconManager iconManager, SettingsManager settingsManager,
|
||||
Fleetsync2DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fleetsync2DecoderState getDecoderState()
|
||||
{
|
||||
return (Fleetsync2DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
/* Calling super init will get and broadcast color settings to properly
|
||||
* setup the jlabel colors */
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 1 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mToLabel.setFont(mFontAuxDecoder);
|
||||
mToLabel.setForeground(mColorLabelAuxDecoder);
|
||||
add(mToLabel);
|
||||
|
||||
mTo.setFont(mFontAuxDecoder);
|
||||
mTo.setForeground(mColorLabelAuxDecoder);
|
||||
add(mTo);
|
||||
|
||||
mToAlias.setFont(mFontAuxDecoder);
|
||||
mToAlias.setForeground(mColorLabelAuxDecoder);
|
||||
add(mToAlias, "wrap");
|
||||
|
||||
mFromLabel.setFont(mFontAuxDecoder);
|
||||
mFromLabel.setForeground(mColorLabelAuxDecoder);
|
||||
add(mFromLabel);
|
||||
|
||||
mFrom.setFont(mFontAuxDecoder);
|
||||
mFrom.setForeground(mColorLabelAuxDecoder);
|
||||
add(mFrom);
|
||||
|
||||
mFromAlias.setFont(mFontAuxDecoder);
|
||||
mFromAlias.setForeground(mColorLabelAuxDecoder);
|
||||
add(mFromAlias, "wrap");
|
||||
|
||||
mProtocol.setFont(mFontAuxDecoder);
|
||||
mProtocol.setForeground(mColorLabelAuxDecoder);
|
||||
add(mProtocol);
|
||||
|
||||
mMessageType.setFont(mFontAuxDecoder);
|
||||
mMessageType.setForeground(mColorLabelAuxDecoder);
|
||||
add(mMessageType);
|
||||
|
||||
mMessage.setFont(mFontAuxDecoder);
|
||||
mMessage.setForeground(mColorLabelAuxDecoder);
|
||||
add(mMessage, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case FROM_TALKGROUP:
|
||||
String from = getDecoderState().getFromID();
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
mFromLabel.setText("FROM:");
|
||||
mFrom.setText(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromLabel.setText(" ");
|
||||
mFrom.setText(" ");
|
||||
}
|
||||
break;
|
||||
case FROM_TALKGROUP_ALIAS:
|
||||
setAliasLabel(mFromAlias, getDecoderState().getFromIDAlias());
|
||||
break;
|
||||
case MESSAGE:
|
||||
mMessage.setText(getDecoderState().getMessage());
|
||||
break;
|
||||
case MESSAGE_TYPE:
|
||||
mMessageType.setText(getDecoderState().getMessageType());
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
String to = getDecoderState().getToID();
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
mToLabel.setText("TO:");
|
||||
mTo.setText(to);
|
||||
}
|
||||
else
|
||||
{
|
||||
mToLabel.setText(" ");
|
||||
mTo.setText(" ");
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
setAliasLabel(mToAlias, getDecoderState().getToIDAlias());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting color = (ColorSetting) setting;
|
||||
|
||||
if(color.getColorSettingName() ==
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER)
|
||||
{
|
||||
mFromLabel.setForeground(color.getColor());
|
||||
mFrom.setForeground(color.getColor());
|
||||
mFromAlias.setForeground(color.getColor());
|
||||
mToLabel.setForeground(color.getColor());
|
||||
mTo.setForeground(color.getColor());
|
||||
mToAlias.setForeground(color.getColor());
|
||||
mProtocol.setForeground(color.getColor());
|
||||
mMessageType.setForeground(color.getColor());
|
||||
mMessage.setForeground(color.getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,34 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* 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 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 module.decode.fleetsync2;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
@@ -116,7 +119,6 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
State state = State.CALL;
|
||||
|
||||
setFromID(fleetsync.getFromID());
|
||||
setFromIDAlias(fleetsync.getFromIDAlias());
|
||||
mIdents.add(fleetsync.getFromID());
|
||||
|
||||
FleetsyncMessageType type = fleetsync.getMessageType();
|
||||
@@ -124,7 +126,6 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
if(type != FleetsyncMessageType.ANI)
|
||||
{
|
||||
setToID(fleetsync.getToID());
|
||||
setToIDAlias(fleetsync.getToIDAlias());
|
||||
mIdents.add(fleetsync.getToID());
|
||||
}
|
||||
|
||||
@@ -179,22 +180,19 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
return mFrom;
|
||||
}
|
||||
|
||||
public void setFromID(String from)
|
||||
{
|
||||
mFrom = from;
|
||||
|
||||
broadcast(Attribute.FROM_TALKGROUP);
|
||||
}
|
||||
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return mFromAlias;
|
||||
}
|
||||
|
||||
public void setFromIDAlias(Alias alias)
|
||||
public void setFromID(String from)
|
||||
{
|
||||
mFromAlias = alias;
|
||||
broadcast(Attribute.FROM_TALKGROUP_ALIAS);
|
||||
if(!StringUtils.isEqual(mFrom, from))
|
||||
{
|
||||
mFrom = from;
|
||||
mFromAlias = hasAliasList() ? getAliasList().getFleetsyncAlias(mFrom) : null;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
@@ -202,21 +200,19 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
return mTo;
|
||||
}
|
||||
|
||||
public void setToID(String to)
|
||||
{
|
||||
mTo = to;
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
}
|
||||
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return mToAlias;
|
||||
}
|
||||
|
||||
public void setToIDAlias(Alias alias)
|
||||
public void setToID(String to)
|
||||
{
|
||||
mToAlias = alias;
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
if(!StringUtils.isEqual(mTo, to))
|
||||
{
|
||||
mTo = to;
|
||||
mToAlias = hasAliasList() ? getAliasList().getFleetsyncAlias(mTo) : null;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
@@ -226,19 +222,25 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast(Attribute.MESSAGE);
|
||||
if(!StringUtils.isEqual(mMessage, message))
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE, mMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
return "Fleetsync " + mMessageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String type)
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast(Attribute.MESSAGE_TYPE);
|
||||
if(!StringUtils.isEqual(mMessageType, type))
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE_TYPE, getMessageType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,127 +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 module.decode.lj1200;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class LJ1200DecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PROTOCOL = "LJ-1200";
|
||||
|
||||
private JLabel mProtocol = new JLabel(PROTOCOL);
|
||||
private JLabel mTo = new JLabel();
|
||||
private JLabel mToAlias = new JLabel();
|
||||
|
||||
public LJ1200DecoderPanel(IconManager iconManager, SettingsManager settingsManager, LJ1200DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
/* Calling super init will get and broadcast color settings to properly
|
||||
* setup the jlabel colors */
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 1 0 0 0", "[grow,fill]", ""));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTo.setFont(mFontDecoder);
|
||||
mTo.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToAlias.setFont(mFontDecoder);
|
||||
mToAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol);
|
||||
add(mTo);
|
||||
add(mToAlias, "wrap");
|
||||
}
|
||||
|
||||
public LJ1200DecoderState getDecoderState()
|
||||
{
|
||||
return (LJ1200DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case TO_TALKGROUP:
|
||||
mTo.setText(getDecoderState().getAddress());
|
||||
repaint();
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias alias = getDecoderState().getAddressAlias();
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
mToAlias.setText(alias.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
mToAlias.setText("");
|
||||
}
|
||||
|
||||
repaint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting color = (ColorSetting) setting;
|
||||
|
||||
if(color.getColorSettingName() ==
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER)
|
||||
{
|
||||
mProtocol.setForeground(color.getColor());
|
||||
mTo.setForeground(color.getColor());
|
||||
mToAlias.setForeground(color.getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 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-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 module.decode.lj1200;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -24,151 +39,138 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
public class LJ1200DecoderState extends DecoderState
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( LJ1200DecoderState.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(LJ1200DecoderState.class);
|
||||
|
||||
private Set<String> mAddresses = new TreeSet<String>();
|
||||
|
||||
private String mAddress;
|
||||
private Alias mAddressAlias;
|
||||
|
||||
public LJ1200DecoderState( AliasList aliasList )
|
||||
{
|
||||
super( aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LJ_1200;
|
||||
}
|
||||
private Set<String> mAddresses = new TreeSet<String>();
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
private String mAddress;
|
||||
private Alias mAddressAlias;
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
public String getAddress()
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
public Alias getAddressAlias()
|
||||
{
|
||||
return mAddressAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
public LJ1200DecoderState(AliasList aliasList)
|
||||
{
|
||||
if( message instanceof LJ1200Message )
|
||||
{
|
||||
LJ1200Message lj = (LJ1200Message)message;
|
||||
|
||||
if( lj.isValid() )
|
||||
{
|
||||
setAddress( lj.getAddress() );
|
||||
setAddressAlias( lj.getTransponderAlias() );
|
||||
|
||||
mAddresses.add( mAddress );
|
||||
|
||||
broadcast( LJ1200CallEvent.getLJ1200Event( lj ) );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.DATA ) );
|
||||
}
|
||||
}
|
||||
else if( message instanceof LJ1200TransponderMessage )
|
||||
{
|
||||
|
||||
}
|
||||
super(aliasList);
|
||||
}
|
||||
|
||||
private void setAddress( String address )
|
||||
{
|
||||
mAddress = address;
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
}
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LJ_1200;
|
||||
}
|
||||
|
||||
private void setAddressAlias( Alias alias )
|
||||
{
|
||||
mAddressAlias = alias;
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
public String getAddress()
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
public Alias getAddressAlias()
|
||||
{
|
||||
return mAddressAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if(message instanceof LJ1200Message)
|
||||
{
|
||||
LJ1200Message lj = (LJ1200Message) message;
|
||||
|
||||
if(lj.isValid())
|
||||
{
|
||||
setAddress(lj.getAddress());
|
||||
setAddressAlias(lj.getTransponderAlias());
|
||||
|
||||
mAddresses.add(mAddress);
|
||||
|
||||
broadcast(LJ1200CallEvent.getLJ1200Event(lj));
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.DATA));
|
||||
}
|
||||
}
|
||||
else if(message instanceof LJ1200TransponderMessage)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void setAddress(String address)
|
||||
{
|
||||
if(!StringUtils.isEqual(mAddress, address))
|
||||
{
|
||||
mAddress = address;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, mAddress, mAddressAlias));
|
||||
}
|
||||
}
|
||||
|
||||
private void setAddressAlias(Alias alias)
|
||||
{
|
||||
mAddressAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, mAddress, mAddressAlias));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "=============================\n" );
|
||||
sb.append( "Decoder:\tLJ-1200I\n\n" );
|
||||
sb.append("=============================\n");
|
||||
sb.append("Decoder:\tLJ-1200I\n\n");
|
||||
|
||||
if( !mAddresses.isEmpty() )
|
||||
{
|
||||
sb.append( "Transponder Addresses:\n" );
|
||||
|
||||
List<String> addresses = new ArrayList<String>( mAddresses );
|
||||
|
||||
Collections.sort( addresses );
|
||||
|
||||
for( String address: addresses )
|
||||
{
|
||||
sb.append( "\t" );
|
||||
sb.append( address );
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
if(!mAddresses.isEmpty())
|
||||
{
|
||||
sb.append("Transponder Addresses:\n");
|
||||
|
||||
return sb.toString();
|
||||
List<String> addresses = new ArrayList<String>(mAddresses);
|
||||
|
||||
Collections.sort(addresses);
|
||||
|
||||
for(String address : addresses)
|
||||
{
|
||||
sb.append("\t");
|
||||
sb.append(address);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization steps */
|
||||
}
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization steps */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveDecoderStateEvent( DecoderStateEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.RESET )
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
setAddress( null );
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
setAddressAlias( null );
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
if(event.getEvent() == Event.RESET)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mAddresses.clear();
|
||||
resetState();
|
||||
}
|
||||
private void resetState()
|
||||
{
|
||||
mAddress = null;
|
||||
mAddressAlias = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mAddresses.clear();
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,157 +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 module.decode.ltrnet;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class LTRNetDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("LTR-Net");
|
||||
private JLabel mTalkgroup = new JLabel();
|
||||
private JLabel mTalkgroupAlias = new JLabel();
|
||||
|
||||
private JLabel mLCN = new JLabel("LCN:");
|
||||
private JLabel mDescription = new JLabel();
|
||||
|
||||
public LTRNetDecoderPanel(IconManager iconManager, SettingsManager settingsManager, LTRNetDecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTalkgroup.setFont(mFontDecoder);
|
||||
mTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTalkgroupAlias.setFont(mFontDecoder);
|
||||
mTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mLCN.setFont(mFontDecoder);
|
||||
mLCN.setForeground(mColorLabelDecoder);
|
||||
|
||||
mDescription.setFont(mFontDecoder);
|
||||
mDescription.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol);
|
||||
add(mTalkgroup);
|
||||
add(mTalkgroupAlias, "wrap");
|
||||
|
||||
add(mLCN);
|
||||
add(mDescription, "span");
|
||||
}
|
||||
|
||||
public LTRNetDecoderState getDecoderState()
|
||||
{
|
||||
return (LTRNetDecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
LTRNetDecoderState state = getDecoderState();
|
||||
|
||||
switch(attribute)
|
||||
{
|
||||
case TO_TALKGROUP:
|
||||
mTalkgroup.setText(state.getToTalkgroup());
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias tgAlias = state.getToTalkgroupAlias();
|
||||
setAliasLabel(mTalkgroupAlias, tgAlias);
|
||||
break;
|
||||
case DESCRIPTION:
|
||||
mDescription.setText(state.getDescription());
|
||||
break;
|
||||
case CHANNEL_NUMBER:
|
||||
mLCN.setText("LCN: " + state.getChannelNumber());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mTalkgroup != null)
|
||||
{
|
||||
mTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mTalkgroupAlias != null)
|
||||
{
|
||||
mTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mLCN != null)
|
||||
{
|
||||
mLCN.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mDescription != null)
|
||||
{
|
||||
mDescription.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,30 +17,28 @@
|
||||
******************************************************************************/
|
||||
package module.decode.ltrnet;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
|
||||
public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(LTRNetDecoderState.class);
|
||||
@@ -53,15 +51,18 @@ public class LTRNetDecoderState extends DecoderState
|
||||
private TreeSet<Integer> mUniqueIDs = new TreeSet<Integer>();
|
||||
private TreeSet<String> mNeighborIDs = new TreeSet<String>();
|
||||
private TreeSet<String> mSiteIDs = new TreeSet<String>();
|
||||
private HashMap<Integer, Long> mReceiveFrequencies =
|
||||
new HashMap<Integer, Long>();
|
||||
private HashMap<Integer, Long> mTransmitFrequencies =
|
||||
new HashMap<Integer, Long>();
|
||||
private HashMap<Integer, String> mActiveCalls = new HashMap<Integer, String>();
|
||||
private HashMap<Integer,Long> mReceiveFrequencies =
|
||||
new HashMap<Integer,Long>();
|
||||
private HashMap<Integer,Long> mTransmitFrequencies =
|
||||
new HashMap<Integer,Long>();
|
||||
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
|
||||
|
||||
private String mTalkgroup;
|
||||
private Alias mTalkgroupAlias;
|
||||
private String mDescription;
|
||||
private String mToTalkgroup;
|
||||
private Alias mToTalkgroupAlias;
|
||||
private String mFromTalkgroup;
|
||||
private Alias mFromTalkgroupAlias;
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
private int mChannelNumber;
|
||||
private long mFrequency = 0;
|
||||
|
||||
@@ -79,47 +80,44 @@ public class LTRNetDecoderState extends DecoderState
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if (message.isValid())
|
||||
if(message.isValid())
|
||||
{
|
||||
State state = State.IDLE;
|
||||
|
||||
if (message instanceof LTRNetOSWMessage)
|
||||
if(message instanceof LTRNetOSWMessage)
|
||||
{
|
||||
LTRNetOSWMessage ltr = (LTRNetOSWMessage) message;
|
||||
|
||||
switch (ltr.getMessageType())
|
||||
switch(ltr.getMessageType())
|
||||
{
|
||||
case CA_ENDD:
|
||||
if (mChannelNumber == 0)
|
||||
if(mChannelNumber == 0)
|
||||
{
|
||||
mChannelNumber = ltr.getChannel();
|
||||
broadcast(Attribute.CHANNEL_NUMBER);
|
||||
setChannelNumber(ltr.getChannel());
|
||||
}
|
||||
|
||||
/* Process FCC Station ID Events */
|
||||
if (ltr.getGroup() == 254)
|
||||
if(ltr.getGroup() == 254)
|
||||
{
|
||||
if (mCurrentCallEvent == null ||
|
||||
mCurrentCallEvent.getCallEventType() !=
|
||||
CallEventType.STATION_ID)
|
||||
if(mCurrentCallEvent == null ||
|
||||
mCurrentCallEvent.getCallEventType() !=
|
||||
CallEventType.STATION_ID)
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_NET, CallEventType.STATION_ID)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.to(ltr.getTalkgroupID())
|
||||
.build();
|
||||
DecoderType.LTR_NET, CallEventType.STATION_ID)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.to(ltr.getTalkgroupID())
|
||||
.build();
|
||||
|
||||
broadcast(mCurrentCallEvent);
|
||||
|
||||
broadcast(new DecoderStateEvent(this,
|
||||
Event.START, State.DATA));
|
||||
broadcast(new DecoderStateEvent(this, Event.START, State.DATA));
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this,
|
||||
Event.CONTINUATION, State.DATA));
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.DATA));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -128,15 +126,14 @@ public class LTRNetDecoderState extends DecoderState
|
||||
}
|
||||
break;
|
||||
case CA_STRT:
|
||||
if (mChannelNumber == 0)
|
||||
if(mChannelNumber == 0)
|
||||
{
|
||||
mChannelNumber = ltr.getChannel();
|
||||
broadcast(Attribute.CHANNEL_NUMBER);
|
||||
setChannelNumber(ltr.getChannel());
|
||||
}
|
||||
|
||||
/* If the call event channel matches our current channel
|
||||
* then it's a call, otherwise it's a call detect. */
|
||||
if (ltr.getChannel() == mChannelNumber)
|
||||
if(ltr.getChannel() == mChannelNumber)
|
||||
{
|
||||
processCallMessage(ltr);
|
||||
}
|
||||
@@ -147,10 +144,9 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
break;
|
||||
case SY_IDLE:
|
||||
if (mChannelNumber != ltr.getChannel())
|
||||
if(mChannelNumber != ltr.getChannel())
|
||||
{
|
||||
mChannelNumber = ltr.getChannel();
|
||||
broadcast(Attribute.CHANNEL_NUMBER);
|
||||
setChannelNumber(ltr.getChannel());
|
||||
}
|
||||
break;
|
||||
case MA_CHNH:
|
||||
@@ -159,24 +155,22 @@ public class LTRNetDecoderState extends DecoderState
|
||||
break;
|
||||
case FQ_RXHI:
|
||||
case FQ_RXLO:
|
||||
if (ltr.getFrequency() > 0)
|
||||
if(ltr.getFrequency() > 0)
|
||||
{
|
||||
mReceiveFrequencies.put(ltr.getHomeRepeater(),
|
||||
ltr.getFrequency());
|
||||
mReceiveFrequencies.put(ltr.getHomeRepeater(), ltr.getFrequency());
|
||||
}
|
||||
break;
|
||||
case FQ_TXHI:
|
||||
case FQ_TXLO:
|
||||
if (ltr.getFrequency() > 0)
|
||||
if(ltr.getFrequency() > 0)
|
||||
{
|
||||
mTransmitFrequencies.put(ltr.getHomeRepeater(),
|
||||
ltr.getFrequency());
|
||||
mTransmitFrequencies.put(ltr.getHomeRepeater(), ltr.getFrequency());
|
||||
}
|
||||
break;
|
||||
case ID_NBOR:
|
||||
String neighborID = ltr.getNeighborID();
|
||||
|
||||
if (neighborID != null)
|
||||
if(neighborID != null)
|
||||
{
|
||||
mNeighborIDs.add(neighborID);
|
||||
}
|
||||
@@ -186,40 +180,37 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
int uniqueID = ltr.getRadioUniqueID();
|
||||
|
||||
if (uniqueID != LTRNetOSWMessage.INT_NULL_VALUE)
|
||||
if(uniqueID != LTRNetOSWMessage.INT_NULL_VALUE)
|
||||
{
|
||||
mUniqueIDs.add(uniqueID);
|
||||
}
|
||||
|
||||
if (getCurrentLTRCallEvent() == null)
|
||||
if(getCurrentLTRCallEvent() == null)
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.from(String.valueOf(uniqueID))
|
||||
.build();
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.from(String.valueOf(uniqueID))
|
||||
.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentCallEvent.setFromID(
|
||||
String.valueOf(ltr.getRadioUniqueID()));
|
||||
String.valueOf(ltr.getRadioUniqueID()));
|
||||
mCurrentCallEvent.setDetails("Unique ID");
|
||||
|
||||
broadcast(mCurrentCallEvent);
|
||||
}
|
||||
|
||||
mTalkgroup = String.valueOf(uniqueID);
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
setFromTalkgroup(String.valueOf(uniqueID));
|
||||
setFromTalkgroupAlias(ltr.getRadioUniqueIDAlias());
|
||||
break;
|
||||
case ID_SITE:
|
||||
String siteID = ltr.getSiteID();
|
||||
|
||||
if (siteID != null)
|
||||
if(siteID != null)
|
||||
{
|
||||
mSiteIDs.add(siteID);
|
||||
}
|
||||
@@ -228,11 +219,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (message instanceof LTRNetISWMessage)
|
||||
else if(message instanceof LTRNetISWMessage)
|
||||
{
|
||||
LTRNetISWMessage ltr = ((LTRNetISWMessage) message);
|
||||
|
||||
switch (ltr.getMessageType())
|
||||
switch(ltr.getMessageType())
|
||||
{
|
||||
case CA_STRT:
|
||||
processCallMessage(ltr);
|
||||
@@ -246,31 +237,26 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
String esn = ltr.getESN();
|
||||
|
||||
if (!esn.contains("xxxx"))
|
||||
if(!esn.contains("xxxx"))
|
||||
{
|
||||
mESNs.add(ltr.getESN());
|
||||
}
|
||||
|
||||
mDescription = "ESN";
|
||||
broadcast(Attribute.DESCRIPTION);
|
||||
|
||||
mTalkgroup = ltr.getESN();
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
mTalkgroupAlias = ltr.getESNAlias();
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
setMessageType("ESN");
|
||||
setFromTalkgroup(ltr.getESN());
|
||||
setFromTalkgroupAlias(ltr.getESNAlias());
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.DATA));
|
||||
|
||||
if (mCurrentCallEvent == null)
|
||||
if(mCurrentCallEvent == null)
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER_ESN)
|
||||
.aliasList(getAliasList())
|
||||
.details("ESN:" + ltr.getESN())
|
||||
.frequency(mFrequency)
|
||||
.from(ltr.getESN())
|
||||
.build();
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER_ESN)
|
||||
.aliasList(getAliasList())
|
||||
.details("ESN:" + ltr.getESN())
|
||||
.frequency(mFrequency)
|
||||
.from(ltr.getESN())
|
||||
.build();
|
||||
|
||||
broadcast(mCurrentCallEvent);
|
||||
}
|
||||
@@ -281,33 +267,28 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
int uniqueid = ltr.getRadioUniqueID();
|
||||
|
||||
if (uniqueid != LTRNetISWMessage.INT_NULL_VALUE)
|
||||
if(uniqueid != LTRNetISWMessage.INT_NULL_VALUE)
|
||||
{
|
||||
mUniqueIDs.add(uniqueid);
|
||||
|
||||
mDescription = "REGISTER UID";
|
||||
broadcast(Attribute.DESCRIPTION);
|
||||
setMessageType("REGISTER UID");
|
||||
setToTalkgroup(String.valueOf(uniqueid));
|
||||
setToTalkgroupAlias(ltr.getRadioUniqueIDAlias());
|
||||
|
||||
mTalkgroup = String.valueOf(uniqueid);
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
|
||||
if (getCurrentLTRCallEvent() == null)
|
||||
if(getCurrentLTRCallEvent() == null)
|
||||
{
|
||||
mCurrentCallEvent = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.from(String.valueOf(uniqueid))
|
||||
.build();
|
||||
DecoderType.LTR_NET, CallEventType.REGISTER)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(mChannelNumber))
|
||||
.frequency(mFrequency)
|
||||
.from(String.valueOf(uniqueid))
|
||||
.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentCallEvent.setFromID(
|
||||
String.valueOf(ltr.getRadioUniqueID()));
|
||||
String.valueOf(ltr.getRadioUniqueID()));
|
||||
mCurrentCallEvent.setDetails("Unique ID");
|
||||
|
||||
broadcast(mCurrentCallEvent);
|
||||
@@ -323,7 +304,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
public LTRCallEvent getCurrentLTRCallEvent()
|
||||
{
|
||||
if (mCurrentCallEvent != null)
|
||||
if(mCurrentCallEvent != null)
|
||||
{
|
||||
return (LTRCallEvent) mCurrentCallEvent;
|
||||
}
|
||||
@@ -339,7 +320,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append("Activity Summary\n");
|
||||
sb.append("Decoder:\tLTR-Net\n\n");
|
||||
|
||||
if (mSiteIDs.isEmpty())
|
||||
if(mSiteIDs.isEmpty())
|
||||
{
|
||||
sb.append("Site:\tUnknown\n");
|
||||
}
|
||||
@@ -347,7 +328,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
Iterator<String> it = mSiteIDs.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
while(it.hasNext())
|
||||
{
|
||||
sb.append("Site:\t");
|
||||
|
||||
@@ -355,11 +336,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append(siteID);
|
||||
|
||||
if (hasAliasList())
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias siteAlias = getAliasList().getSiteID(String.valueOf(siteID));
|
||||
|
||||
if (siteAlias != null)
|
||||
if(siteAlias != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(siteAlias.getName());
|
||||
@@ -372,31 +353,31 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append("\nLCNs (transmit | receive)\n");
|
||||
|
||||
if (mReceiveFrequencies.isEmpty() && mTransmitFrequencies.isEmpty())
|
||||
if(mReceiveFrequencies.isEmpty() && mTransmitFrequencies.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int x = 1; x < 21; x++)
|
||||
for(int x = 1; x < 21; x++)
|
||||
{
|
||||
long rcv = 0;
|
||||
|
||||
if (mReceiveFrequencies.containsKey(x))
|
||||
if(mReceiveFrequencies.containsKey(x))
|
||||
{
|
||||
rcv = mReceiveFrequencies.get(x);
|
||||
}
|
||||
|
||||
long xmt = 0;
|
||||
|
||||
if (mTransmitFrequencies.containsKey(x))
|
||||
if(mTransmitFrequencies.containsKey(x))
|
||||
{
|
||||
xmt = mTransmitFrequencies.get(x);
|
||||
}
|
||||
|
||||
if (rcv > 0 || xmt > 0)
|
||||
if(rcv > 0 || xmt > 0)
|
||||
{
|
||||
if (x < 10)
|
||||
if(x < 10)
|
||||
{
|
||||
sb.append(" ");
|
||||
}
|
||||
@@ -404,7 +385,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(x);
|
||||
sb.append(": ");
|
||||
|
||||
if (xmt == 0)
|
||||
if(xmt == 0)
|
||||
{
|
||||
sb.append("---.-----");
|
||||
}
|
||||
@@ -414,7 +395,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
}
|
||||
sb.append(" | ");
|
||||
|
||||
if (rcv == 0)
|
||||
if(rcv == 0)
|
||||
{
|
||||
sb.append("---.-----");
|
||||
}
|
||||
@@ -423,7 +404,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(mDecimalFormatter.format((double) rcv / 1E6d));
|
||||
}
|
||||
|
||||
if (x == mChannelNumber)
|
||||
if(x == mChannelNumber)
|
||||
{
|
||||
sb.append(" **");
|
||||
}
|
||||
@@ -435,7 +416,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append("\nTalkgroups\n");
|
||||
|
||||
if (mTalkgroups.isEmpty())
|
||||
if(mTalkgroups.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
@@ -443,7 +424,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
Iterator<String> it = mTalkgroups.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
while(it.hasNext())
|
||||
{
|
||||
String tgid = it.next();
|
||||
|
||||
@@ -451,11 +432,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(tgid);
|
||||
sb.append(" ");
|
||||
|
||||
if (hasAliasList())
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias(tgid);
|
||||
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
@@ -467,7 +448,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append("\nRadio Unique IDs\n");
|
||||
|
||||
if (mUniqueIDs.isEmpty())
|
||||
if(mUniqueIDs.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
@@ -475,7 +456,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
Iterator<Integer> it = mUniqueIDs.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
while(it.hasNext())
|
||||
{
|
||||
int uid = it.next();
|
||||
|
||||
@@ -483,11 +464,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(uid);
|
||||
sb.append(" ");
|
||||
|
||||
if (hasAliasList())
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getUniqueID(uid);
|
||||
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
@@ -499,7 +480,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append("\nESNs\n");
|
||||
|
||||
if (mESNs.isEmpty())
|
||||
if(mESNs.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
@@ -507,7 +488,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
Iterator<String> it = mESNs.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
while(it.hasNext())
|
||||
{
|
||||
String esn = it.next();
|
||||
|
||||
@@ -515,11 +496,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(esn);
|
||||
sb.append(" ");
|
||||
|
||||
if (hasAliasList())
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getESNAlias(esn);
|
||||
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
@@ -531,7 +512,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
sb.append("\nNeighbor Sites\n");
|
||||
|
||||
if (mNeighborIDs.isEmpty())
|
||||
if(mNeighborIDs.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
@@ -539,7 +520,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
{
|
||||
Iterator<String> it = mNeighborIDs.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
while(it.hasNext())
|
||||
{
|
||||
String neighbor = it.next();
|
||||
|
||||
@@ -547,11 +528,11 @@ public class LTRNetDecoderState extends DecoderState
|
||||
sb.append(neighbor);
|
||||
sb.append(" ");
|
||||
|
||||
if (hasAliasList())
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getSiteID(String.valueOf(neighbor));
|
||||
|
||||
if (alias != null)
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
@@ -569,8 +550,8 @@ public class LTRNetDecoderState extends DecoderState
|
||||
*/
|
||||
private void processCallDetectMessage(LTRNetMessage message)
|
||||
{
|
||||
if (!mActiveCalls.containsKey(message.getChannel()) ||
|
||||
!mActiveCalls.get(message.getChannel()).contentEquals(message.getTalkgroupID()))
|
||||
if(!mActiveCalls.containsKey(message.getChannel()) ||
|
||||
!mActiveCalls.get(message.getChannel()).contentEquals(message.getTalkgroupID()))
|
||||
{
|
||||
mActiveCalls.put(message.getChannel(), message.getTalkgroupID());
|
||||
|
||||
@@ -578,17 +559,17 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
long frequency = 0;
|
||||
|
||||
if (mTransmitFrequencies.containsKey(channel))
|
||||
if(mTransmitFrequencies.containsKey(channel))
|
||||
{
|
||||
frequency = mTransmitFrequencies.get(channel);
|
||||
}
|
||||
|
||||
broadcast(new LTRCallEvent.Builder(DecoderType.LTR_NET, CallEventType.CALL_DETECT)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(message.getChannel()))
|
||||
.frequency(frequency)
|
||||
.to(message.getTalkgroupID())
|
||||
.build());
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(message.getChannel()))
|
||||
.frequency(frequency)
|
||||
.to(message.getTalkgroupID())
|
||||
.build());
|
||||
}
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.IDLE));
|
||||
@@ -601,9 +582,9 @@ public class LTRNetDecoderState extends DecoderState
|
||||
private boolean isDifferentTalkgroup(String talkgroup)
|
||||
{
|
||||
return talkgroup != null &&
|
||||
mCurrentCallEvent != null &&
|
||||
mCurrentCallEvent.getToID() != null &&
|
||||
!mCurrentCallEvent.getToID().contentEquals(talkgroup);
|
||||
mCurrentCallEvent != null &&
|
||||
mCurrentCallEvent.getToID() != null &&
|
||||
!mCurrentCallEvent.getToID().contentEquals(talkgroup);
|
||||
}
|
||||
|
||||
private boolean isValidTalkgroup(String talkgroup)
|
||||
@@ -616,63 +597,58 @@ public class LTRNetDecoderState extends DecoderState
|
||||
int group = message.getGroup();
|
||||
|
||||
/* Process call registration */
|
||||
if (group == 253)
|
||||
if(group == 253)
|
||||
{
|
||||
setMessageType("REGISTER");
|
||||
broadcast(new DecoderStateEvent(this, Event.START, State.DATA));
|
||||
mDescription = "REGISTER";
|
||||
broadcast(Attribute.DESCRIPTION);
|
||||
}
|
||||
/* Process call */
|
||||
else
|
||||
{
|
||||
String talkgroup = message.getTalkgroupID();
|
||||
|
||||
if (isValidTalkgroup(talkgroup))
|
||||
if(isValidTalkgroup(talkgroup))
|
||||
{
|
||||
final LTRCallEvent current = getCurrentLTRCallEvent();
|
||||
|
||||
/* If this is a new call or the talkgroup is different from the current
|
||||
* call, create a new call event */
|
||||
if (current == null || isDifferentTalkgroup(talkgroup))
|
||||
* call, create a new call event */
|
||||
if(current == null || isDifferentTalkgroup(talkgroup))
|
||||
{
|
||||
/* Invalidate the current call */
|
||||
if (current != null)
|
||||
/* Invalidate the current call */
|
||||
if(current != null)
|
||||
{
|
||||
current.setValid(false);
|
||||
broadcast(current);
|
||||
}
|
||||
|
||||
mTalkgroup = message.getTalkgroupID();
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
setToTalkgroup(message.getTalkgroupID());
|
||||
|
||||
/* A talkgroup must be seen at least once before it will be added
|
||||
* to the mTalkgroups list that is used in the activity summary,
|
||||
* so that we don't pollute the summary with one-off error talkgroups */
|
||||
if (mTalkgroupsFirstHeard.contains(mTalkgroup))
|
||||
/* A talkgroup must be seen at least once before it will be added
|
||||
* to the mTalkgroups list that is used in the activity summary,
|
||||
* so that we don't pollute the summary with one-off error talkgroups */
|
||||
if(mTalkgroupsFirstHeard.contains(mToTalkgroup))
|
||||
{
|
||||
mTalkgroups.add(mTalkgroup);
|
||||
mTalkgroups.add(mToTalkgroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupsFirstHeard.add(mTalkgroup);
|
||||
mTalkgroupsFirstHeard.add(mToTalkgroup);
|
||||
}
|
||||
|
||||
mTalkgroupAlias = message.getTalkgroupIDAlias();
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
setToTalkgroupAlias(message.getTalkgroupIDAlias());
|
||||
|
||||
CallEvent callEvent = new LTRCallEvent.Builder(DecoderType.LTR_NET, CallEventType.CALL)
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(message.getChannel()))
|
||||
.frequency(mFrequency)
|
||||
.to(message.getTalkgroupID())
|
||||
.build();
|
||||
.aliasList(getAliasList())
|
||||
.channel(String.valueOf(message.getChannel()))
|
||||
.frequency(mFrequency)
|
||||
.to(message.getTalkgroupID())
|
||||
.build();
|
||||
|
||||
broadcast(callEvent);
|
||||
|
||||
mCurrentCallEvent = callEvent;
|
||||
|
||||
broadcast(new Metadata(MetadataType.TO, mTalkgroup, mTalkgroupAlias, true));
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.START, State.CALL));
|
||||
}
|
||||
|
||||
@@ -683,8 +659,8 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
private void processCallEndMessage(LTRNetMessage message)
|
||||
{
|
||||
if (mCurrentCallEvent != null &&
|
||||
mCurrentCallEvent.getCallEventType() == CallEventType.CALL)
|
||||
if(mCurrentCallEvent != null &&
|
||||
mCurrentCallEvent.getCallEventType() == CallEventType.CALL)
|
||||
{
|
||||
mCurrentCallEvent.setEnd(System.currentTimeMillis());
|
||||
broadcast(mCurrentCallEvent);
|
||||
@@ -719,8 +695,8 @@ public class LTRNetDecoderState extends DecoderState
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
if (mCurrentCallEvent != null && mCurrentCallEvent
|
||||
.getCallEventType() == CallEventType.CALL)
|
||||
if(mCurrentCallEvent != null && mCurrentCallEvent
|
||||
.getCallEventType() == CallEventType.CALL)
|
||||
{
|
||||
mCurrentCallEvent.end();
|
||||
broadcast(mCurrentCallEvent);
|
||||
@@ -728,29 +704,97 @@ public class LTRNetDecoderState extends DecoderState
|
||||
|
||||
mCurrentCallEvent = null;
|
||||
|
||||
mTalkgroup = null;
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
mToTalkgroup = null;
|
||||
|
||||
mTalkgroupAlias = null;
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
mToTalkgroupAlias = null;
|
||||
|
||||
mDescription = null;
|
||||
broadcast(Attribute.DESCRIPTION);
|
||||
mMessageType = null;
|
||||
}
|
||||
|
||||
public String getToTalkgroup()
|
||||
{
|
||||
return mTalkgroup;
|
||||
return mToTalkgroup;
|
||||
}
|
||||
|
||||
public void setToTalkgroup(String toTalkgroup)
|
||||
{
|
||||
if(!StringUtils.isEqual(mToTalkgroup, toTalkgroup))
|
||||
{
|
||||
mToTalkgroup = toTalkgroup;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getToTalkgroupAlias()
|
||||
{
|
||||
return mTalkgroupAlias;
|
||||
return mToTalkgroupAlias;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
public void setToTalkgroupAlias(Alias alias)
|
||||
{
|
||||
return mDescription;
|
||||
if(mToTalkgroupAlias == null || (alias != null && mToTalkgroupAlias != alias))
|
||||
{
|
||||
mToTalkgroupAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getFromTalkgroup()
|
||||
{
|
||||
return mFromTalkgroup;
|
||||
}
|
||||
|
||||
public void setFromTalkgroup(String fromTalkgroup)
|
||||
{
|
||||
if(!StringUtils.isEqual(mFromTalkgroup, fromTalkgroup))
|
||||
{
|
||||
mFromTalkgroup = fromTalkgroup;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup,
|
||||
mFromTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getFromTalkgroupAlias()
|
||||
{
|
||||
return mFromTalkgroupAlias;
|
||||
}
|
||||
|
||||
public void setFromTalkgroupAlias(Alias alias)
|
||||
{
|
||||
if(mFromTalkgroupAlias == null || (alias != null && alias != mFromTalkgroupAlias))
|
||||
{
|
||||
mFromTalkgroupAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup,
|
||||
mFromTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessage, message))
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE, mMessageType));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
|
||||
private void setMessageType(String messageType)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessageType, messageType))
|
||||
{
|
||||
mMessageType = messageType;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE_TYPE, mMessageType));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChannelNumber()
|
||||
@@ -763,6 +807,16 @@ public class LTRNetDecoderState extends DecoderState
|
||||
return mChannelNumber;
|
||||
}
|
||||
|
||||
public void setChannelNumber(int channelNumber)
|
||||
{
|
||||
if(mChannelNumber != channelNumber)
|
||||
{
|
||||
mChannelNumber = channelNumber;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.CHANNEL_FREQUENCY_LABEL,
|
||||
"LCN:" + getChannelNumber()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
@@ -772,7 +826,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
switch (event.getEvent())
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
|
||||
@@ -1,164 +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 module.decode.ltrstandard;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class LTRStandardDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("LTR Standard");
|
||||
private JLabel mTalkgroup = new JLabel();
|
||||
private JLabel mTalkgroupAlias = new JLabel();
|
||||
|
||||
private JLabel mLCN = new JLabel("LCN:");
|
||||
|
||||
public LTRStandardDecoderPanel(IconManager iconManager, SettingsManager settingsManager,
|
||||
LTRStandardDecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTalkgroup.setFont(mFontDecoder);
|
||||
mTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTalkgroupAlias.setFont(mFontDecoder);
|
||||
mTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mLCN.setFont(mFontDecoder);
|
||||
mLCN.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol);
|
||||
add(mTalkgroup);
|
||||
add(mTalkgroupAlias, "wrap");
|
||||
|
||||
add(mLCN, "wrap");
|
||||
}
|
||||
|
||||
public LTRStandardDecoderState getDecoderState()
|
||||
{
|
||||
return (LTRStandardDecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
LTRStandardDecoderState state = getDecoderState();
|
||||
|
||||
switch(attribute)
|
||||
{
|
||||
case CHANNEL_NUMBER:
|
||||
if(state.getChannelNumber() != 0)
|
||||
{
|
||||
mLCN.setText("LCN: " + state.getChannelNumber());
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
mTalkgroup.setText(state.getTalkgroup());
|
||||
/* fall-through */
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias alias = state.getTalkgroupAlias();
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
mTalkgroupAlias.setText(alias.getName());
|
||||
mTalkgroupAlias.setIcon(mIconManager.getIcon(alias.getIconName(),
|
||||
IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupAlias.setText(null);
|
||||
mTalkgroupAlias.setIcon(null);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mTalkgroup != null)
|
||||
{
|
||||
mTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mTalkgroupAlias != null)
|
||||
{
|
||||
mTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mLCN != null)
|
||||
{
|
||||
mLCN.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* 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-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 module.decode.ltrstandard;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import module.decode.ltrnet.LTRCallEvent;
|
||||
import module.decode.ltrstandard.message.CallEndMessage;
|
||||
import module.decode.ltrstandard.message.CallMessage;
|
||||
import module.decode.ltrstandard.message.IdleMessage;
|
||||
import module.decode.ltrstandard.message.LTRStandardMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -26,471 +47,466 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import module.decode.ltrnet.LTRCallEvent;
|
||||
import module.decode.ltrstandard.message.CallEndMessage;
|
||||
import module.decode.ltrstandard.message.CallMessage;
|
||||
import module.decode.ltrstandard.message.IdleMessage;
|
||||
import module.decode.ltrstandard.message.LTRStandardMessage;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
|
||||
public class LTRStandardDecoderState extends DecoderState
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( LTRStandardDecoderState.class );
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger(LTRStandardDecoderState.class);
|
||||
|
||||
private Map<Integer,LTRCallEvent> mActiveCalls = new HashMap<>();
|
||||
private Set<String> mTalkgroupsFirstHeard = new HashSet<>();
|
||||
private Set<String> mTalkgroups = new TreeSet<>();
|
||||
|
||||
private String mTalkgroup;
|
||||
private Alias mTalkgroupAlias;
|
||||
private Map<Integer,LTRCallEvent> mActiveCalls = new HashMap<>();
|
||||
private Set<String> mTalkgroupsFirstHeard = new HashSet<>();
|
||||
private Set<String> mTalkgroups = new TreeSet<>();
|
||||
|
||||
private String mTalkgroup;
|
||||
private Alias mTalkgroupAlias;
|
||||
private long mFrequency;
|
||||
private LCNTracker mLCNTracker = new LCNTracker();
|
||||
|
||||
public LTRStandardDecoderState( AliasList aliasList )
|
||||
{
|
||||
super( aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
public LTRStandardDecoderState(AliasList aliasList)
|
||||
{
|
||||
if( message.isValid() && message instanceof LTRStandardMessage )
|
||||
{
|
||||
switch( ((LTRStandardMessage)message).getMessageType() )
|
||||
{
|
||||
case CA_STRT:
|
||||
CallMessage start = (CallMessage)message;
|
||||
|
||||
int channel = start.getChannel();
|
||||
|
||||
mLCNTracker.processCallChannel( channel );
|
||||
|
||||
mLCNTracker.processFreeChannel( start.getFree() );
|
||||
|
||||
//Only process calls on this LCN, or call detects for
|
||||
//talkgroups that are homed on this LCN
|
||||
if( mLCNTracker.isValidChannel( channel ) &&
|
||||
( mLCNTracker.isCurrentChannel( channel ) ||
|
||||
mLCNTracker.isCurrentChannel( start.getHomeRepeater() ) ) )
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get( channel );
|
||||
|
||||
if( event == null ||
|
||||
!event.isMatchingTalkgroup( start.getToID() ) )
|
||||
{
|
||||
//Check for different talkgroup
|
||||
if( event != null )
|
||||
{
|
||||
event.end();
|
||||
mActiveCalls.remove( channel );
|
||||
}
|
||||
|
||||
boolean current = mLCNTracker.isCurrentChannel( channel );
|
||||
|
||||
event = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_STANDARD,
|
||||
current ? CallEventType.CALL : CallEventType.CALL_DETECT )
|
||||
.to( start.getToID() )
|
||||
.aliasList( getAliasList() )
|
||||
.channel( start.getChannelFormatted() )
|
||||
.frequency( current ? mFrequency : 0 )
|
||||
.build();
|
||||
|
||||
mActiveCalls.put( channel, event );
|
||||
|
||||
broadcast( event );
|
||||
|
||||
if( mLCNTracker.isCurrentChannel( channel ) )
|
||||
{
|
||||
mTalkgroup = start.getToID();
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
|
||||
processTalkgroup( mTalkgroup );
|
||||
|
||||
mTalkgroupAlias = start.getToIDAlias();
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
broadcast( new Metadata( MetadataType.TO,
|
||||
mTalkgroup, mTalkgroupAlias, true ) );
|
||||
}
|
||||
}
|
||||
|
||||
broadcast( new DecoderStateEvent( this,
|
||||
Event.CONTINUATION, State.CALL ) );
|
||||
}
|
||||
break;
|
||||
case CA_ENDD:
|
||||
CallEndMessage end = (CallEndMessage)message;
|
||||
|
||||
//Home channel is 31 for call end -- use the free channel
|
||||
//as the call end channel
|
||||
int repeater = end.getFree();
|
||||
|
||||
mLCNTracker.processCallChannel( repeater );
|
||||
|
||||
if( mLCNTracker.isCurrentChannel( repeater ) )
|
||||
{
|
||||
mTalkgroup = end.getToID();
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
|
||||
processTalkgroup( mTalkgroup );
|
||||
|
||||
mTalkgroupAlias = end.getToIDAlias();
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
LTRCallEvent event = mActiveCalls.remove( repeater );
|
||||
|
||||
if( event != null )
|
||||
{
|
||||
event.end();
|
||||
broadcast( event );
|
||||
broadcast( new DecoderStateEvent( this, Event.END, State.FADE ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SY_IDLE:
|
||||
IdleMessage idle = (IdleMessage)message;
|
||||
|
||||
int lcn = idle.getChannel();
|
||||
|
||||
mLCNTracker.processCallChannel( lcn );
|
||||
|
||||
break;
|
||||
case UN_KNWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
super(aliasList);
|
||||
}
|
||||
|
||||
private void processTalkgroup( String talkgroup )
|
||||
{
|
||||
if( mTalkgroupsFirstHeard.contains( talkgroup ) )
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if(message.isValid() && message instanceof LTRStandardMessage)
|
||||
{
|
||||
mTalkgroups.add( talkgroup );
|
||||
switch(((LTRStandardMessage) message).getMessageType())
|
||||
{
|
||||
case CA_STRT:
|
||||
CallMessage start = (CallMessage) message;
|
||||
|
||||
int channel = start.getChannel();
|
||||
|
||||
setChannelNumber(channel);
|
||||
|
||||
mLCNTracker.processFreeChannel(start.getFree());
|
||||
|
||||
//Only process calls on this LCN, or call detects for
|
||||
//talkgroups that are homed on this LCN
|
||||
if(mLCNTracker.isValidChannel(channel) &&
|
||||
(mLCNTracker.isCurrentChannel(channel) ||
|
||||
mLCNTracker.isCurrentChannel(start.getHomeRepeater())))
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get(channel);
|
||||
|
||||
if(event == null || !event.isMatchingTalkgroup(start.getToID()))
|
||||
{
|
||||
//Check for different talkgroup
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
mActiveCalls.remove(channel);
|
||||
}
|
||||
|
||||
boolean current = mLCNTracker.isCurrentChannel(channel);
|
||||
|
||||
event = new LTRCallEvent.Builder(
|
||||
DecoderType.LTR_STANDARD,
|
||||
current ? CallEventType.CALL : CallEventType.CALL_DETECT)
|
||||
.to(start.getToID())
|
||||
.aliasList(getAliasList())
|
||||
.channel(start.getChannelFormatted())
|
||||
.frequency(current ? mFrequency : 0)
|
||||
.build();
|
||||
|
||||
mActiveCalls.put(channel, event);
|
||||
|
||||
broadcast(event);
|
||||
|
||||
if(mLCNTracker.isCurrentChannel(channel))
|
||||
{
|
||||
setTalkgroup(start.getToID());
|
||||
|
||||
processTalkgroup(mTalkgroup);
|
||||
|
||||
setTalkgroupAlias(start.getToIDAlias());
|
||||
}
|
||||
}
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL));
|
||||
}
|
||||
break;
|
||||
case CA_ENDD:
|
||||
CallEndMessage end = (CallEndMessage) message;
|
||||
|
||||
//Home channel is 31 for call end -- use the free channel
|
||||
//as the call end channel
|
||||
int repeater = end.getFree();
|
||||
|
||||
setChannelNumber(repeater);
|
||||
|
||||
if(mLCNTracker.isCurrentChannel(repeater))
|
||||
{
|
||||
setTalkgroup(end.getToID());
|
||||
|
||||
processTalkgroup(mTalkgroup);
|
||||
|
||||
setTalkgroupAlias(end.getToIDAlias());
|
||||
|
||||
LTRCallEvent event = mActiveCalls.remove(repeater);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
broadcast(event);
|
||||
broadcast(new DecoderStateEvent(this, Event.END, State.FADE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SY_IDLE:
|
||||
IdleMessage idle = (IdleMessage) message;
|
||||
|
||||
int lcn = idle.getChannel();
|
||||
|
||||
mLCNTracker.processCallChannel(lcn);
|
||||
|
||||
break;
|
||||
case UN_KNWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processTalkgroup(String talkgroup)
|
||||
{
|
||||
if(mTalkgroupsFirstHeard.contains(talkgroup))
|
||||
{
|
||||
mTalkgroups.add(talkgroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTalkgroupsFirstHeard.add( talkgroup );
|
||||
mTalkgroupsFirstHeard.add(talkgroup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full reset
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mActiveCalls.clear();
|
||||
mTalkgroupsFirstHeard.clear();
|
||||
mTalkgroups.clear();
|
||||
mLCNTracker.reset();
|
||||
}
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a temporal reset following a call or other decode event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
for( Integer key: mActiveCalls.keySet() )
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get( key );
|
||||
|
||||
if( event != null )
|
||||
{
|
||||
event.end();
|
||||
|
||||
broadcast( event );
|
||||
}
|
||||
}
|
||||
|
||||
mActiveCalls.clear();
|
||||
|
||||
mTalkgroup = null;
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
/**
|
||||
* Performs a full reset
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mActiveCalls.clear();
|
||||
mTalkgroupsFirstHeard.clear();
|
||||
mTalkgroups.clear();
|
||||
mLCNTracker.reset();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a temporal reset following a call or other decode event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
for(Integer key : mActiveCalls.keySet())
|
||||
{
|
||||
LTRCallEvent event = mActiveCalls.get(key);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end();
|
||||
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
mActiveCalls.clear();
|
||||
|
||||
mTalkgroup = null;
|
||||
mTalkgroupAlias = null;
|
||||
}
|
||||
|
||||
public String getTalkgroup()
|
||||
{
|
||||
return mTalkgroup;
|
||||
}
|
||||
|
||||
private void setTalkgroup(String talkgroup)
|
||||
{
|
||||
if(!StringUtils.isEqual(mTalkgroup, talkgroup))
|
||||
{
|
||||
mTalkgroup = talkgroup;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mTalkgroup, mTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getTalkgroupAlias()
|
||||
{
|
||||
return mTalkgroupAlias;
|
||||
}
|
||||
|
||||
private void setTalkgroupAlias(Alias alias)
|
||||
{
|
||||
if(mTalkgroupAlias == null || (alias != null && mTalkgroupAlias != alias))
|
||||
{
|
||||
mTalkgroupAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mTalkgroup, mTalkgroupAlias));
|
||||
}
|
||||
}
|
||||
|
||||
mTalkgroupAlias = null;
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getTalkgroup()
|
||||
{
|
||||
return mTalkgroup;
|
||||
}
|
||||
|
||||
public Alias getTalkgroupAlias()
|
||||
{
|
||||
return mTalkgroupAlias;
|
||||
}
|
||||
|
||||
public boolean hasChannelNumber()
|
||||
{
|
||||
return mLCNTracker.getCurrentChannel() != 0;
|
||||
}
|
||||
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mLCNTracker.getCurrentChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
private void setChannelNumber(int channel)
|
||||
{
|
||||
int original = mLCNTracker.getCurrentChannel();
|
||||
|
||||
@Override
|
||||
public void receiveDecoderStateEvent( DecoderStateEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
case SOURCE_FREQUENCY:
|
||||
mFrequency = event.getFrequency();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
mLCNTracker.processCallChannel(channel);
|
||||
|
||||
if(mLCNTracker.getCurrentChannel() != original)
|
||||
{
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.CHANNEL_FREQUENCY_LABEL,
|
||||
"LCN:" + mLCNTracker.getCurrentChannel()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
case SOURCE_FREQUENCY:
|
||||
mFrequency = event.getFrequency();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "Activity Summary\n\n" );
|
||||
|
||||
sb.append( "Decoder:\tLTR-Standard\n" );
|
||||
|
||||
sb.append( "Monitored LCN: " );
|
||||
|
||||
if( hasChannelNumber() )
|
||||
{
|
||||
sb.append( getChannelNumber() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "*Insufficient Data*" );
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
|
||||
sb.append( "Active LCNs:\t" );
|
||||
sb.append("Activity Summary\n\n");
|
||||
|
||||
List<Integer> lcns = mLCNTracker.getActiveLCNs();
|
||||
|
||||
if( lcns.size() > 0 )
|
||||
{
|
||||
sb.append( mLCNTracker.getActiveLCNs() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "*Insufficient Data*" );
|
||||
}
|
||||
sb.append( "\n\n" );
|
||||
sb.append("Decoder:\tLTR-Standard\n");
|
||||
|
||||
sb.append( "Talkgroups\n" );
|
||||
|
||||
if( mTalkgroups.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( String talkgroup: mTalkgroups )
|
||||
{
|
||||
sb.append( " " );
|
||||
sb.append( talkgroup );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias( talkgroup );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
sb.append("Monitored LCN: ");
|
||||
|
||||
if(hasChannelNumber())
|
||||
{
|
||||
sb.append(getChannelNumber());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("*Insufficient Data*");
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
sb.append("Active LCNs:\t");
|
||||
|
||||
List<Integer> lcns = mLCNTracker.getActiveLCNs();
|
||||
|
||||
if(lcns.size() > 0)
|
||||
{
|
||||
sb.append(mLCNTracker.getActiveLCNs());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("*Insufficient Data*");
|
||||
}
|
||||
sb.append("\n\n");
|
||||
|
||||
sb.append("Talkgroups\n");
|
||||
|
||||
if(mTalkgroups.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(String talkgroup : mTalkgroups)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(talkgroup);
|
||||
sb.append(" ");
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias(talkgroup);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the set of call and free channels for a system in order to
|
||||
* dynamically determine the current LCN and minimize false triggers from
|
||||
* bogus decoded LTR messages. Tracks the number of occurances of each
|
||||
* LCN and uses a dynamic threshold to determine LCN validity.
|
||||
*/
|
||||
public class LCNTracker
|
||||
{
|
||||
private static final int DEFAULT_COUNT = 10;
|
||||
private int[] mCallLCNCounts;
|
||||
private int[] mFreeLCNCounts;
|
||||
private int mCallHighestCount;
|
||||
private int mFreeHighestCount;
|
||||
private int mCurrentLCN;
|
||||
|
||||
public LCNTracker()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
public void logStatistics()
|
||||
{
|
||||
for( int x = 1; x <= 20; x++ )
|
||||
{
|
||||
mLog.debug( "Call " + x + ": " + mCallLCNCounts[ x ] );
|
||||
}
|
||||
mLog.debug( "Call Highest Count: " + mCallHighestCount );
|
||||
for( int x = 1; x <= 20; x++ )
|
||||
{
|
||||
mLog.debug( "Free " + x + ": " + mFreeLCNCounts[ x ] );
|
||||
}
|
||||
mLog.debug( "Free Highest Count: " + mFreeHighestCount );
|
||||
|
||||
mLog.debug( "Current LCN: " + mCurrentLCN );
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
//Dim channel arrays to 21 -- ignore the 0 index
|
||||
mCallLCNCounts = new int[ 21 ];
|
||||
mFreeLCNCounts = new int[ 21 ];
|
||||
mCallHighestCount = 3;
|
||||
mFreeHighestCount = DEFAULT_COUNT;
|
||||
mCurrentLCN = 0;
|
||||
}
|
||||
|
||||
public boolean isCurrentChannel( int channel )
|
||||
{
|
||||
if( mCurrentLCN == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return channel == mCurrentLCN;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentChannel()
|
||||
{
|
||||
return mCurrentLCN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the channel is valid based on the observed current and
|
||||
* free channels reported by the system. Tracks the count of each
|
||||
* reported free channel the highest free channel count is used as a
|
||||
* threshold where a channel is valid when its count exceeds 20% of the
|
||||
* highest free channel count. A channel is also valid when it is
|
||||
* the currently monitored channel.
|
||||
*/
|
||||
public boolean isValidChannel( int channel )
|
||||
{
|
||||
if( isCurrentChannel( channel ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Tracks the set of call and free channels for a system in order to
|
||||
* dynamically determine the current LCN and minimize false triggers from
|
||||
* bogus decoded LTR messages. Tracks the number of occurances of each
|
||||
* LCN and uses a dynamic threshold to determine LCN validity.
|
||||
*/
|
||||
public class LCNTracker
|
||||
{
|
||||
private static final int DEFAULT_COUNT = 10;
|
||||
private int[] mCallLCNCounts;
|
||||
private int[] mFreeLCNCounts;
|
||||
private int mCallHighestCount;
|
||||
private int mFreeHighestCount;
|
||||
private int mCurrentLCN;
|
||||
|
||||
int count = mFreeLCNCounts[ channel ];
|
||||
|
||||
int threshold = (int)( (double)mFreeHighestCount * 0.2 );
|
||||
public LCNTracker()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
return count >= threshold;
|
||||
}
|
||||
public void logStatistics()
|
||||
{
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
mLog.debug("Call " + x + ": " + mCallLCNCounts[x]);
|
||||
}
|
||||
mLog.debug("Call Highest Count: " + mCallHighestCount);
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
mLog.debug("Free " + x + ": " + mFreeLCNCounts[x]);
|
||||
}
|
||||
mLog.debug("Free Highest Count: " + mFreeHighestCount);
|
||||
|
||||
public void processCallChannel( int channel )
|
||||
{
|
||||
if( 1 <= channel && channel <= 20 )
|
||||
{
|
||||
mCallLCNCounts[ channel ]++;
|
||||
|
||||
if( mCallLCNCounts[ channel ] > mCallHighestCount )
|
||||
{
|
||||
mCallHighestCount = mCallLCNCounts[ channel ];
|
||||
mCurrentLCN = channel;
|
||||
|
||||
broadcast( Attribute.CHANNEL_NUMBER );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processFreeChannel( int channel )
|
||||
{
|
||||
if( 1 <= channel && channel <= 20 )
|
||||
{
|
||||
mFreeLCNCounts[ channel ]++;
|
||||
|
||||
if( mFreeLCNCounts[ channel ] > mFreeHighestCount )
|
||||
{
|
||||
mFreeHighestCount = mFreeLCNCounts[ channel ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> getActiveLCNs()
|
||||
{
|
||||
List<Integer> active = new ArrayList<>();
|
||||
|
||||
if( mFreeHighestCount > DEFAULT_COUNT )
|
||||
{
|
||||
for( int x = 1; x <= 20; x++ )
|
||||
{
|
||||
if( mCurrentLCN != 0 && isCurrentChannel( x ) )
|
||||
{
|
||||
active.add( x );
|
||||
}
|
||||
else if( isValidChannel( x ) )
|
||||
{
|
||||
active.add( x );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
}
|
||||
mLog.debug("Current LCN: " + mCurrentLCN);
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
//Dim channel arrays to 21 -- ignore the 0 index
|
||||
mCallLCNCounts = new int[21];
|
||||
mFreeLCNCounts = new int[21];
|
||||
mCallHighestCount = 3;
|
||||
mFreeHighestCount = DEFAULT_COUNT;
|
||||
mCurrentLCN = 0;
|
||||
}
|
||||
|
||||
public boolean isCurrentChannel(int channel)
|
||||
{
|
||||
if(mCurrentLCN == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return channel == mCurrentLCN;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentChannel()
|
||||
{
|
||||
return mCurrentLCN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the channel is valid based on the observed current and
|
||||
* free channels reported by the system. Tracks the count of each
|
||||
* reported free channel the highest free channel count is used as a
|
||||
* threshold where a channel is valid when its count exceeds 20% of the
|
||||
* highest free channel count. A channel is also valid when it is
|
||||
* the currently monitored channel.
|
||||
*/
|
||||
public boolean isValidChannel(int channel)
|
||||
{
|
||||
if(isCurrentChannel(channel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int count = mFreeLCNCounts[channel];
|
||||
|
||||
int threshold = (int) ((double) mFreeHighestCount * 0.2);
|
||||
|
||||
return count >= threshold;
|
||||
}
|
||||
|
||||
public void processCallChannel(int channel)
|
||||
{
|
||||
if(1 <= channel && channel <= 20)
|
||||
{
|
||||
mCallLCNCounts[channel]++;
|
||||
|
||||
if(mCallLCNCounts[channel] > mCallHighestCount)
|
||||
{
|
||||
mCallHighestCount = mCallLCNCounts[channel];
|
||||
mCurrentLCN = channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processFreeChannel(int channel)
|
||||
{
|
||||
if(1 <= channel && channel <= 20)
|
||||
{
|
||||
mFreeLCNCounts[channel]++;
|
||||
|
||||
if(mFreeLCNCounts[channel] > mFreeHighestCount)
|
||||
{
|
||||
mFreeHighestCount = mFreeLCNCounts[channel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> getActiveLCNs()
|
||||
{
|
||||
List<Integer> active = new ArrayList<>();
|
||||
|
||||
if(mFreeHighestCount > DEFAULT_COUNT)
|
||||
{
|
||||
for(int x = 1; x <= 20; x++)
|
||||
{
|
||||
if(mCurrentLCN != 0 && isCurrentChannel(x))
|
||||
{
|
||||
active.add(x);
|
||||
}
|
||||
else if(isValidChannel(x))
|
||||
{
|
||||
active.add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,183 +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 module.decode.mdc1200;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MDCDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String sPROTOCOL = "MDC-1200";
|
||||
|
||||
private JLabel mFromLabel = new JLabel(" ");
|
||||
private JLabel mFrom = new JLabel();
|
||||
private JLabel mFromAlias = new JLabel();
|
||||
|
||||
private JLabel mToLabel = new JLabel(" ");
|
||||
private JLabel mTo = new JLabel();
|
||||
private JLabel mToAlias = new JLabel();
|
||||
|
||||
private JLabel mProtocol = new JLabel(sPROTOCOL);
|
||||
private JLabel mMessage = new JLabel();
|
||||
private JLabel mMessageType = new JLabel();
|
||||
|
||||
public MDCDecoderPanel(IconManager iconManager, SettingsManager settingsManager, MDCDecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public MDCDecoderState getDecoderState()
|
||||
{
|
||||
return (MDCDecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
/* Calling super init will get and broadcast color settings to properly
|
||||
* setup the jlabel colors */
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 1 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
add(mFromLabel);
|
||||
add(mFrom);
|
||||
add(mFromAlias, "wrap");
|
||||
|
||||
add(mToLabel);
|
||||
add(mTo);
|
||||
add(mToAlias, "wrap");
|
||||
|
||||
add(mProtocol);
|
||||
add(mMessageType);
|
||||
add(mMessage, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case FROM_TALKGROUP:
|
||||
String from = getDecoderState().getFrom();
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
mFromLabel.setText("FM:");
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromLabel.setText(" ");
|
||||
}
|
||||
mFrom.setText(from);
|
||||
break;
|
||||
case FROM_TALKGROUP_ALIAS:
|
||||
Alias fromAlias = getDecoderState().getFromAlias();
|
||||
|
||||
if(fromAlias != null)
|
||||
{
|
||||
mFromAlias.setText(fromAlias.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromAlias.setText(null);
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
String to = getDecoderState().getTo();
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
mToLabel.setText("TO:");
|
||||
}
|
||||
else
|
||||
{
|
||||
mToLabel.setText(" ");
|
||||
}
|
||||
mTo.setText(to);
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias toAlias = getDecoderState().getToAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
mToAlias.setText(toAlias.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
mToAlias.setText(null);
|
||||
}
|
||||
break;
|
||||
case MESSAGE:
|
||||
mMessage.setText(getDecoderState().getMessage());
|
||||
break;
|
||||
case MESSAGE_TYPE:
|
||||
mMessageType.setText(getDecoderState().getMessageType());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting color = (ColorSetting) setting;
|
||||
|
||||
if(color.getColorSettingName() ==
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER)
|
||||
{
|
||||
mFromLabel.setForeground(color.getColor());
|
||||
mFrom.setForeground(color.getColor());
|
||||
mFromAlias.setForeground(color.getColor());
|
||||
mToLabel.setForeground(color.getColor());
|
||||
mTo.setForeground(color.getColor());
|
||||
mToAlias.setForeground(color.getColor());
|
||||
mProtocol.setForeground(color.getColor());
|
||||
mMessageType.setForeground(color.getColor());
|
||||
mMessage.setForeground(color.getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,306 +1,327 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 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-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 module.decode.mdc1200;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.State;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
public class MDCDecoderState extends DecoderState
|
||||
{
|
||||
private TreeSet<String> mIdents = new TreeSet<String>();
|
||||
private TreeSet<String> mEmergencyIdents = new TreeSet<String>();
|
||||
private TreeSet<String> mIdents = new TreeSet<String>();
|
||||
private TreeSet<String> mEmergencyIdents = new TreeSet<String>();
|
||||
|
||||
private String mFrom;
|
||||
private Alias mFromAlias;
|
||||
private String mTo;
|
||||
private Alias mToAlias;
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
private String mFrom;
|
||||
private Alias mFromAlias;
|
||||
private String mTo;
|
||||
private Alias mToAlias;
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
|
||||
public MDCDecoderState( AliasList aliasList )
|
||||
{
|
||||
super( aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.MDC1200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mIdents.clear();
|
||||
mEmergencyIdents.clear();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
setFrom( null );
|
||||
setFromAlias( null );
|
||||
setTo( null);
|
||||
setToAlias( null );
|
||||
setMessage( null );
|
||||
setMessageType( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
public MDCDecoderState(AliasList aliasList)
|
||||
{
|
||||
if( message instanceof MDCMessage )
|
||||
{
|
||||
MDCMessage mdc = (MDCMessage)message;
|
||||
|
||||
mIdents.add( mdc.getUnitID() );
|
||||
|
||||
if( mdc.isEmergency() )
|
||||
{
|
||||
mEmergencyIdents.add( mdc.getUnitID() );
|
||||
}
|
||||
|
||||
setFrom( mdc.getFromID() );
|
||||
setFromAlias( mdc.getFromIDAlias() );
|
||||
|
||||
MDCMessageType type = mdc.getMessageType();
|
||||
|
||||
setMessageType( type.getLabel() );
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "OPCODE " );
|
||||
sb.append( String.valueOf( mdc.getOpcode() ) );
|
||||
|
||||
if( mdc.isBOT() )
|
||||
{
|
||||
sb.append( " TYPE:BOT" );
|
||||
}
|
||||
|
||||
if( mdc.isEOT() )
|
||||
{
|
||||
sb.append( " TYPE:EOT" );
|
||||
}
|
||||
|
||||
setMessage( sb.toString() );
|
||||
|
||||
MDCCallEvent event = MDCCallEvent.getMDCCallEvent( mdc );
|
||||
event.setAliasList( getAliasList() );
|
||||
broadcast( event );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case ANI:
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.CALL ) );
|
||||
break;
|
||||
case ACKNOWLEDGE:
|
||||
case EMERGENCY:
|
||||
case PAGING:
|
||||
case STATUS:
|
||||
default:
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.DATA ) );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
super(aliasList);
|
||||
}
|
||||
|
||||
public String getFrom()
|
||||
{
|
||||
return mFrom;
|
||||
}
|
||||
|
||||
public void setFrom( String from )
|
||||
{
|
||||
mFrom = from;
|
||||
broadcast( Attribute.FROM_TALKGROUP );
|
||||
}
|
||||
|
||||
public Alias getFromAlias()
|
||||
{
|
||||
return mFromAlias;
|
||||
}
|
||||
|
||||
public void setFromAlias( Alias alias )
|
||||
{
|
||||
mFromAlias = alias;
|
||||
broadcast( Attribute.FROM_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getTo()
|
||||
{
|
||||
return mTo;
|
||||
}
|
||||
|
||||
public void setTo( String to )
|
||||
{
|
||||
mTo = to;
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
}
|
||||
|
||||
public Alias getToAlias()
|
||||
{
|
||||
return mToAlias;
|
||||
}
|
||||
|
||||
public void setToAlias( Alias alias )
|
||||
{
|
||||
mToAlias = alias;
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public void setMessage( String message )
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast( Attribute.MESSAGE );
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
|
||||
public void setMessageType( String type )
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast( Attribute.MESSAGE_TYPE );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.MDC1200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mIdents.clear();
|
||||
mEmergencyIdents.clear();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
mFrom = null;
|
||||
mFromAlias = null;
|
||||
mTo = null;
|
||||
mToAlias = null;
|
||||
mMessage = null;
|
||||
mMessageType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if(message instanceof MDCMessage)
|
||||
{
|
||||
MDCMessage mdc = (MDCMessage) message;
|
||||
|
||||
mIdents.add(mdc.getUnitID());
|
||||
|
||||
if(mdc.isEmergency())
|
||||
{
|
||||
mEmergencyIdents.add(mdc.getUnitID());
|
||||
}
|
||||
|
||||
setFrom(mdc.getFromID());
|
||||
setFromAlias(mdc.getFromIDAlias());
|
||||
|
||||
MDCMessageType type = mdc.getMessageType();
|
||||
|
||||
setMessageType(type.getLabel());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("OPCODE ");
|
||||
sb.append(String.valueOf(mdc.getOpcode()));
|
||||
|
||||
if(mdc.isBOT())
|
||||
{
|
||||
sb.append(" TYPE:BOT");
|
||||
}
|
||||
|
||||
if(mdc.isEOT())
|
||||
{
|
||||
sb.append(" TYPE:EOT");
|
||||
}
|
||||
|
||||
setMessage(sb.toString());
|
||||
|
||||
MDCCallEvent event = MDCCallEvent.getMDCCallEvent(mdc);
|
||||
event.setAliasList(getAliasList());
|
||||
broadcast(event);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ANI:
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.CALL));
|
||||
break;
|
||||
case ACKNOWLEDGE:
|
||||
case EMERGENCY:
|
||||
case PAGING:
|
||||
case STATUS:
|
||||
default:
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.DATA));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getFrom()
|
||||
{
|
||||
return mFrom;
|
||||
}
|
||||
|
||||
public void setFrom(String from)
|
||||
{
|
||||
if(!StringUtils.isEqual(mFrom, from))
|
||||
{
|
||||
mFrom = from;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getFromAlias()
|
||||
{
|
||||
return mFromAlias;
|
||||
}
|
||||
|
||||
public void setFromAlias(Alias alias)
|
||||
{
|
||||
if(mFromAlias == null || (alias != null && mFromAlias != alias))
|
||||
{
|
||||
mFromAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getTo()
|
||||
{
|
||||
return mTo;
|
||||
}
|
||||
|
||||
public void setTo(String to)
|
||||
{
|
||||
if(!StringUtils.isEqual(mTo, to))
|
||||
{
|
||||
mTo = to;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getToAlias()
|
||||
{
|
||||
return mToAlias;
|
||||
}
|
||||
|
||||
public void setToAlias(Alias alias)
|
||||
{
|
||||
if(mToAlias == null || (alias != null && mToAlias != alias))
|
||||
{
|
||||
mToAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessage, message))
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE, mMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String type)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessageType, type))
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE_TYPE, "MDC:" + mMessageType));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "=============================\n" );
|
||||
sb.append( "Decoder:\tMDC-1200\n\n" );
|
||||
sb.append( "MDC-1200 Idents\n" );
|
||||
sb.append("=============================\n");
|
||||
sb.append("Decoder:\tMDC-1200\n\n");
|
||||
sb.append("MDC-1200 Idents\n");
|
||||
|
||||
if( mIdents.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mIdents.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String ident = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( ident );
|
||||
sb.append( " " );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getMDC1200Alias( ident );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
if(mIdents.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mIdents.iterator();
|
||||
|
||||
sb.append( "MDC-1200 Emergency Idents\n" );
|
||||
while(it.hasNext())
|
||||
{
|
||||
String ident = it.next();
|
||||
|
||||
if( mEmergencyIdents.isEmpty() )
|
||||
{
|
||||
sb.append( " None\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mEmergencyIdents.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
String ident = it.next();
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( ident );
|
||||
sb.append( " " );
|
||||
sb.append(" ");
|
||||
sb.append(ident);
|
||||
sb.append(" ");
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getMDC1200Alias( ident );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getMDC1200Alias(ident);
|
||||
|
||||
return sb.toString();
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("MDC-1200 Emergency Idents\n");
|
||||
|
||||
if(mEmergencyIdents.isEmpty())
|
||||
{
|
||||
sb.append(" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Iterator<String> it = mEmergencyIdents.iterator();
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
String ident = it.next();
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(ident);
|
||||
sb.append(" ");
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getMDC1200Alias(ident);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization required */
|
||||
}
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization required */
|
||||
}
|
||||
|
||||
/**
|
||||
* Responds to reset events issued by the channel state
|
||||
*/
|
||||
@Override
|
||||
public void receiveDecoderStateEvent( DecoderStateEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Responds to reset events issued by the channel state
|
||||
*/
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,200 +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 module.decode.mpt1327;
|
||||
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MPT1327DecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("");
|
||||
private JLabel mSiteOrToTalkgroup = new JLabel("");
|
||||
private JLabel mSiteOrToTalkgroupAlias = new JLabel("");
|
||||
|
||||
private JLabel mFromTalkgroupLabel = new JLabel("");
|
||||
private JLabel mFromTalkgroup = new JLabel("");
|
||||
private JLabel mFromTalkgroupAliasLabel = new JLabel("");
|
||||
|
||||
public MPT1327DecoderPanel(IconManager iconManager, SettingsManager settingsManager, MPT1327DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public MPT1327DecoderState getDecoderState()
|
||||
{
|
||||
return (MPT1327DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setText("MPT1327");
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
MPT1327DecoderState mptState = getDecoderState();
|
||||
|
||||
mSiteOrToTalkgroup.setFont(mFontDecoder);
|
||||
mSiteOrToTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mSiteOrToTalkgroupAlias.setFont(mFontDecoder);
|
||||
mSiteOrToTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroupLabel.setFont(mFontDetails);
|
||||
mFromTalkgroupLabel.setForeground(mColorLabelDetails);
|
||||
|
||||
mFromTalkgroup.setFont(mFontDecoder);
|
||||
mFromTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroupAliasLabel.setFont(mFontDecoder);
|
||||
mFromTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
|
||||
switch(mptState.getChannelType())
|
||||
{
|
||||
case STANDARD:
|
||||
mSiteOrToTalkgroup.setText(mptState.getSite());
|
||||
setAliasLabel(mSiteOrToTalkgroupAlias, mptState.getSiteAlias());
|
||||
break;
|
||||
case TRAFFIC:
|
||||
mSiteOrToTalkgroup.setText(mptState.getToTalkgroup());
|
||||
setAliasLabel(mSiteOrToTalkgroupAlias, mptState.getToTalkgroupAlias());
|
||||
|
||||
mFromTalkgroupLabel.setText("From:");
|
||||
mFromTalkgroup.setText(getDecoderState().getFromTalkgroup());
|
||||
setAliasLabel(mFromTalkgroupAliasLabel, mptState.getFromTalkgroupAlias());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized channel "
|
||||
+ "type in MPT1327 Decoder [" + getDecoderState()
|
||||
.getChannelType().name() + "]");
|
||||
}
|
||||
|
||||
add(mProtocol);
|
||||
add(mSiteOrToTalkgroup);
|
||||
add(mSiteOrToTalkgroupAlias, "wrap");
|
||||
|
||||
if(mptState.getChannelType() == ChannelType.TRAFFIC)
|
||||
{
|
||||
add(mFromTalkgroupLabel);
|
||||
add(mFromTalkgroup);
|
||||
add(mFromTalkgroupAliasLabel, "wrap");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
final MPT1327DecoderState state = getDecoderState();
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case CHANNEL_SITE_NUMBER:
|
||||
mSiteOrToTalkgroup.setText(String.valueOf(state.getSite()));
|
||||
setAliasLabel(mSiteOrToTalkgroupAlias, state.getSiteAlias(), false);
|
||||
repaint();
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
mSiteOrToTalkgroup.setText(state.getToTalkgroup());
|
||||
setAliasLabel(mSiteOrToTalkgroupAlias, state.getToTalkgroupAlias());
|
||||
repaint();
|
||||
break;
|
||||
case FROM_TALKGROUP:
|
||||
mFromTalkgroup.setText(state.getFromTalkgroup());
|
||||
setAliasLabel(mFromTalkgroupAliasLabel, state.getFromTalkgroupAlias());
|
||||
repaint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mSiteOrToTalkgroup != null)
|
||||
{
|
||||
mSiteOrToTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mSiteOrToTalkgroupAlias != null)
|
||||
{
|
||||
mSiteOrToTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mFromTalkgroup != null)
|
||||
{
|
||||
mFromTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mFromTalkgroupAliasLabel != null)
|
||||
{
|
||||
mFromTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
if(mFromTalkgroupLabel != null)
|
||||
{
|
||||
mFromTalkgroupLabel.setForeground(mColorLabelDetails);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,179 +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 module.decode.mpt1327;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MPT1327TrafficPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocolLabel;
|
||||
private JLabel mFromTalkgroupLabel;
|
||||
private JLabel mFromTalkgroupAliasLabel;
|
||||
|
||||
private JLabel mToLabel;
|
||||
private JLabel mToTalkgroupLabel;
|
||||
private JLabel mToTalkgroupAliasLabel;
|
||||
|
||||
public MPT1327TrafficPanel(IconManager iconManager, SettingsManager settingsManager,
|
||||
MPT1327DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public MPT1327DecoderState getDecoderState()
|
||||
{
|
||||
return (MPT1327DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
mProtocolLabel = new JLabel("MPT1327");
|
||||
mProtocolLabel.setFont(mFontDecoder);
|
||||
mProtocolLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroupLabel = new JLabel();
|
||||
mFromTalkgroupLabel.setFont(mFontDecoder);
|
||||
mFromTalkgroupLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroupAliasLabel = new JLabel();
|
||||
mFromTalkgroupAliasLabel.setFont(mFontDecoder);
|
||||
mFromTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToLabel = new JLabel("TO:");
|
||||
mToLabel.setFont(mFontDetails);
|
||||
mToLabel.setForeground(mColorLabelDetails);
|
||||
|
||||
mToTalkgroupLabel = new JLabel(getDecoderState().getFromTalkgroup());
|
||||
mToTalkgroupLabel.setFont(mFontDecoder);
|
||||
mToTalkgroupLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToTalkgroupAliasLabel = new JLabel();
|
||||
mToTalkgroupAliasLabel.setFont(mFontDecoder);
|
||||
mToTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocolLabel);
|
||||
add(mFromTalkgroupLabel);
|
||||
add(mFromTalkgroupAliasLabel, "wrap");
|
||||
|
||||
add(mToLabel);
|
||||
add(mToTalkgroupLabel);
|
||||
add(mToTalkgroupAliasLabel, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
final MPT1327DecoderState state = getDecoderState();
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case FROM_TALKGROUP:
|
||||
String talkgroup = state.getFromTalkgroup();
|
||||
|
||||
mFromTalkgroupLabel.setText(talkgroup);
|
||||
|
||||
Alias alias = state.getFromTalkgroupAlias();
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
mFromTalkgroupAliasLabel.setText(alias.getName());
|
||||
|
||||
String icon = alias.getIconName();
|
||||
|
||||
mFromTalkgroupAliasLabel.setIcon(mIconManager.getIcon(icon, IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
String toTalkgroup = state.getToTalkgroup();
|
||||
|
||||
mToTalkgroupLabel.setText(toTalkgroup);
|
||||
|
||||
Alias toAlias = state.getToTalkgroupAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
mToTalkgroupAliasLabel.setText(toAlias.getName());
|
||||
|
||||
String icon = toAlias.getIconName();
|
||||
|
||||
if(icon != null)
|
||||
{
|
||||
mToTalkgroupAliasLabel.setIcon(mIconManager.getIcon(icon, IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
mProtocolLabel.setForeground(mColorLabelDecoder);
|
||||
mFromTalkgroupLabel.setForeground(mColorLabelDecoder);
|
||||
mFromTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
mToTalkgroupLabel.setForeground(mColorLabelDecoder);
|
||||
mToTalkgroupAliasLabel.setForeground(mColorLabelDecoder);
|
||||
break;
|
||||
case CHANNEL_STATE_LABEL_DETAILS:
|
||||
mToLabel.setForeground(mColorLabelDetails);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +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 module.decode.nbfm;
|
||||
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import channel.state.DecoderState;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class NBFMDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("NBFM");
|
||||
|
||||
public NBFMDecoderPanel(IconManager iconManager, SettingsManager settingsManager, DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Attribute t)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting color = (ColorSetting) setting;
|
||||
|
||||
if(color.getColorSettingName() ==
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_DECODER)
|
||||
{
|
||||
mProtocol.setForeground(color.getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,226 +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 module.decode.p25;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class P25DecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol;
|
||||
private JLabel mTo = new JLabel(" ");
|
||||
private JLabel mToAlias = new JLabel(" ");
|
||||
|
||||
private JLabel mNAC = new JLabel("NAC:");
|
||||
private JLabel mFrom = new JLabel(" ");
|
||||
private JLabel mFromAlias = new JLabel(" ");
|
||||
|
||||
private JLabel mSystem = new JLabel("SYS:");
|
||||
private JLabel mSite = new JLabel("Site:");
|
||||
private JLabel mSiteAlias = new JLabel("");
|
||||
|
||||
|
||||
public P25DecoderPanel(IconManager iconManager, SettingsManager settingsManager, P25DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
mProtocol = new JLabel("P25-1 " + decoderState.getModulation().getShortLabel());
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
mTo.setFont(mFontDecoder);
|
||||
mTo.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToAlias.setFont(mFontDecoder);
|
||||
mToAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mNAC.setFont(mFontDetails);
|
||||
mNAC.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFrom.setFont(mFontDecoder);
|
||||
mFrom.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromAlias.setFont(mFontDecoder);
|
||||
mFromAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mSystem.setFont(mFontDetails);
|
||||
mSystem.setForeground(mColorLabelDecoder);
|
||||
|
||||
mSiteAlias.setFont(mFontDecoder);
|
||||
mSiteAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mSite.setFont(mFontDetails);
|
||||
mSite.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol);
|
||||
add(mTo);
|
||||
add(mToAlias, "wrap");
|
||||
|
||||
add(mNAC);
|
||||
add(mFrom);
|
||||
add(mFromAlias, "wrap");
|
||||
|
||||
add(mSystem);
|
||||
add(mSite);
|
||||
add(mSiteAlias, "wrap");
|
||||
}
|
||||
|
||||
public P25DecoderState getDecoderState()
|
||||
{
|
||||
return (P25DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
final P25DecoderState state = getDecoderState();
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
||||
switch(attribute)
|
||||
{
|
||||
case NAC:
|
||||
mNAC.setText("NAC:" + state.getNAC());
|
||||
break;
|
||||
case SYSTEM:
|
||||
mSystem.setText("SYS:" + state.getSystem());
|
||||
break;
|
||||
case SITE:
|
||||
mSite.setText("SITE:" + state.getSite());
|
||||
break;
|
||||
case SITE_ALIAS:
|
||||
mSiteAlias.setText(state.getSiteAlias());
|
||||
break;
|
||||
case FROM_TALKGROUP:
|
||||
if(state.getFromTalkgroup() == null)
|
||||
{
|
||||
mFrom.setText(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrom.setText(state.getFromTalkgroup());
|
||||
}
|
||||
break;
|
||||
case FROM_TALKGROUP_ALIAS:
|
||||
Alias from = state.getFromAlias();
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
mFromAlias.setText(from.getName());
|
||||
|
||||
final String icon = from.getIconName();
|
||||
|
||||
if(icon != null && mIconManager != null)
|
||||
{
|
||||
mFromAlias.setIcon(mIconManager.getIcon(icon, IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromAlias.setText(" ");
|
||||
mFromAlias.setIcon(null);
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
if(state.getToTalkgroup() == null)
|
||||
{
|
||||
mTo.setText(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
mTo.setText(state.getToTalkgroup());
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
final Alias to = state.getToAlias();
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
mToAlias.setText(to.getName());
|
||||
|
||||
final String icon = to.getIconName();
|
||||
|
||||
if(icon != null && mIconManager != null)
|
||||
{
|
||||
mToAlias.setIcon(mIconManager.getIcon(icon, IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mToAlias.setText(" ");
|
||||
mToAlias.setIcon(null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,14 @@ import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import alias.PatchGroupAlias;
|
||||
import alias.id.talkgroup.TalkgroupID;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.ChangeChannelTimeoutEvent;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import channel.traffic.TrafficChannelAllocationEvent;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -123,13 +129,6 @@ import module.decode.p25.reference.IPProtocol;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Response;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import channel.state.ChangeChannelTimeoutEvent;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import channel.traffic.TrafficChannelAllocationEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -159,10 +158,10 @@ public class P25DecoderState extends DecoderState
|
||||
private Set<module.decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcast> mSecondaryControlChannels =
|
||||
new TreeSet<>();
|
||||
|
||||
private Map<Integer, IdentifierUpdate> mBands = new HashMap<>();
|
||||
private Map<String, Long> mRegistrations = new HashMap<>();
|
||||
private Map<String, IAdjacentSite> mNeighborMap = new HashMap<>();
|
||||
private Map<String, List<String>> mPatchGroupMap = new HashMap<>();
|
||||
private Map<Integer,IdentifierUpdate> mBands = new HashMap<>();
|
||||
private Map<String,Long> mRegistrations = new HashMap<>();
|
||||
private Map<String,IAdjacentSite> mNeighborMap = new HashMap<>();
|
||||
private Map<String,List<String>> mPatchGroupMap = new HashMap<>();
|
||||
|
||||
private String mLastCommandEventID;
|
||||
private String mLastPageEventID;
|
||||
@@ -188,7 +187,7 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
private P25CallEvent mCurrentCallEvent;
|
||||
private List<String> mCallDetectTalkgroups = new ArrayList<>();
|
||||
private Map<String, P25CallEvent> mChannelCallMap = new HashMap<>();
|
||||
private Map<String,P25CallEvent> mChannelCallMap = new HashMap<>();
|
||||
|
||||
public P25DecoderState(AliasList aliasList,
|
||||
ChannelType channelType,
|
||||
@@ -225,9 +224,10 @@ public class P25DecoderState extends DecoderState
|
||||
{
|
||||
resetState();
|
||||
|
||||
updateNAC(null);
|
||||
updateSite(null);
|
||||
updateSystem(null);
|
||||
mNAC = null;
|
||||
mSite = null;
|
||||
mSiteAlias = null;
|
||||
mSystem = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,16 +236,9 @@ public class P25DecoderState extends DecoderState
|
||||
private void resetState()
|
||||
{
|
||||
mFromTalkgroup = null;
|
||||
broadcast(Attribute.FROM_TALKGROUP);
|
||||
|
||||
mFromAlias = null;
|
||||
broadcast(Attribute.FROM_TALKGROUP_ALIAS);
|
||||
|
||||
mToTalkgroup = null;
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
mToAlias = null;
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
|
||||
mCallDetectTalkgroups.clear();
|
||||
|
||||
@@ -496,7 +489,7 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
break;
|
||||
case CALL_TERMINATION_OR_CANCELLATION:
|
||||
/* This opcode as handled at the beginning of the method */
|
||||
/* This opcode as handled at the beginning of the method */
|
||||
break;
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
//TODO: does the activity summary need this message?
|
||||
@@ -2843,7 +2836,7 @@ public class P25DecoderState extends DecoderState
|
||||
patchedTalkgroups = new ArrayList<>();
|
||||
}
|
||||
|
||||
for(String talkgroupToAdd: talkgroupsToAdd)
|
||||
for(String talkgroupToAdd : talkgroupsToAdd)
|
||||
{
|
||||
//Exclude the patch group ID if it is included in the patched talkgroup list so that we don't have
|
||||
//an infinite loop situation
|
||||
@@ -2887,7 +2880,7 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
if(patchedTalkgroups != null)
|
||||
{
|
||||
for(String talkgroupToRemove: talkgroupsToRemove)
|
||||
for(String talkgroupToRemove : talkgroupsToRemove)
|
||||
{
|
||||
if(patchedTalkgroups.contains(talkgroupToRemove))
|
||||
{
|
||||
@@ -2929,7 +2922,7 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
if(existingAlias instanceof PatchGroupAlias)
|
||||
{
|
||||
patchGroupAlias = (PatchGroupAlias)existingAlias;
|
||||
patchGroupAlias = (PatchGroupAlias) existingAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2953,7 +2946,7 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
patchGroupAlias.clearPatchedAliases();
|
||||
|
||||
for(String patchedTalkgroup: patchedTalkgroups)
|
||||
for(String patchedTalkgroup : patchedTalkgroups)
|
||||
{
|
||||
Alias patchedAlias = getAliasList().getTalkgroupAlias(patchedTalkgroup);
|
||||
|
||||
@@ -2974,7 +2967,7 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
if(alias instanceof PatchGroupAlias)
|
||||
{
|
||||
PatchGroupAlias patchGroupAlias = (PatchGroupAlias)alias;
|
||||
PatchGroupAlias patchGroupAlias = (PatchGroupAlias) alias;
|
||||
|
||||
getAliasList().removeAlias(patchGroupAlias);
|
||||
|
||||
@@ -3372,8 +3365,6 @@ public class P25DecoderState extends DecoderState
|
||||
{
|
||||
mToTalkgroup = to;
|
||||
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
mToAlias = getAliasList().getTalkgroupAlias(mToTalkgroup);
|
||||
@@ -3383,14 +3374,10 @@ public class P25DecoderState extends DecoderState
|
||||
mToAlias = null;
|
||||
}
|
||||
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
|
||||
/* Send audio metadata update */
|
||||
broadcast(new Metadata(MetadataType.TO, mToTalkgroup, mToAlias, true));
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToAlias));
|
||||
|
||||
if(mCurrentCallEvent != null &&
|
||||
(mCurrentCallEvent.getToID() == null ||
|
||||
!mCurrentCallEvent.getToID().contentEquals(to)))
|
||||
(mCurrentCallEvent.getToID() == null || !mCurrentCallEvent.getToID().contentEquals(to)))
|
||||
{
|
||||
mCurrentCallEvent.setToID(to);
|
||||
broadcast(mCurrentCallEvent);
|
||||
@@ -3409,7 +3396,6 @@ public class P25DecoderState extends DecoderState
|
||||
if(mFromTalkgroup == null || !mFromTalkgroup.contentEquals(from))
|
||||
{
|
||||
mFromTalkgroup = from;
|
||||
broadcast(Attribute.FROM_TALKGROUP);
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
@@ -3420,14 +3406,11 @@ public class P25DecoderState extends DecoderState
|
||||
mFromAlias = null;
|
||||
}
|
||||
|
||||
broadcast(Attribute.FROM_TALKGROUP_ALIAS);
|
||||
|
||||
/* Send audio metadata update */
|
||||
broadcast(new Metadata(MetadataType.FROM, mFromTalkgroup, mFromAlias, true));
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup,
|
||||
mFromAlias));
|
||||
|
||||
if(mCurrentCallEvent != null &&
|
||||
(mCurrentCallEvent.getFromID() == null ||
|
||||
!mCurrentCallEvent.getFromID().contentEquals(from)))
|
||||
(mCurrentCallEvent.getFromID() == null || !mCurrentCallEvent.getFromID().contentEquals(from)))
|
||||
{
|
||||
mCurrentCallEvent.setFromID(from);
|
||||
broadcast(mCurrentCallEvent);
|
||||
@@ -3437,19 +3420,6 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts an update to the NAC
|
||||
*/
|
||||
private void updateNAC(String nac)
|
||||
{
|
||||
if(mNAC == null || (nac != null && !mNAC.contentEquals(nac)))
|
||||
{
|
||||
mNAC = nac;
|
||||
|
||||
broadcast(Attribute.NAC);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the site information
|
||||
*/
|
||||
@@ -3459,8 +3429,6 @@ public class P25DecoderState extends DecoderState
|
||||
{
|
||||
mSite = site;
|
||||
|
||||
broadcast(Attribute.SITE);
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getSiteID(mSite);
|
||||
@@ -3475,7 +3443,7 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
}
|
||||
|
||||
broadcast(Attribute.SITE_ALIAS);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3484,11 +3452,28 @@ public class P25DecoderState extends DecoderState
|
||||
if(mSystem == null || (system != null && !mSystem.contentEquals(system)))
|
||||
{
|
||||
mSystem = system;
|
||||
|
||||
broadcast(Attribute.SYSTEM);
|
||||
broadcastSystemAndNACUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts an update to the NAC
|
||||
*/
|
||||
private void updateNAC(String nac)
|
||||
{
|
||||
if(mNAC == null || (nac != null && !mNAC.contentEquals(nac)))
|
||||
{
|
||||
mNAC = nac;
|
||||
broadcastSystemAndNACUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastSystemAndNACUpdate()
|
||||
{
|
||||
String label = String.format("SYS:%s NAC:%s", mSystem, mNAC);
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.NETWORK_ID_1, label));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a unit paging event message
|
||||
*/
|
||||
@@ -3816,27 +3801,24 @@ public class P25DecoderState extends DecoderState
|
||||
mCurrentCallEvent = (P25CallEvent) allocationEvent.getCallEvent();
|
||||
|
||||
mCurrentChannel = allocationEvent.getCallEvent().getChannel();
|
||||
broadcast(Attribute.CHANNEL_NUMBER);
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.CHANNEL_FREQUENCY_LABEL, mCurrentChannel));
|
||||
|
||||
mCurrentChannelFrequency = allocationEvent.getCallEvent().getFrequency();
|
||||
broadcast(Attribute.SOURCE);
|
||||
broadcast(new AttributeChangeRequest<Long>(Attribute.CHANNEL_FREQUENCY, mCurrentChannelFrequency));
|
||||
|
||||
mFromTalkgroup = allocationEvent.getCallEvent().getFromID();
|
||||
broadcast(Attribute.FROM_TALKGROUP);
|
||||
|
||||
mToTalkgroup = allocationEvent.getCallEvent().getToID();
|
||||
broadcast(Attribute.TO_TALKGROUP);
|
||||
|
||||
if(allocationEvent.getCallEvent().hasAliasList())
|
||||
{
|
||||
AliasList aliasList = allocationEvent.getCallEvent().getAliasList();
|
||||
|
||||
mFromAlias = aliasList.getTalkgroupAlias(mFromTalkgroup);
|
||||
broadcast(Attribute.FROM_TALKGROUP_ALIAS);
|
||||
|
||||
mToAlias = aliasList.getTalkgroupAlias(mToTalkgroup);
|
||||
broadcast(Attribute.TO_TALKGROUP_ALIAS);
|
||||
}
|
||||
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup, mFromAlias));
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToAlias));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,56 +1,42 @@
|
||||
package module.decode.p25.audio;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketProvider;
|
||||
import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.SquelchState;
|
||||
import channel.metadata.Metadata;
|
||||
import dsp.gain.NonClippingGain;
|
||||
import jmbe.iface.AudioConversionLibrary;
|
||||
import jmbe.iface.AudioConverter;
|
||||
import message.IMessageListener;
|
||||
import message.Message;
|
||||
import module.Module;
|
||||
import module.decode.p25.message.ldu.LDUMessage;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketProvider;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import audio.metadata.IMetadataListener;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.SquelchState;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.IChannelEventListener;
|
||||
import dsp.gain.NonClippingGain;
|
||||
|
||||
public class P25AudioModule extends Module implements Listener<Message>,
|
||||
IAudioPacketProvider, IMessageListener, IChannelEventListener,
|
||||
IMetadataListener, ISquelchStateListener
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class P25AudioModule extends Module implements Listener<Message>, IAudioPacketProvider, IMessageListener,
|
||||
ISquelchStateListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(P25AudioModule.class);
|
||||
|
||||
private static final String IMBE_CODEC = "IMBE";
|
||||
|
||||
/* Provides a unique identifier for this audio module instance to use as a
|
||||
* source identifier for all audio packets */
|
||||
private static int UNIQUE_ID = 0;
|
||||
private int mSourceID;
|
||||
private static boolean mLibraryLoadStatusLogged = false;
|
||||
private boolean mCanConvertAudio = false;
|
||||
private AudioConverter mAudioConverter;
|
||||
private Listener<AudioPacket> mAudioPacketListener;
|
||||
private AudioMetadata mAudioMetadata;
|
||||
private ChannelEventListener mChannelEventListener = new ChannelEventListener();
|
||||
private SquelchStateListener mSquelchStateListener = new SquelchStateListener();
|
||||
private NonClippingGain mGain = new NonClippingGain(5.0f, 0.95f);
|
||||
private Metadata mMetadata;
|
||||
|
||||
public P25AudioModule(boolean record)
|
||||
public P25AudioModule(Metadata metadata)
|
||||
{
|
||||
mSourceID = ++UNIQUE_ID;
|
||||
mAudioMetadata = new AudioMetadata(mSourceID, record);
|
||||
|
||||
mMetadata = metadata;
|
||||
loadConverter();
|
||||
}
|
||||
|
||||
@@ -75,7 +61,6 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mAudioMetadata.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,8 +98,7 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
|
||||
audio = mGain.apply(audio);
|
||||
|
||||
mAudioPacketListener.receive(
|
||||
new AudioPacket(audio, mAudioMetadata.copyOf()));
|
||||
mAudioPacketListener.receive(new AudioPacket(audio, mMetadata.copyOf()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,41 +195,6 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
mAudioPacketListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<Metadata> getMetadataListener()
|
||||
{
|
||||
return mAudioMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<ChannelEvent> getChannelEventListener()
|
||||
{
|
||||
return mChannelEventListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for channel event listener. Responds to channel state reset
|
||||
* events to remove/cleanup current audio metadata
|
||||
*/
|
||||
public class ChannelEventListener implements Listener<ChannelEvent>
|
||||
{
|
||||
@Override
|
||||
public void receive(ChannelEvent event)
|
||||
{
|
||||
switch (event.getEvent())
|
||||
{
|
||||
case NOTIFICATION_STATE_RESET:
|
||||
mAudioMetadata.reset();
|
||||
break;
|
||||
case NOTIFICATION_SELECTION_CHANGE:
|
||||
mAudioMetadata.setSelected(event.getChannel().isSelected());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for squelch state listener. Internally, the P25 audio module
|
||||
* doesn't have a squelch state. If there are IMBE audio frames, we have
|
||||
@@ -259,10 +208,7 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
{
|
||||
if (state == SquelchState.SQUELCH && mAudioPacketListener != null)
|
||||
{
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END,
|
||||
mAudioMetadata.copyOf()));
|
||||
|
||||
mAudioMetadata.reset();
|
||||
mAudioPacketListener.receive(new AudioPacket(AudioPacket.Type.END, mMetadata.copyOf()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,225 +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 module.decode.passport;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class PassportDecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel mProtocol = new JLabel("Passport");
|
||||
private JLabel mToTalkgroup = new JLabel();
|
||||
private JLabel mToTalkgroupAlias = new JLabel();
|
||||
|
||||
private JLabel mSiteAndChannel = new JLabel("Site:");
|
||||
private JLabel mFromTalkgroup = new JLabel();
|
||||
private JLabel mFromTalkgroupAlias = new JLabel();
|
||||
|
||||
public PassportDecoderPanel(IconManager iconManager, SettingsManager settingsManager, PassportDecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
mProtocol.setFont(mFontDecoder);
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToTalkgroup.setFont(mFontDecoder);
|
||||
mToTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mToTalkgroupAlias.setFont(mFontDecoder);
|
||||
mToTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
mSiteAndChannel.setFont(mFontDecoder);
|
||||
mSiteAndChannel.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroup.setFont(mFontDecoder);
|
||||
mFromTalkgroup.setForeground(mColorLabelDecoder);
|
||||
|
||||
mFromTalkgroupAlias.setFont(mFontDecoder);
|
||||
mFromTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
|
||||
add(mProtocol);
|
||||
add(mToTalkgroup);
|
||||
add(mToTalkgroupAlias, "wrap");
|
||||
|
||||
add(mSiteAndChannel);
|
||||
add(mFromTalkgroup);
|
||||
add(mFromTalkgroupAlias, "wrap");
|
||||
}
|
||||
|
||||
public PassportDecoderState getDecoderState()
|
||||
{
|
||||
return (PassportDecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
PassportDecoderState state = getDecoderState();
|
||||
|
||||
switch(attribute)
|
||||
{
|
||||
case TO_TALKGROUP:
|
||||
String tg = state.getTalkgroup();
|
||||
|
||||
if(tg != null)
|
||||
{
|
||||
mToTalkgroup.setText("TG:" + tg);
|
||||
}
|
||||
else
|
||||
{
|
||||
mToTalkgroup.setText(null);
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias toAlias = state.getTalkgroupAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
mToTalkgroupAlias.setText(toAlias.getName());
|
||||
|
||||
mToTalkgroupAlias.setIcon(mIconManager.getIcon(toAlias.getIconName(), IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
mToTalkgroupAlias.setText(null);
|
||||
mToTalkgroupAlias.setIcon(null);
|
||||
}
|
||||
break;
|
||||
case FROM_TALKGROUP:
|
||||
String mid = state.getMobileID();
|
||||
|
||||
if(mid != null)
|
||||
{
|
||||
mFromTalkgroup.setText("MIN:" + mid);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromTalkgroup.setText(null);
|
||||
}
|
||||
break;
|
||||
case FROM_TALKGROUP_ALIAS:
|
||||
Alias fromAlias = state.getMobileIDAlias();
|
||||
|
||||
if(fromAlias != null)
|
||||
{
|
||||
mFromTalkgroupAlias.setText(fromAlias.getName());
|
||||
|
||||
mFromTalkgroupAlias.setIcon(mIconManager
|
||||
.getIcon(fromAlias.getIconName(), IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromTalkgroupAlias.setText(null);
|
||||
mFromTalkgroupAlias.setIcon(null);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_NUMBER:
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Site: ");
|
||||
sb.append(state.getSiteNumber());
|
||||
sb.append("/");
|
||||
sb.append(state.getChannelNumber());
|
||||
|
||||
mSiteAndChannel.setText(sb.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting colorSetting = (ColorSetting) setting;
|
||||
|
||||
switch(colorSetting.getColorSettingName())
|
||||
{
|
||||
case CHANNEL_STATE_LABEL_DECODER:
|
||||
if(mColorLabelDecoder != null)
|
||||
{
|
||||
if(mProtocol != null)
|
||||
{
|
||||
mProtocol.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mToTalkgroup != null)
|
||||
{
|
||||
mToTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mToTalkgroupAlias != null)
|
||||
{
|
||||
mToTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mSiteAndChannel != null)
|
||||
{
|
||||
mSiteAndChannel.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mFromTalkgroup != null)
|
||||
{
|
||||
mFromTalkgroup.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
if(mFromTalkgroupAlias != null)
|
||||
{
|
||||
mFromTalkgroupAlias.setForeground(mColorLabelDecoder);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,180 +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 module.decode.tait;
|
||||
|
||||
import alias.Alias;
|
||||
import icon.IconManager;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Tait1200DecoderPanel extends DecoderPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PROTOCOL = "TAIT-1200";
|
||||
|
||||
private JLabel mFromLabel = new JLabel(" ");
|
||||
private JLabel mFrom = new JLabel();
|
||||
private JLabel mFromAlias = new JLabel();
|
||||
|
||||
private JLabel mToLabel = new JLabel();
|
||||
private JLabel mTo = new JLabel(" ");
|
||||
private JLabel mToAlias = new JLabel();
|
||||
|
||||
private JLabel mProtocol = new JLabel(PROTOCOL);
|
||||
private JLabel mMessage = new JLabel();
|
||||
private JLabel mMessageType = new JLabel();
|
||||
|
||||
public Tait1200DecoderPanel(IconManager iconManager, SettingsManager settingsManager, Tait1200DecoderState decoderState)
|
||||
{
|
||||
super(iconManager, settingsManager, decoderState);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public Tait1200DecoderState getDecoderState()
|
||||
{
|
||||
return (Tait1200DecoderState) super.getDecoderState();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
/* Calling super init will get and broadcast color settings to properly
|
||||
* setup the jlabel colors */
|
||||
super.init();
|
||||
|
||||
setLayout(new MigLayout("insets 1 0 0 0", "[grow,fill]", "[]0[]0[]"));
|
||||
|
||||
add(mFromLabel);
|
||||
add(mFrom);
|
||||
add(mFromAlias, "wrap");
|
||||
|
||||
add(mToLabel);
|
||||
add(mTo);
|
||||
add(mToAlias, "wrap");
|
||||
|
||||
add(mProtocol);
|
||||
add(mMessageType);
|
||||
add(mMessage, "wrap");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(final Attribute attribute)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
switch(attribute)
|
||||
{
|
||||
case FROM_TALKGROUP:
|
||||
String from = getDecoderState().getFromID();
|
||||
|
||||
if(from != null)
|
||||
{
|
||||
mFromLabel.setText("FM:");
|
||||
}
|
||||
else
|
||||
{
|
||||
mFromLabel.setText(" ");
|
||||
}
|
||||
mFrom.setText(from);
|
||||
break;
|
||||
case FROM_TALKGROUP_ALIAS:
|
||||
Alias fromAlias = getDecoderState().getFromIDAlias();
|
||||
|
||||
if(fromAlias != null)
|
||||
{
|
||||
mFromAlias.setText(fromAlias.getName());
|
||||
}
|
||||
break;
|
||||
case TO_TALKGROUP:
|
||||
String to = getDecoderState().getToID();
|
||||
|
||||
if(to != null)
|
||||
{
|
||||
mToLabel.setText("TO:");
|
||||
}
|
||||
else
|
||||
{
|
||||
mToLabel.setText(" ");
|
||||
}
|
||||
mTo.setText(to);
|
||||
break;
|
||||
case TO_TALKGROUP_ALIAS:
|
||||
Alias toAlias = getDecoderState().getToIDAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
mToAlias.setText(toAlias.getName());
|
||||
}
|
||||
break;
|
||||
case MESSAGE:
|
||||
mMessage.setText(getDecoderState().getMessage());
|
||||
break;
|
||||
case MESSAGE_TYPE:
|
||||
mMessageType.setText(getDecoderState().getMessageType());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
super.settingChanged(setting);
|
||||
|
||||
if(setting instanceof ColorSetting)
|
||||
{
|
||||
ColorSetting color = (ColorSetting) setting;
|
||||
|
||||
if(color.getColorSettingName() ==
|
||||
ColorSettingName.CHANNEL_STATE_LABEL_AUX_DECODER)
|
||||
{
|
||||
mFromLabel.setForeground(color.getColor());
|
||||
mFrom.setForeground(color.getColor());
|
||||
mFromAlias.setForeground(color.getColor());
|
||||
mToLabel.setForeground(color.getColor());
|
||||
mTo.setForeground(color.getColor());
|
||||
mToAlias.setForeground(color.getColor());
|
||||
mProtocol.setForeground(color.getColor());
|
||||
mMessageType.setForeground(color.getColor());
|
||||
mMessage.setForeground(color.getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,268 +1,288 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 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-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 module.decode.tait;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import channel.state.State;
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
import util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.state.DecoderState;
|
||||
import channel.state.DecoderStateEvent;
|
||||
import channel.state.State;
|
||||
import channel.state.DecoderStateEvent.Event;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
public class Tait1200DecoderState extends DecoderState
|
||||
{
|
||||
private TreeSet<String> mIdents = new TreeSet<String>();
|
||||
|
||||
private String mFrom;
|
||||
private Alias mFromAlias;
|
||||
private TreeSet<String> mIdents = new TreeSet<String>();
|
||||
|
||||
private String mTo;
|
||||
private Alias mToAlias;
|
||||
private String mFrom;
|
||||
private Alias mFromAlias;
|
||||
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
private String mTo;
|
||||
private Alias mToAlias;
|
||||
|
||||
public Tait1200DecoderState( AliasList aliasList )
|
||||
{
|
||||
super( aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.TAIT_1200;
|
||||
}
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mIdents.clear();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
setFromID( null );
|
||||
setFromIDAlias( null );
|
||||
setToID( null );
|
||||
setToIDAlias( null );
|
||||
setMessage( null );
|
||||
setMessageType( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
public Tait1200DecoderState(AliasList aliasList)
|
||||
{
|
||||
if( message instanceof Tait1200GPSMessage )
|
||||
{
|
||||
Tait1200GPSMessage gps = (Tait1200GPSMessage)message;
|
||||
|
||||
setFromID( gps.getFromID() );
|
||||
setFromIDAlias( gps.getFromIDAlias() );
|
||||
mIdents.add( gps.getFromID() );
|
||||
|
||||
setToID( gps.getToID() );
|
||||
setToIDAlias( gps.getToIDAlias() );
|
||||
mIdents.add( gps.getToID());
|
||||
|
||||
GeoPosition position = gps.getGPSLocation();
|
||||
|
||||
if( position != null )
|
||||
{
|
||||
setMessage( gps.getGPSLocation().toString().replace( "[", "" )
|
||||
.replace( "]", "" ) );
|
||||
}
|
||||
|
||||
setMessageType( "GPS" );
|
||||
|
||||
broadcast( new Tait1200CallEvent( CallEventType.GPS, getAliasList(),
|
||||
gps.getFromID(), gps.getToID(), gps.getGPSLocation().toString() ) );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.DATA ) );
|
||||
}
|
||||
else if( message instanceof Tait1200ANIMessage )
|
||||
{
|
||||
Tait1200ANIMessage ani = (Tait1200ANIMessage)message;
|
||||
|
||||
setFromID( ani.getFromID() );
|
||||
setFromIDAlias( ani.getFromIDAlias() );
|
||||
mIdents.add( ani.getFromID() );
|
||||
|
||||
setToID( ani.getToID() );
|
||||
setToIDAlias( ani.getToIDAlias() );
|
||||
mIdents.add( ani.getToID());
|
||||
|
||||
setMessage( null );
|
||||
setMessageType( "ANI" );
|
||||
|
||||
broadcast( new Tait1200CallEvent( CallEventType.ID_ANI, getAliasList(),
|
||||
ani.getFromID(), ani.getToID(), "ANI" ) );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, State.CALL ) );
|
||||
}
|
||||
super(aliasList);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.TAIT_1200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
mIdents.clear();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
mFrom = null;
|
||||
mFromAlias = null;
|
||||
mTo = null;
|
||||
mToAlias = null;
|
||||
mMessage = null;
|
||||
mMessageType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
if(message instanceof Tait1200GPSMessage)
|
||||
{
|
||||
Tait1200GPSMessage gps = (Tait1200GPSMessage) message;
|
||||
|
||||
setFromID(gps.getFromID());
|
||||
setFromIDAlias(gps.getFromIDAlias());
|
||||
mIdents.add(gps.getFromID());
|
||||
|
||||
setToID(gps.getToID());
|
||||
setToIDAlias(gps.getToIDAlias());
|
||||
mIdents.add(gps.getToID());
|
||||
|
||||
GeoPosition position = gps.getGPSLocation();
|
||||
|
||||
if(position != null)
|
||||
{
|
||||
setMessage(gps.getGPSLocation().toString().replace("[", "")
|
||||
.replace("]", ""));
|
||||
}
|
||||
|
||||
setMessageType("GPS");
|
||||
|
||||
broadcast(new Tait1200CallEvent(CallEventType.GPS, getAliasList(),
|
||||
gps.getFromID(), gps.getToID(), gps.getGPSLocation().toString()));
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.DATA));
|
||||
}
|
||||
else if(message instanceof Tait1200ANIMessage)
|
||||
{
|
||||
Tait1200ANIMessage ani = (Tait1200ANIMessage) message;
|
||||
|
||||
setFromID(ani.getFromID());
|
||||
setFromIDAlias(ani.getFromIDAlias());
|
||||
mIdents.add(ani.getFromID());
|
||||
|
||||
setToID(ani.getToID());
|
||||
setToIDAlias(ani.getToIDAlias());
|
||||
mIdents.add(ani.getToID());
|
||||
|
||||
setMessage(null);
|
||||
setMessageType("ANI");
|
||||
|
||||
broadcast(new Tait1200CallEvent(CallEventType.ID_ANI, getAliasList(),
|
||||
ani.getFromID(), ani.getToID(), "ANI"));
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.CALL));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "=============================\n" );
|
||||
sb.append( "Decoder:\tTait-1200I\n\n" );
|
||||
|
||||
if( !mIdents.isEmpty() )
|
||||
{
|
||||
sb.append( "Radio Identifiers:\n" );
|
||||
|
||||
List<String> idents = new ArrayList<String>( mIdents );
|
||||
|
||||
Collections.sort( idents );
|
||||
|
||||
for( String ident: idents )
|
||||
{
|
||||
sb.append( "\t" );
|
||||
sb.append( ident );
|
||||
|
||||
if( hasAliasList() )
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias( ident );
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( "\t" );
|
||||
sb.append( alias.getName() );
|
||||
}
|
||||
}
|
||||
sb.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
sb.append("=============================\n");
|
||||
sb.append("Decoder:\tTait-1200I\n\n");
|
||||
|
||||
if(!mIdents.isEmpty())
|
||||
{
|
||||
sb.append("Radio Identifiers:\n");
|
||||
|
||||
List<String> idents = new ArrayList<String>(mIdents);
|
||||
|
||||
Collections.sort(idents);
|
||||
|
||||
for(String ident : idents)
|
||||
{
|
||||
sb.append("\t");
|
||||
sb.append(ident);
|
||||
|
||||
if(hasAliasList())
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias(ident);
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
sb.append("\t");
|
||||
sb.append(alias.getName());
|
||||
}
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization required */
|
||||
}
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
/* No initialization required */
|
||||
}
|
||||
|
||||
/**
|
||||
* Responds to reset events issued by the channel state
|
||||
*/
|
||||
@Override
|
||||
public void receiveDecoderStateEvent( DecoderStateEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public String getFromID()
|
||||
{
|
||||
return mFrom;
|
||||
}
|
||||
|
||||
public void setFromID( String from )
|
||||
{
|
||||
mFrom = from;
|
||||
broadcast( Attribute.FROM_TALKGROUP );
|
||||
}
|
||||
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return mFromAlias;
|
||||
}
|
||||
/**
|
||||
* Responds to reset events issued by the channel state
|
||||
*/
|
||||
@Override
|
||||
public void receiveDecoderStateEvent(DecoderStateEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFromIDAlias( Alias alias )
|
||||
{
|
||||
mFromAlias = alias;
|
||||
broadcast( Attribute.FROM_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
{
|
||||
return mTo;
|
||||
}
|
||||
|
||||
public void setToID( String to )
|
||||
{
|
||||
mTo = to;
|
||||
broadcast( Attribute.TO_TALKGROUP );
|
||||
}
|
||||
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return mToAlias;
|
||||
}
|
||||
|
||||
public void setToIDAlias( Alias alias )
|
||||
{
|
||||
mToAlias = alias;
|
||||
broadcast( Attribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
public String getFromID()
|
||||
{
|
||||
return mFrom;
|
||||
}
|
||||
|
||||
public void setMessage( String message )
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast( Attribute.MESSAGE );
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
public void setFromID(String from)
|
||||
{
|
||||
if(!StringUtils.isEqual(mFrom, from))
|
||||
{
|
||||
mFrom = from;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_FROM, getFromID(), getFromIDAlias()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setMessageType( String type )
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast( Attribute.MESSAGE_TYPE );
|
||||
}
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return mFromAlias;
|
||||
}
|
||||
|
||||
public void setFromIDAlias(Alias alias)
|
||||
{
|
||||
if(mFromAlias == null || (alias != null && mFromAlias != alias))
|
||||
{
|
||||
mFromAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_FROM, getFromID(), getFromIDAlias()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
{
|
||||
return mTo;
|
||||
}
|
||||
|
||||
public void setToID(String to)
|
||||
{
|
||||
if(!StringUtils.isEqual(mTo, to))
|
||||
{
|
||||
mTo = to;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, getToID(), getToIDAlias()));
|
||||
}
|
||||
}
|
||||
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return mToAlias;
|
||||
}
|
||||
|
||||
public void setToIDAlias(Alias alias)
|
||||
{
|
||||
if(mToAlias == null || (alias != null && mToAlias != alias))
|
||||
{
|
||||
mToAlias = alias;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.SECONDARY_ADDRESS_TO, getToID(), getToIDAlias()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public void setMessage(String message)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessage, message))
|
||||
{
|
||||
mMessage = message;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE, getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageType()
|
||||
{
|
||||
return mMessageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String type)
|
||||
{
|
||||
if(!StringUtils.isEqual(mMessageType, type))
|
||||
{
|
||||
mMessageType = type;
|
||||
broadcast(new AttributeChangeRequest<String>(Attribute.MESSAGE_TYPE, getMessageType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ package record;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketListener;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
import module.Module;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -49,7 +49,7 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
|
||||
protected Path mPath;
|
||||
protected AudioMetadata mAudioMetadata;
|
||||
protected Metadata mMetadata;
|
||||
protected long mTimeRecordingStart;
|
||||
protected long mTimeLastPacketReceived;
|
||||
private BufferProcessor mBufferProcessor;
|
||||
@@ -79,9 +79,9 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
/**
|
||||
* Latest audio metadata received for this recording
|
||||
*/
|
||||
public AudioMetadata getMetadata()
|
||||
public Metadata getMetadata()
|
||||
{
|
||||
return mAudioMetadata;
|
||||
return mMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +119,7 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the audio packet and captures the latest AudioMetadata for the recording for easy access.
|
||||
* Processes the audio packet and captures the latest Metadata for the recording for easy access.
|
||||
*/
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
@@ -129,14 +129,14 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
mTimeRecordingStart = System.currentTimeMillis();
|
||||
mTimeLastPacketReceived = mTimeRecordingStart;
|
||||
|
||||
if(audioPacket.hasAudioMetadata())
|
||||
if(audioPacket.hasMetadata())
|
||||
{
|
||||
mAudioMetadata = audioPacket.getAudioMetadata();
|
||||
mMetadata = audioPacket.getMetadata();
|
||||
}
|
||||
|
||||
boolean success = mAudioPacketQueue.offer(audioPacket);
|
||||
|
||||
if (!success)
|
||||
if(!success)
|
||||
{
|
||||
mLog.error("recorder buffer overflow - stopping recorder [" + getPath().toString() + "]");
|
||||
stop();
|
||||
@@ -189,11 +189,11 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
*/
|
||||
public void start(ScheduledExecutorService executor)
|
||||
{
|
||||
if (mRunning.compareAndSet(false, true))
|
||||
if(mRunning.compareAndSet(false, true))
|
||||
{
|
||||
mTimeLastPacketReceived = System.currentTimeMillis();
|
||||
|
||||
if (mBufferProcessor == null)
|
||||
if(mBufferProcessor == null)
|
||||
{
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
/* Schedule the handler to run every half second */
|
||||
mProcessorHandle = executor.scheduleAtFixedRate(mBufferProcessor, 0, 500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (IOException io)
|
||||
catch(IOException io)
|
||||
{
|
||||
mLog.error("Error starting audio recorder [" + getPath().toString() + "]", io);
|
||||
|
||||
@@ -221,13 +221,13 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
{
|
||||
mAudioPacketQueue.drainTo(mPacketsToProcess);
|
||||
|
||||
if (!mPacketsToProcess.isEmpty())
|
||||
if(!mPacketsToProcess.isEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
record(mPacketsToProcess);
|
||||
|
||||
for(AudioPacket packet: mPacketsToProcess)
|
||||
for(AudioPacket packet : mPacketsToProcess)
|
||||
{
|
||||
if(packet.getType() == AudioPacket.Type.AUDIO)
|
||||
{
|
||||
@@ -279,7 +279,7 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
|
||||
public void run()
|
||||
{
|
||||
if (mProcessing.compareAndSet(false, true))
|
||||
if(mProcessing.compareAndSet(false, true))
|
||||
{
|
||||
processAudioPacketQueue();
|
||||
|
||||
@@ -290,14 +290,14 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
//Allow sub-classes to flush remaining audio frame data to disk.
|
||||
flush();
|
||||
|
||||
if (mFileOutputStream != null)
|
||||
if(mFileOutputStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
mFileOutputStream.flush();
|
||||
mFileOutputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
catch(IOException e)
|
||||
{
|
||||
mLog.error("Error closing output stream", e);
|
||||
}
|
||||
@@ -308,7 +308,7 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
|
||||
mRecordingClosedListener.receive(AudioRecorder.this);
|
||||
}
|
||||
|
||||
if (mProcessorHandle != null)
|
||||
if(mProcessorHandle != null)
|
||||
{
|
||||
mProcessorHandle.cancel(false);
|
||||
mProcessorHandle = null;
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
package record;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -38,7 +37,7 @@ public class RecorderManager implements Listener<AudioPacket>
|
||||
|
||||
public static final int AUDIO_SAMPLE_RATE = 8000;
|
||||
|
||||
private Map<String, RealBufferWaveRecorder> mRecorders = new HashMap<>();
|
||||
private Map<String,RealBufferWaveRecorder> mRecorders = new HashMap<>();
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
|
||||
@@ -61,10 +60,10 @@ public class RecorderManager implements Listener<AudioPacket>
|
||||
@Override
|
||||
public void receive(AudioPacket audioPacket)
|
||||
{
|
||||
if(audioPacket.hasAudioMetadata() &&
|
||||
audioPacket.getAudioMetadata().isRecordable())
|
||||
if(audioPacket.hasMetadata() &&
|
||||
audioPacket.getMetadata().isRecordable())
|
||||
{
|
||||
String identifier = audioPacket.getAudioMetadata().getIdentifier();
|
||||
String identifier = audioPacket.getMetadata().getUniqueIdentifier();
|
||||
|
||||
if(mRecorders.containsKey(identifier))
|
||||
{
|
||||
@@ -125,37 +124,18 @@ public class RecorderManager implements Listener<AudioPacket>
|
||||
|
||||
sb.append(File.separator);
|
||||
|
||||
Metadata systemMetadata = packet.getAudioMetadata().getMetadata(MetadataType.SYSTEM);
|
||||
Metadata metadata = packet.getMetadata();
|
||||
|
||||
sb.append(systemMetadata != null ? systemMetadata.getValue() : "UNKNOWN_SYSTEM");
|
||||
sb.append(metadata.getNetworkID1().hasIdentifier() ? metadata.getNetworkID1().getIdentifier() + "_" : "SYSTEM-SITE");
|
||||
sb.append(metadata.getNetworkID1().hasIdentifier() ? metadata.getNetworkID1().getIdentifier() : "CHANNEL");
|
||||
|
||||
Metadata toMetadata = packet.getAudioMetadata().getMetadata(MetadataType.TO);
|
||||
|
||||
if(toMetadata != null)
|
||||
if(metadata.getPrimaryAddressTo().hasIdentifier())
|
||||
{
|
||||
sb.append("_TO_").append(toMetadata.getValue());
|
||||
sb.append("_TO_").append(metadata.getPrimaryAddressTo().getIdentifier());
|
||||
|
||||
Metadata fromMetadata = packet.getAudioMetadata().getMetadata(MetadataType.FROM);
|
||||
|
||||
if(fromMetadata != null)
|
||||
if(metadata.getPrimaryAddressFrom().hasIdentifier())
|
||||
{
|
||||
sb.append("_FROM_").append(fromMetadata.getValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Metadata siteMetadata = packet.getAudioMetadata().getMetadata(MetadataType.SITE_ID);
|
||||
|
||||
if(siteMetadata != null)
|
||||
{
|
||||
sb.append("_").append(siteMetadata.getValue());
|
||||
}
|
||||
|
||||
Metadata channelMetadata = packet.getAudioMetadata().getMetadata(MetadataType.CHANNEL_NAME);
|
||||
|
||||
if(channelMetadata != null)
|
||||
{
|
||||
sb.append("_").append(channelMetadata.getValue());
|
||||
sb.append("_FROM_").append(metadata.getPrimaryAddressFrom().getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* 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
|
||||
@@ -20,7 +20,7 @@ package record.wave;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketListener;
|
||||
import audio.metadata.AudioMetadata;
|
||||
import channel.metadata.Metadata;
|
||||
import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.nio.file.Path;
|
||||
|
||||
public class AudioPacketMonoWaveReader extends MonoWaveReader implements Listener<RealBuffer>
|
||||
{
|
||||
private AudioMetadata mMetadata = new AudioMetadata(0, false);
|
||||
private Metadata mMetadata = new Metadata();
|
||||
|
||||
private IAudioPacketListener mListener;
|
||||
|
||||
@@ -40,7 +40,6 @@ public class AudioPacketMonoWaveReader extends MonoWaveReader implements Listene
|
||||
* @param realTime causes the read() method to read and dispatch audio packets in real time. Note: when using
|
||||
* real time playback, the thread calling the read() method will sleep as needed to effect real-time playback,
|
||||
* therefore you should invoke read() on a separate thread if this will impact the calling thread.
|
||||
*
|
||||
* @throws IOException on any file IO errors
|
||||
*/
|
||||
public AudioPacketMonoWaveReader(Path path, boolean realTime) throws IOException
|
||||
@@ -49,7 +48,7 @@ public class AudioPacketMonoWaveReader extends MonoWaveReader implements Listene
|
||||
setListener(this);
|
||||
}
|
||||
|
||||
public void setMetadata(AudioMetadata metadata)
|
||||
public void setMetadata(Metadata metadata)
|
||||
{
|
||||
mMetadata = metadata;
|
||||
}
|
||||
|
||||
41
src/util/StringUtils.java
Normal file
41
src/util/StringUtils.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* 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 util;
|
||||
|
||||
public class StringUtils
|
||||
{
|
||||
/**
|
||||
* Compares string a to b and returns true if a is non-null and non-empty, b is non-null and non-empty, and
|
||||
* a is equal to b.
|
||||
* @param a string to compare
|
||||
* @param b string to compare
|
||||
*/
|
||||
public static boolean isEqual(String a, String b)
|
||||
{
|
||||
return !isEmpty(a) && !isEmpty(b) && a.equals(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the string for null or empty condition
|
||||
*/
|
||||
public static boolean isEmpty(String a)
|
||||
{
|
||||
return a == null || a.isEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user