@@ -94,11 +743,11 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/src/main/java/io/github/dsheirer/alias/Alias.java b/src/main/java/io/github/dsheirer/alias/Alias.java
index 588995cd..cd50e0db 100644
--- a/src/main/java/io/github/dsheirer/alias/Alias.java
+++ b/src/main/java/io/github/dsheirer/alias/Alias.java
@@ -1,20 +1,22 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -24,10 +26,10 @@ import io.github.dsheirer.alias.action.AliasAction;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.AliasIDType;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
import io.github.dsheirer.alias.id.priority.Priority;
+import io.github.dsheirer.alias.id.record.Record;
-import java.awt.*;
+import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -187,7 +189,7 @@ public class Alias
* Returns the priority level of this alias, if defined, or the default priority
*/
@JsonIgnore
- public int getCallPriority()
+ public int getPlaybackPriority()
{
for(AliasID id : mAliasIDs)
{
@@ -245,27 +247,39 @@ public class Alias
{
for(AliasID id : getId())
{
- if(id.getType() == AliasIDType.NON_RECORDABLE)
+ if(id.getType() == AliasIDType.RECORD)
{
- return false;
+ return true;
}
}
- return true;
+ return false;
}
/**
- * Sets or removes the non-recordable alias ID for this alias.
+ * Sets or removes the record alias ID for this alias.
*/
public void setRecordable(boolean recordable)
{
if(recordable)
+ {
+ for(AliasID id : getId())
+ {
+ if(id.getType() == AliasIDType.RECORD)
+ {
+ return;
+ }
+ }
+
+ addAliasID(new Record());
+ }
+ else
{
AliasID toRemove = null;
for(AliasID id : getId())
{
- if(id.getType() == AliasIDType.NON_RECORDABLE)
+ if(id.getType() == AliasIDType.RECORD)
{
toRemove = id;
break;
@@ -277,18 +291,6 @@ public class Alias
removeAliasID(toRemove);
}
}
- else
- {
- for(AliasID id : getId())
- {
- if(id.getType() == AliasIDType.NON_RECORDABLE)
- {
- return;
- }
- }
-
- addAliasID(new NonRecordable());
- }
}
/**
diff --git a/src/main/java/io/github/dsheirer/alias/AliasFactory.java b/src/main/java/io/github/dsheirer/alias/AliasFactory.java
index ad28d053..102007cb 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasFactory.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasFactory.java
@@ -1,20 +1,22 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias;
import io.github.dsheirer.alias.action.AliasAction;
@@ -31,26 +33,32 @@ import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannelEditor;
import io.github.dsheirer.alias.id.esn.ESNEditor;
import io.github.dsheirer.alias.id.esn.Esn;
-import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
-import io.github.dsheirer.alias.id.fleetsync.FleetsyncIDEditor;
+import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
+import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncIDEditor;
+import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
+import io.github.dsheirer.alias.id.legacy.mdc.MDC1200IDEditor;
+import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
+import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327IDEditor;
+import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
+import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordableEditor;
+import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
+import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupIDEditor;
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
import io.github.dsheirer.alias.id.lojack.LoJackIDEditor;
-import io.github.dsheirer.alias.id.mdc.MDC1200ID;
-import io.github.dsheirer.alias.id.mdc.MDC1200IDEditor;
import io.github.dsheirer.alias.id.mobileID.MINEditor;
import io.github.dsheirer.alias.id.mobileID.Min;
-import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
-import io.github.dsheirer.alias.id.mpt1327.MPT1327IDEditor;
-import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
-import io.github.dsheirer.alias.id.nonrecordable.NonRecordableEditor;
import io.github.dsheirer.alias.id.priority.Priority;
import io.github.dsheirer.alias.id.priority.PriorityEditor;
+import io.github.dsheirer.alias.id.record.Record;
+import io.github.dsheirer.alias.id.record.RecordEditor;
import io.github.dsheirer.alias.id.siteID.SiteID;
import io.github.dsheirer.alias.id.siteID.SiteIDEditor;
import io.github.dsheirer.alias.id.status.StatusID;
import io.github.dsheirer.alias.id.status.StatusIDEditor;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupIDEditor;
+import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
+import io.github.dsheirer.alias.id.talkgroup.TalkgroupEditor;
+import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
+import io.github.dsheirer.alias.id.talkgroup.TalkgroupRangeEditor;
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
import io.github.dsheirer.alias.id.uniqueID.UniqueIDEditor;
import io.github.dsheirer.audio.broadcast.BroadcastModel;
@@ -59,246 +67,255 @@ import io.github.dsheirer.gui.editor.EmptyEditor;
public class AliasFactory
{
- public static AliasID copyOf( AliasID id )
- {
- switch( id.getType() )
- {
- case BROADCAST_CHANNEL:
- BroadcastChannel originalBroadcast = (BroadcastChannel)id;
- BroadcastChannel copyBroadcast = new BroadcastChannel();
- copyBroadcast.setChannelName(originalBroadcast.getChannelName());
- return copyBroadcast;
- case ESN:
- Esn originalESN = (Esn)id;
- Esn copyESN = new Esn();
- copyESN.setEsn( originalESN.getEsn() );
- return copyESN;
- case FLEETSYNC:
- FleetsyncID originalFleetsyncID = (FleetsyncID)id;
- FleetsyncID copyFleetsyncID = new FleetsyncID();
- copyFleetsyncID.setIdent( originalFleetsyncID.getIdent() );
- return copyFleetsyncID;
- case LTR_NET_UID:
- UniqueID originalUniqueID = (UniqueID)id;
- UniqueID copyUniqueID = new UniqueID();
- copyUniqueID.setUid( originalUniqueID.getUid() );
- return copyUniqueID;
- case LOJACK:
- LoJackFunctionAndID originalLoJackFunctionAndID = (LoJackFunctionAndID)id;
- LoJackFunctionAndID copyLoJackFunctionAndID = new LoJackFunctionAndID();
- copyLoJackFunctionAndID.setFunction( originalLoJackFunctionAndID.getFunction() );
- copyLoJackFunctionAndID.setID( originalLoJackFunctionAndID.getID() );
- return copyLoJackFunctionAndID;
- case MDC1200:
- MDC1200ID originalMDC1200ID = (MDC1200ID)id;
- MDC1200ID copyMDC1200ID = new MDC1200ID();
- copyMDC1200ID.setIdent( originalMDC1200ID.getIdent() );
- return copyMDC1200ID;
- case MIN:
- Min originalMin = (Min)id;
- Min copyMin = new Min();
- copyMin.setMin( originalMin.getMin() );
- return copyMin;
- case MPT1327:
- MPT1327ID originalMPT1327ID = (MPT1327ID)id;
- MPT1327ID copyMPT1327ID = new MPT1327ID();
- copyMPT1327ID.setIdent( originalMPT1327ID.getIdent() );
- return copyMPT1327ID;
- case NON_RECORDABLE:
- return new NonRecordable();
- case PRIORITY:
- Priority originalPriority = (Priority)id;
- Priority copyPriority = new Priority();
- copyPriority.setPriority( originalPriority.getPriority() );
- return copyPriority;
- case SITE:
- SiteID originalSiteID = (SiteID)id;
- SiteID copySiteID = new SiteID();
- copySiteID.setSite( originalSiteID.getSite() );
- return copySiteID;
- case TALKGROUP:
- TalkgroupID originalTalkgroupID = (TalkgroupID)id;
- TalkgroupID copyTalkgroupID = new TalkgroupID();
- copyTalkgroupID.setTalkgroup( originalTalkgroupID.getTalkgroup() );
- return copyTalkgroupID;
- case STATUS:
- StatusID originalStatusID = (StatusID)id;
- StatusID copyStatusID = new StatusID();
- copyStatusID.setStatus( originalStatusID.getStatus() );
- return copyStatusID;
- default:
- }
+ public static AliasID copyOf(AliasID id)
+ {
+ switch(id.getType())
+ {
+ case BROADCAST_CHANNEL:
+ BroadcastChannel originalBroadcast = (BroadcastChannel)id;
+ BroadcastChannel copyBroadcast = new BroadcastChannel();
+ copyBroadcast.setChannelName(originalBroadcast.getChannelName());
+ return copyBroadcast;
+ case ESN:
+ Esn originalESN = (Esn)id;
+ Esn copyESN = new Esn();
+ copyESN.setEsn(originalESN.getEsn());
+ return copyESN;
+ case LTR_NET_UID:
+ UniqueID originalUniqueID = (UniqueID)id;
+ UniqueID copyUniqueID = new UniqueID();
+ copyUniqueID.setUid(originalUniqueID.getUid());
+ return copyUniqueID;
+ case LOJACK:
+ LoJackFunctionAndID originalLoJackFunctionAndID = (LoJackFunctionAndID)id;
+ LoJackFunctionAndID copyLoJackFunctionAndID = new LoJackFunctionAndID();
+ copyLoJackFunctionAndID.setFunction(originalLoJackFunctionAndID.getFunction());
+ copyLoJackFunctionAndID.setID(originalLoJackFunctionAndID.getID());
+ return copyLoJackFunctionAndID;
+ case MIN:
+ Min originalMin = (Min)id;
+ Min copyMin = new Min();
+ copyMin.setMin(originalMin.getMin());
+ return copyMin;
+ case PRIORITY:
+ Priority originalPriority = (Priority)id;
+ Priority copyPriority = new Priority();
+ copyPriority.setPriority(originalPriority.getPriority());
+ return copyPriority;
+ case RECORD:
+ return new Record();
+ case SITE:
+ SiteID originalSiteID = (SiteID)id;
+ SiteID copySiteID = new SiteID();
+ copySiteID.setSite(originalSiteID.getSite());
+ return copySiteID;
+ case STATUS:
+ StatusID originalStatusID = (StatusID)id;
+ StatusID copyStatusID = new StatusID();
+ copyStatusID.setStatus(originalStatusID.getStatus());
+ return copyStatusID;
+ case TALKGROUP:
+ Talkgroup originalTalkgroup = (Talkgroup)id;
+ Talkgroup copyTalkgroup = new Talkgroup(originalTalkgroup.getProtocol(), originalTalkgroup.getValue());
+ return copyTalkgroup;
+ case TALKGROUP_RANGE:
+ TalkgroupRange originalRange = (TalkgroupRange)id;
+ TalkgroupRange copyRange = new TalkgroupRange(originalRange.getProtocol(), originalRange.getMinTalkgroup(),
+ originalRange.getMaxTalkgroup());
+ return copyRange;
- return null;
- }
-
- public static AliasAction copyOf( AliasAction action )
- {
- if( action instanceof BeepAction )
- {
- return new BeepAction();
- }
- else if( action instanceof ClipAction)
- {
- ClipAction originalClip = (ClipAction)action;
- ClipAction copyClip = new ClipAction();
- copyClip.setInterval( originalClip.getInterval() );
- copyClip.setPath( originalClip.getPath() );
- copyClip.setPeriod( originalClip.getPeriod() );
- return copyClip;
- }
- else if( action instanceof ScriptAction )
- {
- ScriptAction originalScript = (ScriptAction)action;
- ScriptAction copyScript = new ScriptAction();
- copyScript.setInterval( originalScript.getInterval() );
- copyScript.setPeriod( originalScript.getPeriod() );
- copyScript.setScript( originalScript.getScript() );
- return copyScript;
- }
-
- return null;
- }
-
- public static Alias copyOf( Alias original )
- {
- Alias copy = new Alias( original.getName() );
- copy.setList( original.getList() );
- copy.setGroup( original.getGroup() );
- copy.setColor( original.getColor() );
- copy.setIconName( original.getIconName() );
-
- for( AliasID id: original.getId() )
- {
- AliasID copyID = copyOf( id );
-
- if( copyID != null )
- {
- copy.addAliasID( copyID );
- }
- }
+ //Legacy identifiers ... not supported
+ case FLEETSYNC:
+ case LEGACY_TALKGROUP:
+ case MDC1200:
+ case MPT1327:
+ case NON_RECORDABLE:
+ default:
+ }
- for( AliasAction action: original.getAction() )
- {
- AliasAction copyAction = copyOf( action );
-
- if( copyAction != null )
- {
- copy.addAliasAction( copyAction );
- }
- }
-
- return copy;
- }
+ return null;
+ }
+
+ public static AliasAction copyOf(AliasAction action)
+ {
+ if(action instanceof BeepAction)
+ {
+ return new BeepAction();
+ }
+ else if(action instanceof ClipAction)
+ {
+ ClipAction originalClip = (ClipAction)action;
+ ClipAction copyClip = new ClipAction();
+ copyClip.setInterval(originalClip.getInterval());
+ copyClip.setPath(originalClip.getPath());
+ copyClip.setPeriod(originalClip.getPeriod());
+ return copyClip;
+ }
+ else if(action instanceof ScriptAction)
+ {
+ ScriptAction originalScript = (ScriptAction)action;
+ ScriptAction copyScript = new ScriptAction();
+ copyScript.setInterval(originalScript.getInterval());
+ copyScript.setPeriod(originalScript.getPeriod());
+ copyScript.setScript(originalScript.getScript());
+ return copyScript;
+ }
+
+ return null;
+ }
+
+ public static Alias copyOf(Alias original)
+ {
+ Alias copy = new Alias(original.getName());
+ copy.setList(original.getList());
+ copy.setGroup(original.getGroup());
+ copy.setColor(original.getColor());
+ copy.setIconName(original.getIconName());
+
+ for(AliasID id : original.getId())
+ {
+ AliasID copyID = copyOf(id);
+
+ if(copyID != null)
+ {
+ copy.addAliasID(copyID);
+ }
+ }
+
+ for(AliasAction action : original.getAction())
+ {
+ AliasAction copyAction = copyOf(action);
+
+ if(copyAction != null)
+ {
+ copy.addAliasAction(copyAction);
+ }
+ }
+
+ return copy;
+ }
+
+ public static Editor getEditor(AliasID aliasID, BroadcastModel broadcastModel)
+ {
+ if(aliasID != null)
+ {
+ switch(aliasID.getType())
+ {
+ case BROADCAST_CHANNEL:
+ return new BroadcastChannelEditor(aliasID, broadcastModel);
+ case ESN:
+ return new ESNEditor(aliasID);
+ case LTR_NET_UID:
+ return new UniqueIDEditor(aliasID);
+ case LOJACK:
+ return new LoJackIDEditor(aliasID);
+ case MIN:
+ return new MINEditor(aliasID);
+ case PRIORITY:
+ return new PriorityEditor(aliasID);
+ case RECORD:
+ return new RecordEditor(aliasID);
+ case SITE:
+ return new SiteIDEditor(aliasID);
+ case STATUS:
+ return new StatusIDEditor(aliasID);
+ case TALKGROUP:
+ return new TalkgroupEditor(aliasID);
+ case TALKGROUP_RANGE:
+ return new TalkgroupRangeEditor(aliasID);
+
+ case FLEETSYNC:
+ return new FleetsyncIDEditor(aliasID);
+ case LEGACY_TALKGROUP:
+ return new LegacyTalkgroupIDEditor(aliasID);
+ case MDC1200:
+ return new MDC1200IDEditor(aliasID);
+ case MPT1327:
+ return new MPT1327IDEditor(aliasID);
+ case NON_RECORDABLE:
+ return new NonRecordableEditor(aliasID);
+ default:
+ break;
+ }
+ }
+
+ return new EmptyEditor();
+ }
+
+ public static Editor getEditor(AliasAction aliasAction)
+ {
+ if(aliasAction != null)
+ {
+ switch(aliasAction.getType())
+ {
+ case BEEP:
+ return new BeepActionEditor(aliasAction);
+ case CLIP:
+ return new ClipActionEditor(aliasAction);
+ case SCRIPT:
+ return new ScriptActionEditor(aliasAction);
+ default:
+ break;
+ }
+ }
+
+ return new EmptyEditor();
+ }
+
+ public static AliasID getAliasID(AliasIDType type)
+ {
+ switch(type)
+ {
+ case BROADCAST_CHANNEL:
+ return new BroadcastChannel();
+ case ESN:
+ return new Esn();
+ case FLEETSYNC:
+ return new FleetsyncID();
+ case LTR_NET_UID:
+ return new UniqueID();
+ case LOJACK:
+ return new LoJackFunctionAndID();
+ case MDC1200:
+ return new MDC1200ID();
+ case MIN:
+ return new Min();
+ case MPT1327:
+ return new MPT1327ID();
+ case NON_RECORDABLE:
+ return new NonRecordable();
+ case PRIORITY:
+ return new Priority();
+ case RECORD:
+ return new Record();
+ case TALKGROUP:
+ return new Talkgroup();
+ case TALKGROUP_RANGE:
+ return new TalkgroupRange();
+ case SITE:
+ return new SiteID();
+ case STATUS:
+ return new StatusID();
+ case LEGACY_TALKGROUP:
+ return new LegacyTalkgroupID();
+ default:
+ throw new IllegalArgumentException("Unrecognized Alias ID type: " + type);
+ }
+ }
+
+ public static AliasAction getAliasAction(AliasActionType type)
+ {
+ switch(type)
+ {
+ case BEEP:
+ return new BeepAction();
+ case CLIP:
+ return new ClipAction();
+ case SCRIPT:
+ return new ScriptAction();
+ default:
+ throw new IllegalArgumentException("Unrecognized Alias Action type: " + type);
+ }
+ }
- public static Editor getEditor( AliasID aliasID, BroadcastModel broadcastModel )
- {
- if( aliasID != null )
- {
- switch( aliasID.getType() )
- {
- case BROADCAST_CHANNEL:
- return new BroadcastChannelEditor(aliasID, broadcastModel);
- case ESN:
- return new ESNEditor( aliasID );
- case FLEETSYNC:
- return new FleetsyncIDEditor( aliasID );
- case LTR_NET_UID:
- return new UniqueIDEditor( aliasID );
- case LOJACK:
- return new LoJackIDEditor( aliasID );
- case MDC1200:
- return new MDC1200IDEditor( aliasID );
- case MIN:
- return new MINEditor( aliasID );
- case MPT1327:
- return new MPT1327IDEditor( aliasID );
- case NON_RECORDABLE:
- return new NonRecordableEditor( aliasID );
- case PRIORITY:
- return new PriorityEditor( aliasID );
- case SITE:
- return new SiteIDEditor( aliasID );
- case STATUS:
- return new StatusIDEditor( aliasID );
- case TALKGROUP:
- return new TalkgroupIDEditor( aliasID );
- default:
- break;
- }
- }
-
- return new EmptyEditor();
- }
-
- public static Editor getEditor( AliasAction aliasAction )
- {
- if( aliasAction != null )
- {
- switch( aliasAction.getType() )
- {
- case BEEP:
- return new BeepActionEditor( aliasAction );
- case CLIP:
- return new ClipActionEditor( aliasAction );
- case SCRIPT:
- return new ScriptActionEditor( aliasAction );
- default:
- break;
- }
- }
-
- return new EmptyEditor();
- }
-
- public static AliasID getAliasID( AliasIDType type )
- {
- switch( type )
- {
- case BROADCAST_CHANNEL:
- return new BroadcastChannel();
- case ESN:
- return new Esn();
- case FLEETSYNC:
- return new FleetsyncID();
- case LTR_NET_UID:
- return new UniqueID();
- case LOJACK:
- return new LoJackFunctionAndID();
- case MDC1200:
- return new MDC1200ID();
- case MIN:
- return new Min();
- case MPT1327:
- return new MPT1327ID();
- case NON_RECORDABLE:
- return new NonRecordable();
- case PRIORITY:
- return new Priority();
- case SITE:
- return new SiteID();
- case STATUS:
- return new StatusID();
- case TALKGROUP:
- return new TalkgroupID();
- default:
- throw new IllegalArgumentException( "Unrecognized Alias ID type: " + type );
- }
- }
-
- public static AliasAction getAliasAction( AliasActionType type )
- {
- switch( type )
- {
- case BEEP:
- return new BeepAction();
- case CLIP:
- return new ClipAction();
- case SCRIPT:
- return new ScriptAction();
- default:
- throw new IllegalArgumentException( "Unrecognized Alias Action type: " + type );
- }
- }
-
}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasList.java b/src/main/java/io/github/dsheirer/alias/AliasList.java
index b51503bf..a6051822 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasList.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasList.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,24 +15,25 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.WildcardID;
+import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
import io.github.dsheirer.alias.id.esn.Esn;
-import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
-import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
-import io.github.dsheirer.alias.id.mdc.MDC1200ID;
-import io.github.dsheirer.alias.id.mobileID.Min;
-import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
+import io.github.dsheirer.alias.id.priority.Priority;
import io.github.dsheirer.alias.id.siteID.SiteID;
import io.github.dsheirer.alias.id.status.StatusID;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
+import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
-import io.github.dsheirer.module.decode.lj1200.LJ1200Message;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.esn.ESNIdentifier;
+import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
+import io.github.dsheirer.protocol.Protocol;
import io.github.dsheirer.sample.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,31 +43,23 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
public class AliasList implements Listener
{
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
public static final String WILDCARD = "*";
- public static final String REGEX_WILDCARD = ".";
private Map mESN = new HashMap<>();
- private Map mFleetsync = new HashMap<>();
- private Map mLoJack = new HashMap<>();
- private Map mMDC1200 = new HashMap<>();
- private Map mMobileID = new HashMap<>();
- private Map mMPT1327 = new HashMap<>();
private Map mSiteID = new HashMap<>();
private Map mStatus = new HashMap<>();
- private Map mTalkgroup = new HashMap<>();
private Map mUniqueID = new HashMap<>();
private List mESNWildcards = new ArrayList<>();
- private List mMobileIDWildcards = new ArrayList<>();
- private List mFleetsyncWildcards = new ArrayList<>();
- private List mMDC1200Wildcards = new ArrayList<>();
- private List mMPT1327Wildcards = new ArrayList<>();
private List mSiteWildcards = new ArrayList<>();
- private List mTalkgroupWildcards = new ArrayList<>();
+ private boolean mHasAliasActions = false;
+
+ private Map> mTalkgroupProtocolMap = new HashMap<>();
private String mName;
@@ -92,6 +86,11 @@ public class AliasList implements Listener
addAliasID(aliasID, alias);
}
}
+
+ if(alias.hasActions())
+ {
+ mHasAliasActions = true;
+ }
}
/**
@@ -105,6 +104,19 @@ public class AliasList implements Listener
{
switch(id.getType())
{
+ case TALKGROUP:
+ Talkgroup talkgroup = (Talkgroup)id;
+
+ Map protocolMap = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
+
+ if(protocolMap == null)
+ {
+ protocolMap = new TreeMap();
+ mTalkgroupProtocolMap.put(talkgroup.getProtocol(), protocolMap);
+ }
+
+ protocolMap.put(talkgroup.getValue(), alias);
+ break;
case ESN:
String esn = ((Esn) id).getEsn();
@@ -119,65 +131,6 @@ public class AliasList implements Listener
mESN.put(esn, alias);
}
break;
- case FLEETSYNC:
- String fleetsync = ((FleetsyncID) id).getIdent();
-
- if(fleetsync != null)
- {
- if(fleetsync.contains(WILDCARD))
- {
- mFleetsyncWildcards.add(new WildcardID(fleetsync));
- Collections.sort(mFleetsyncWildcards);
- }
-
- mFleetsync.put(fleetsync, alias);
- }
- break;
- case LOJACK:
- mLoJack.put((LoJackFunctionAndID) id, alias);
- break;
- case MDC1200:
- String mdc = ((MDC1200ID) id).getIdent();
-
- if(mdc != null)
- {
- if(mdc.contains(WILDCARD))
- {
- mMDC1200Wildcards.add(new WildcardID(mdc));
- Collections.sort(mMDC1200Wildcards);
- }
-
- mMDC1200.put(mdc, alias);
- }
- break;
- case MPT1327:
- String mpt = ((MPT1327ID) id).getIdent();
-
- if(mpt != null)
- {
- if(mpt.contains(WILDCARD))
- {
- mMPT1327Wildcards.add(new WildcardID(mpt));
- Collections.sort(mMPT1327Wildcards);
- }
-
- mMPT1327.put(mpt, alias);
- }
- break;
- case MIN:
- String min = ((Min) id).getMin();
-
- if(min != null)
- {
- if(min.contains(WILDCARD))
- {
- mMobileIDWildcards.add(new WildcardID(min));
- Collections.sort(mMobileIDWildcards);
- }
-
- mMobileID.put(min, alias);
- }
- break;
case LTR_NET_UID:
mUniqueID.put(((UniqueID) id).getUid(), alias);
break;
@@ -198,20 +151,6 @@ public class AliasList implements Listener
case STATUS:
mStatus.put(((StatusID) id).getStatus(), alias);
break;
- case TALKGROUP:
- String tgid = ((TalkgroupID) id).getTalkgroup();
-
- if(tgid != null)
- {
- if(tgid.contains(WILDCARD))
- {
- mTalkgroupWildcards.add(new WildcardID(tgid));
- Collections.sort(mTalkgroupWildcards);
- }
-
- mTalkgroup.put(tgid, alias);
- }
- break;
case BROADCAST_CHANNEL:
case NON_RECORDABLE:
case PRIORITY:
@@ -279,61 +218,6 @@ public class AliasList implements Listener
mESN.remove(esn);
break;
- case FLEETSYNC:
- String fleetsync = ((FleetsyncID) id).getIdent();
-
- if(fleetsync != null)
- {
- if(fleetsync.contains(WILDCARD))
- {
- removeWildcard(fleetsync, mFleetsyncWildcards);
- }
-
- mFleetsync.remove(fleetsync);
- }
- break;
- case LOJACK:
- mLoJack.remove((LoJackFunctionAndID) id);
- break;
- case MDC1200:
- String mdc = ((MDC1200ID) id).getIdent();
-
- if(mdc != null)
- {
- if(mdc.contains(WILDCARD))
- {
- removeWildcard(mdc, mMDC1200Wildcards);
- }
-
- mMDC1200.remove(mdc);
- }
- break;
- case MPT1327:
- String mpt = ((MPT1327ID) id).getIdent();
-
- if(mpt != null)
- {
- if(mpt.contains(WILDCARD))
- {
- removeWildcard(mpt, mMPT1327Wildcards);
- }
-
- mMPT1327.remove(mpt);
- }
- break;
- case MIN:
- String min = ((Min) id).getMin();
-
- if(min != null)
- {
- if(min.contains(WILDCARD))
- {
- removeWildcard(min, mMobileIDWildcards);
- }
-
- mMobileID.remove(min);
- }
- break;
case LTR_NET_UID:
mUniqueID.remove(((UniqueID) id).getUid());
break;
@@ -343,19 +227,6 @@ public class AliasList implements Listener
case STATUS:
mStatus.remove(((StatusID) id).getStatus());
break;
- case TALKGROUP:
- String tgid = ((TalkgroupID) id).getTalkgroup();
-
- if(tgid != null)
- {
- if(tgid.contains(WILDCARD))
- {
- removeWildcard(tgid, mTalkgroupWildcards);
- }
-
- mTalkgroup.remove(tgid);
- }
- break;
case NON_RECORDABLE:
case PRIORITY:
case BROADCAST_CHANNEL:
@@ -458,162 +329,6 @@ public class AliasList implements Listener
return alias;
}
- /**
- * Lookup alias by fleetsync ID
- */
- public Alias getFleetsyncAlias(String ident)
- {
- Alias alias = null;
-
- if(ident != null)
- {
- alias = mFleetsync.get(ident);
-
- if(alias == null)
- {
- String wildcard = getWildcardMatch(ident, mFleetsyncWildcards);
-
- if(wildcard != null)
- {
- alias = mFleetsync.get(wildcard);
- }
- }
- }
-
- return alias;
- }
-
- /**
- * Lookup alias by lojack function and ID
- */
- public Alias getLoJackAlias(LJ1200Message.Function function, String id)
- {
- if(id != null)
- {
- for(LoJackFunctionAndID lojack : mLoJack.keySet())
- {
- if(lojack.matches(function, id))
- {
- return mLoJack.get(lojack);
- }
- }
- }
-
- return null;
- }
-
- /**
- * Lookup alias by MDC1200 ID
- */
- public Alias getMDC1200Alias(String ident)
- {
- Alias alias = null;
-
- if(ident != null)
- {
- alias = mMDC1200.get(ident);
-
- if(alias == null)
- {
- String wildcard = getWildcardMatch(ident, mMDC1200Wildcards);
-
- if(wildcard != null)
- {
- alias = mMDC1200.get(wildcard);
- }
- }
- }
-
- return alias;
- }
-
- /**
- * Lookup alias by MPT1327 Ident
- */
- public Alias getMPT1327Alias(String ident)
- {
- Alias alias = null;
-
- if(ident != null)
- {
- alias = mMPT1327.get(ident);
-
- if(alias == null)
- {
- String wildcard = getWildcardMatch(ident, mMPT1327Wildcards);
-
- if(wildcard != null)
- {
- alias = mMPT1327.get(wildcard);
- }
- }
- }
-
- return alias;
- }
-
- /**
- * Lookup alias by Mobile ID Number (MIN)
- */
- public Alias getMobileIDNumberAlias(String ident)
- {
- Alias alias = null;
-
- if(ident != null)
- {
- alias = mMobileID.get(ident);
-
- if(alias == null)
- {
- String wildcard = getWildcardMatch(ident, mMobileIDWildcards);
-
- if(wildcard != null)
- {
- alias = mMobileID.get(wildcard);
- }
- }
- }
-
- return alias;
- }
-
- /**
- * Lookup alias by talkgroup
- *
- * @param tgid to use when searching for an alias
- * @param includeWildcards true if you want to additionally search for a matching alias that contains wildcard(s)
- * when there is not a direct match to the TGID.
- */
- public Alias getTalkgroupAlias(String tgid, boolean includeWildcards)
- {
- Alias alias = null;
-
- if(tgid != null)
- {
- alias = mTalkgroup.get(tgid);
-
- if(alias == null && includeWildcards)
- {
- String wildcard = getWildcardMatch(tgid, mTalkgroupWildcards);
-
- if(wildcard != null)
- {
- alias = mTalkgroup.get(wildcard);
- }
- }
- }
-
- return alias;
- }
-
- /**
- * Lookup alias by talkgroup. Defaults to matching to wildcard talkgroups.
- */
- public Alias getTalkgroupAlias(String tgid)
- {
- return getTalkgroupAlias(tgid, true);
- }
-
/**
* Alias list name
*/
@@ -674,4 +389,136 @@ public class AliasList implements Listener
}
}
}
+
+ /**
+ * Returns an optional alias that is associated with the identifier
+ * @param identifier to alias
+ * @return alias or null
+ */
+ public Alias getAlias(Identifier identifier)
+ {
+ if(identifier != null)
+ {
+ switch(identifier.getForm())
+ {
+ case TALKGROUP:
+ TalkgroupIdentifier talkgroup = (TalkgroupIdentifier)identifier;
+ Map protocolMap = mTalkgroupProtocolMap.get(identifier.getProtocol());
+
+ if(protocolMap != null)
+ {
+ return protocolMap.get(talkgroup.getValue());
+ }
+ break;
+ case ESN:
+ if(identifier instanceof ESNIdentifier)
+ {
+ return getESNAlias(((ESNIdentifier)identifier).getValue());
+ }
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Indicates if any of the identifiers contain a broadcast channel for streaming of audio.
+ * @param identifierCollection to inspect
+ * @return true if the identifier collection is designated for streaming to one or more channels.
+ */
+ public boolean isStreamable(IdentifierCollection identifierCollection)
+ {
+ for(Identifier identifier: identifierCollection.getIdentifiers())
+ {
+ Alias alias = getAlias(identifier);
+
+ if(alias != null && alias.isStreamable())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Indicates if any of the identifiers have been identified for recording.
+ * @param identifierCollection to inspect
+ * @return true if recordable.
+ */
+ public boolean isRecordable(IdentifierCollection identifierCollection)
+ {
+ for(Identifier identifier: identifierCollection.getIdentifiers())
+ {
+ Alias alias = getAlias(identifier);
+
+ if(alias != null && alias.isRecordable())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Indicates if any of the aliases in this list have an associated alias action
+ */
+ public boolean hasAliasActions()
+ {
+ return mHasAliasActions;
+ }
+
+ /**
+ * Returns the lowest audio playback priority specified by aliases for identifiers in the
+ * identifier collection.
+ *
+ * @param identifierCollection to inspect for audio priority
+ * @return audio playback priority
+ */
+ public int getAudioPlaybackPriority(IdentifierCollection identifierCollection)
+ {
+ int priority = Priority.DEFAULT_PRIORITY;
+
+ for(Identifier identifier: identifierCollection.getIdentifiers())
+ {
+ Alias alias = getAlias(identifier);
+
+ if(alias != null && alias.getPlaybackPriority() < priority)
+ {
+ priority = alias.getPlaybackPriority();
+ }
+ }
+
+ return priority;
+ }
+
+ /**
+ * Returns a list of streaming broadcast channels specified for any of the identifiers in the collection.
+ *
+ * @return list of broadcast channels or an empty list
+ */
+ public List getBroadcastChannels(IdentifierCollection identifierCollection)
+ {
+ List channels = new ArrayList<>();
+
+ for(Identifier identifier: identifierCollection.getIdentifiers())
+ {
+ Alias alias = getAlias(identifier);
+
+ if(alias != null && alias.isStreamable())
+ {
+ for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels())
+ {
+ if(!channels.contains(broadcastChannel))
+ {
+ channels.add(broadcastChannel);
+ }
+ }
+ }
+ }
+
+ return channels;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasModel.java b/src/main/java/io/github/dsheirer/alias/AliasModel.java
index 2a62f05f..daba8830 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasModel.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasModel.java
@@ -1,23 +1,27 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
@@ -30,7 +34,9 @@ import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
- * Alias Model
+ * Alias Model contains all aliases and is responsible for creation and management of alias lists. Alias lists are a
+ * set of aliases that all share a common alias list name and can be attached to a decoding channel for aliasing
+ * identifiers produced by channel decoder(s).
*/
public class AliasModel extends AbstractTableModel
{
@@ -68,31 +74,69 @@ public class AliasModel extends AbstractTableModel
return null;
}
+ /**
+ * Returns an optional alias list associated with the identifier collection
+ *
+ * @return alias list or null
+ */
+ public AliasList getAliasList(IdentifierCollection identifierCollection)
+ {
+ if(identifierCollection != null)
+ {
+ return getAliasList(identifierCollection.getAliasListConfiguration());
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieves an alias list specified by the alias list configuration identifier
+ *
+ * @param configurationIdentifier containing the name of an alias list
+ * @return alias list or null.
+ */
+ public AliasList getAliasList(AliasListConfigurationIdentifier configurationIdentifier)
+ {
+ if(configurationIdentifier != null && configurationIdentifier.isValid())
+ {
+ return getAliasList(configurationIdentifier.getValue());
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new alias list containing all aliases that match the alias name, or returns a previously created and
+ * cached alias list. Returned alias list is automatically registered as a listener to this model so that any
+ * updates to the list by the user will automatically be reflected in constructed alias lists.
+ */
public AliasList getAliasList(String name)
{
- if(name != null && mAliasListMap.containsKey(name))
+ if(name == null || name.isEmpty())
+ {
+ return new AliasList(name);
+ }
+
+ if(mAliasListMap.containsKey(name))
{
return mAliasListMap.get(name);
}
AliasList aliasList = new AliasList(name);
- if(name != null)
+ for(Alias alias : mAliases)
{
- for(Alias alias : mAliases)
+ if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
{
- if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
- {
- aliasList.addAlias(alias);
- }
+ aliasList.addAlias(alias);
}
-
- mAliasListMap.put(name, aliasList);
-
- //Register the new alias list to receive updates from this model
- addListener(aliasList);
}
+ mAliasListMap.put(name, aliasList);
+
+ //Register the new alias list to receive updates from this model
+ addListener(aliasList);
+
return aliasList;
}
diff --git a/src/main/java/io/github/dsheirer/alias/PatchGroupAlias.java b/src/main/java/io/github/dsheirer/alias/PatchGroupAlias.java
deleted file mode 100644
index 9350fec8..00000000
--- a/src/main/java/io/github/dsheirer/alias/PatchGroupAlias.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.alias;
-
-import io.github.dsheirer.alias.action.AliasAction;
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.alias.id.AliasIDType;
-import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.alias.id.priority.Priority;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class PatchGroupAlias extends Alias
-{
- private final static Logger mLog = LoggerFactory.getLogger(PatchGroupAlias.class);
-
- private Alias mPatchGroupAlias;
- private List mPatchedAliases = new ArrayList<>();
- private List mPatchedTalkgroupIDs = new ArrayList<>();
-
- /**
- * Patch group alias is a single alias for a group of aliases that are temporarily patched together. This will
- * normally be used for patched talkgroups, but could be used with any type of alias identifiers that can be
- * temporarily joined to form a patch group.
- *
- * Alias properties such as recordable, streamable and call priority are an aggregation from the set of patched
- * aliases contained in this patch group alias and the patch group ID alias and where applicable, return the highest
- * value/priority from the group of patched aliases.
- */
- public PatchGroupAlias()
- {
- }
-
- @Override
- public int getColor()
- {
- if(mPatchGroupAlias != null)
- {
- return mPatchGroupAlias.getColor();
- }
-
- return super.getColor();
- }
-
- /**
- * Sets an alias for this patch group ID
- */
- public void setPatchGroupAlias(Alias alias)
- {
- mPatchGroupAlias = alias;
- }
-
- /**
- * Alias for this patch group
- */
- public Alias getPatchGroupAlias()
- {
- return mPatchGroupAlias;
- }
-
- /**
- * Indicates if this patch group has an alias
- */
- public boolean hasPatchGroupAlias()
- {
- return mPatchGroupAlias != null;
- }
-
- /**
- * List of patched aliases contained in this patch group
- */
- public List getPatchedAliases()
- {
- return mPatchedAliases;
- }
-
- /**
- * Removes/clears all patched aliases from this patch alias group
- */
- public void clearPatchedAliases()
- {
- mPatchedAliases.clear();
- }
-
- /**
- * Adds the patched alias to this patch alias group
- */
- public void addPatchedAlias(Alias alias)
- {
- if(alias == PatchGroupAlias.this)
- {
- throw new IllegalArgumentException("Can't add patch group alias to itself - would create an infinite loop");
- }
-
- mPatchedAliases.add(alias);
- }
-
- /**
- * Removes the patched alias from this patch alias group
- */
- public void removePatchedAlias(Alias alias)
- {
- mPatchedAliases.remove(alias);
- }
-
- /**
- * Sets the list of patched talkgroup IDs for this patch group
- */
- public void setPatchedTalkgroupIDs(List talkgroupIDs)
- {
- mPatchedTalkgroupIDs = talkgroupIDs;
- }
-
- /**
- * List of patched talkgroup IDs for this patch group
- */
- public List getPatchedTalkgroupIDs()
- {
- return mPatchedTalkgroupIDs;
- }
-
- @Override
- public String getName()
- {
- if(hasPatchGroupAlias())
- {
- return getPatchGroupAlias().getName();
- }
- else
- {
- for(AliasID id: getId())
- {
- if(id.getType() == AliasIDType.TALKGROUP)
- {
- return "PATCH:" + ((TalkgroupID)id).getTalkgroup();
- }
- }
- }
-
- return "PATCH:****";
- }
-
- @Override
- public List getAction()
- {
- List aliasActions = new ArrayList<>();
-
- if(hasPatchGroupAlias())
- {
- aliasActions.addAll(getPatchGroupAlias().getAction());
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias))
- {
- for(AliasAction action: alias.getAction())
- {
- if(!aliasActions.contains(action))
- {
- aliasActions.add(action);
- }
- }
- }
- }
-
- return aliasActions;
- }
-
- @Override
- public boolean hasActions()
- {
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.hasActions())
- {
- return true;
- }
- }
-
- return hasPatchGroupAlias() && getPatchGroupAlias().hasActions();
- }
-
- /**
- * Returns the highest listenable audio priority defined among the aliases in the group, or returns 'Do Not Monitor'
- * if that is the only priority defined. Otherwise, returns default (100) priority.
- */
- @Override
- public int getCallPriority()
- {
- boolean hasDoNotMonitor = false;
-
- int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY + 1);
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority() && alias.getCallPriority() < highestPriority)
- {
- if(alias.getCallPriority() == Priority.DO_NOT_MONITOR)
- {
- hasDoNotMonitor = true;
- }
- else
- {
- highestPriority = alias.getCallPriority();
- }
- }
- }
-
- if(highestPriority <= Priority.DEFAULT_PRIORITY)
- {
- return highestPriority;
- }
- else if(hasDoNotMonitor)
- {
- return Priority.DO_NOT_MONITOR;
- }
- else
- {
- return Priority.DEFAULT_PRIORITY;
- }
- }
-
- @Override
- public boolean hasCallPriority()
- {
- if(hasPatchGroupAlias() && getPatchGroupAlias().hasCallPriority())
- {
- return true;
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority())
- {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean isRecordable()
- {
- if(hasPatchGroupAlias() && getPatchGroupAlias().isRecordable())
- {
- return true;
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.isRecordable())
- {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean isStreamable()
- {
- if(hasPatchGroupAlias() && getPatchGroupAlias().isStreamable())
- {
- return true;
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.isStreamable())
- {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public Set getBroadcastChannels()
- {
- Set broadcastChannels = new TreeSet<>();
-
- if(hasPatchGroupAlias())
- {
- broadcastChannels.addAll(getPatchGroupAlias().getBroadcastChannels());
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias))
- {
- broadcastChannels.addAll(alias.getBroadcastChannels());
- }
- }
-
- return broadcastChannels;
- }
-
- @Override
- public boolean hasBroadcastChannel(String channel)
- {
- if(hasPatchGroupAlias() && getPatchGroupAlias().hasBroadcastChannel(channel))
- {
- return true;
- }
-
- for(Alias alias: mPatchedAliases)
- {
- if(!(alias instanceof PatchGroupAlias) && alias.hasBroadcastChannel(channel))
- {
- return true;
- }
- }
-
- return false;
- }
-
- public static void main(String[] args)
- {
- Alias a1 = new Alias("Alias 1");
- a1.addAliasID(new BroadcastChannel("Channel 1"));
- a1.addAliasID(new BroadcastChannel("Channel 2"));
- a1.addAliasID(new BroadcastChannel("Channel 3"));
- a1.addAliasID(new BroadcastChannel("Channel 4"));
-
- Alias a2 = new Alias("Alias 1");
- a1.addAliasID(new BroadcastChannel("Channel 1"));
- a1.addAliasID(new BroadcastChannel("Channel 2"));
- a1.addAliasID(new BroadcastChannel("Channel 3"));
- a1.addAliasID(new BroadcastChannel("Channel 4"));
-
- Alias a3 = new Alias("Alias 1");
- a1.addAliasID(new BroadcastChannel("Channel 1"));
- a1.addAliasID(new BroadcastChannel("Channel 2"));
- a1.addAliasID(new BroadcastChannel("Channel 3"));
- a1.addAliasID(new BroadcastChannel("Channel 4"));
-
- Alias a4 = new Alias("Alias 1");
- a1.addAliasID(new BroadcastChannel("Channel 1"));
- a1.addAliasID(new BroadcastChannel("Channel 2"));
- a1.addAliasID(new BroadcastChannel("Channel 3"));
- a1.addAliasID(new BroadcastChannel("Channel 4"));
-
- PatchGroupAlias pga = new PatchGroupAlias();
- pga.setPatchGroupAlias(a1);
- pga.addPatchedAlias(a2);
- pga.addPatchedAlias(a3);
- pga.addPatchedAlias(a4);
-
- Set bc = pga.getBroadcastChannels();
-
- mLog.debug("Channels:" + bc);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/action/AliasAction.java b/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
index ae514992..6018019d 100644
--- a/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
@@ -26,9 +26,7 @@ import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.action.beep.BeepAction;
import io.github.dsheirer.alias.action.clip.ClipAction;
import io.github.dsheirer.alias.action.script.ScriptAction;
-import io.github.dsheirer.message.Message;
-
-import java.util.concurrent.ScheduledExecutorService;
+import io.github.dsheirer.message.IMessage;
/**
* Alias action defines an action to execute when an alias is detected active.
@@ -56,7 +54,7 @@ public abstract class AliasAction
* action attached. The alias argument is the parent alias containing the
* alias action.
*/
- public abstract void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message);
+ public abstract void execute(Alias alias, IMessage message);
/**
* Dismiss a persistent alias action
diff --git a/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java b/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
index 760122cb..8d73f0eb 100644
--- a/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
+++ b/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
@@ -19,51 +19,86 @@
package io.github.dsheirer.alias.action;
import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.message.IMessage;
+import io.github.dsheirer.message.IMessageListener;
+import io.github.dsheirer.module.Module;
import io.github.dsheirer.sample.Listener;
-import io.github.dsheirer.util.ThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.List;
/**
- * Manages all alias action events. Each received message is interrogated for
- * any alias entries and then each alias is interrogated for any alias actions.
+ * Manages all alias action events. Each received message is interrogated for any identifiers that may be aliasable
+ * and have associated alias actions.
*
- * Each alias action is executed and provided a copy of the source message so
- * that the contents of the message can be used as part of the action.
+ * Each alias action is executed and provided a copy of the source message so that the contents of the message can be
+ * used as part of the action.
*/
-public class AliasActionManager implements Listener
+public class AliasActionManager extends Module implements IMessageListener, Listener
{
- public AliasActionManager()
+ private final static Logger mLog = LoggerFactory.getLogger(AliasActionManager.class);
+ private AliasList mAliasList;
+
+ public AliasActionManager(AliasList aliasList)
{
+ mAliasList = aliasList;
}
@Override
- public void receive(Message message)
+ public void receive(IMessage message)
{
- if(message.isValid())
+ if(mAliasList != null && message.isValid())
{
- List aliases = message.getAliases();
+ List identifiers = message.getIdentifiers();
- if(aliases != null)
+ for(Identifier identifier: identifiers)
{
- for(Alias alias : aliases)
- {
- if(alias.hasActions())
- {
- List actions = alias.getAction();
+ Alias alias = mAliasList.getAlias(identifier);
- for(AliasAction action : actions)
- {
- /* Provide access to the thread pool manager in case the
- * action needs to setup a timer, and provide the original
- * message to be used as part of the action (e.g. sending
- * the message as a text message to a cell phone */
- action.execute(ThreadPool.SCHEDULED, alias, message);
- }
+ if(alias != null && alias.hasActions())
+ {
+ for(AliasAction action: alias.getAction())
+ {
+ action.execute(alias, message);
}
}
}
}
}
+
+ @Override
+ public void reset()
+ {
+ //No actions neeeded
+ }
+
+ @Override
+ public void start()
+ {
+ //No actions neeeded
+ }
+
+ @Override
+ public void stop()
+ {
+ //No actions neeeded
+ }
+
+ @Override
+ public void dispose()
+ {
+ //No actions neeeded
+ }
+
+ /**
+ * IMessageListener interface ... delegates to this class implementation of Listener
+ */
+ @Override
+ public Listener getMessageListener()
+ {
+ return this;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java b/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
index 8847eddf..5df29108 100644
--- a/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
@@ -1,13 +1,33 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
package io.github.dsheirer.alias.action;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.message.IMessage;
+import io.github.dsheirer.util.ThreadPool;
-import javax.swing.*;
-import java.awt.*;
-import java.util.concurrent.ScheduledExecutorService;
+import javax.swing.JOptionPane;
+import java.awt.EventQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -18,19 +38,15 @@ public abstract class RecurringAction extends AliasAction
protected AtomicBoolean mRunning = new AtomicBoolean(false);
@JsonIgnore
private ScheduledFuture> mPerpetualAction;
- @JsonIgnore
- protected ScheduledExecutorService mScheduledExecutorService;
protected Interval mInterval = Interval.ONCE;
protected int mPeriod = 5;
- public abstract void performAction(Alias alias, Message message);
+ public abstract void performAction(Alias alias, IMessage message);
@Override
- public void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message)
+ public void execute(Alias alias, IMessage message)
{
- mScheduledExecutorService = scheduledExecutorService;
-
if(mRunning.compareAndSet(false, true))
{
switch(mInterval)
@@ -41,10 +57,10 @@ public abstract class RecurringAction extends AliasAction
break;
case DELAYED_RESET:
performThreadedAction(alias, message);
- mScheduledExecutorService.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
break;
case UNTIL_DISMISSED:
- mPerpetualAction = mScheduledExecutorService.scheduleAtFixedRate(
+ mPerpetualAction = ThreadPool.SCHEDULED.scheduleAtFixedRate(
new PerformActionTask(alias, message), mPeriod, mPeriod, TimeUnit.SECONDS);
StringBuilder sb = new StringBuilder();
@@ -56,18 +72,13 @@ public abstract class RecurringAction extends AliasAction
final String text = sb.toString();
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- JOptionPane.showMessageDialog(null, text,
- "Alias Alert", JOptionPane.INFORMATION_MESSAGE);
+ EventQueue.invokeLater(() -> {
+ JOptionPane.showMessageDialog(null, text,
+ "Alias Alert", JOptionPane.INFORMATION_MESSAGE);
- dismiss(false);
+ dismiss(false);
- mScheduledExecutorService.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
- }
+ ThreadPool.SCHEDULED.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
});
break;
default:
@@ -79,16 +90,9 @@ public abstract class RecurringAction extends AliasAction
* Spawns the performAction() event into a new thread so that it doesn't
* delay any decoder actions.
*/
- private void performThreadedAction(final Alias alias, final Message message)
+ private void performThreadedAction(final Alias alias, final IMessage message)
{
- mScheduledExecutorService.schedule(new Runnable()
- {
- @Override
- public void run()
- {
- performAction(alias, message);
- }
- }, 0, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(() -> performAction(alias, message), 0, TimeUnit.SECONDS);
}
@Override
@@ -139,7 +143,7 @@ public abstract class RecurringAction extends AliasAction
private String mLabel;
- private Interval(String label)
+ Interval(String label)
{
mLabel = label;
}
@@ -153,9 +157,9 @@ public abstract class RecurringAction extends AliasAction
public class PerformActionTask implements Runnable
{
private Alias mAlias;
- private Message mMessage;
+ private IMessage mMessage;
- public PerformActionTask(Alias alias, Message message)
+ public PerformActionTask(Alias alias, IMessage message)
{
mAlias = alias;
mMessage = message;
diff --git a/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java b/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
index 6a0717ac..644b655d 100644
--- a/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
@@ -1,10 +1,30 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
package io.github.dsheirer.alias.action.beep;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.action.AliasActionType;
import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.message.IMessage;
public class BeepAction extends RecurringAction
{
@@ -17,7 +37,7 @@ public class BeepAction extends RecurringAction
}
@Override
- public void performAction(Alias alias, Message message )
+ public void performAction(Alias alias, IMessage message )
{
System.out.println( "\007" );
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java b/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
index 15807304..9bea3933 100644
--- a/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
@@ -1,3 +1,23 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
package io.github.dsheirer.alias.action.clip;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -5,7 +25,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.action.AliasActionType;
import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.message.IMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +65,7 @@ public class ClipAction extends RecurringAction
}
@Override
- public void performAction(Alias alias, Message message)
+ public void performAction(Alias alias, IMessage message)
{
try
{
diff --git a/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java b/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
index 9aa920c2..e837010d 100644
--- a/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
@@ -1,10 +1,30 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
package io.github.dsheirer.alias.action.script;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.action.AliasActionType;
import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.message.IMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +59,7 @@ public class ScriptAction extends RecurringAction
}
@Override
- public void performAction(Alias alias, Message message)
+ public void performAction(Alias alias, IMessage message)
{
try
{
@@ -63,8 +83,7 @@ public class ScriptAction extends RecurringAction
int exitCode = p.waitFor();
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(p.getInputStream()));
+ BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
@@ -77,8 +96,7 @@ public class ScriptAction extends RecurringAction
if(exitCode != 0)
{
- throw new RuntimeException("Exit Code: " + exitCode +
- " Console:" + sb.toString());
+ throw new RuntimeException("Exit Code: " + exitCode + " Console:" + sb.toString());
}
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasID.java b/src/main/java/io/github/dsheirer/alias/id/AliasID.java
index 0534f4a2..935c764e 100644
--- a/src/main/java/io/github/dsheirer/alias/id/AliasID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/AliasID.java
@@ -1,17 +1,17 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014-2016 Dennis Sheirer
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
******************************************************************************/
@@ -23,46 +23,52 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
import io.github.dsheirer.alias.id.esn.Esn;
-import io.github.dsheirer.alias.id.fleetsync.FleetsyncID;
+import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
+import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
+import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
+import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
+import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
-import io.github.dsheirer.alias.id.mdc.MDC1200ID;
import io.github.dsheirer.alias.id.mobileID.Min;
-import io.github.dsheirer.alias.id.mpt1327.MPT1327ID;
-import io.github.dsheirer.alias.id.nonrecordable.NonRecordable;
import io.github.dsheirer.alias.id.priority.Priority;
+import io.github.dsheirer.alias.id.record.Record;
import io.github.dsheirer.alias.id.siteID.SiteID;
import io.github.dsheirer.alias.id.status.StatusID;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupID;
+import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
+import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
import io.github.dsheirer.alias.id.uniqueID.UniqueID;
-@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.PROPERTY, property="type")
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
- @JsonSubTypes.Type(value=BroadcastChannel.class, name="broadcastChannel"),
- @JsonSubTypes.Type(value=Esn.class, name="esn"),
- @JsonSubTypes.Type(value=FleetsyncID.class, name="fleetsyncID"),
+ @JsonSubTypes.Type(value = BroadcastChannel.class, name = "broadcastChannel"),
+ @JsonSubTypes.Type(value = Esn.class, name = "esn"),
+ @JsonSubTypes.Type(value = FleetsyncID.class, name = "fleetsyncID"),
@JsonSubTypes.Type(value = LoJackFunctionAndID.class, name = "loJackFunctionAndID"),
@JsonSubTypes.Type(value = MDC1200ID.class, name = "mdc1200ID"),
@JsonSubTypes.Type(value = Min.class, name = "min"),
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
+ @JsonSubTypes.Type(value = Talkgroup.class, name = "talkgroup"),
+ @JsonSubTypes.Type(value = TalkgroupRange.class, name = "talkgroupRange"),
@JsonSubTypes.Type(value = Priority.class, name = "priority"),
+ @JsonSubTypes.Type(value = Record.class, name = "record"),
@JsonSubTypes.Type(value = SiteID.class, name = "siteID"),
@JsonSubTypes.Type(value = StatusID.class, name = "statusID"),
- @JsonSubTypes.Type(value = TalkgroupID.class, name = "talkgroupID"),
+ @JsonSubTypes.Type(value = LegacyTalkgroupID.class, name = "talkgroupID"),
@JsonSubTypes.Type(value = UniqueID.class, name = "uniqueID")
})
-@JacksonXmlRootElement( localName = "id" )
+@JacksonXmlRootElement(localName = "id")
public abstract class AliasID
{
- public AliasID()
- {
- }
+ public AliasID()
+ {
+ }
- @JsonIgnore
- public abstract AliasIDType getType();
-
- public abstract boolean matches( AliasID id );
+ @JsonIgnore
+ public abstract AliasIDType getType();
- @JsonIgnore
- public abstract boolean isValid();
+ public abstract boolean matches(AliasID id);
+
+ @JsonIgnore
+ public abstract boolean isValid();
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java b/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
index bd95471e..206a9e09 100644
--- a/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
+++ b/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
@@ -1,49 +1,55 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias.id;
public enum AliasIDType
{
- ESN( "ESN" ),
- FLEETSYNC( "Fleetsync" ),
- LOJACK( "LoJack" ),
- LTR_NET_UID( "LTR-Net UID" ),
- MDC1200( "MDC-1200" ),
- MIN( "Passport MIN" ),
- MPT1327( "MPT-1327" ),
- SITE( "Site" ),
- STATUS( "Status" ),
- TALKGROUP( "Talkgroup" ),
+ BROADCAST_CHANNEL("Audio Broadcast Channel"),
+ ESN("ESN"),
+ INVERT("Audio Inversion"),
+ LOJACK("LoJack"),
+ LTR_NET_UID("LTR-Net UID"),
+ MIN("Passport MIN"),
+ PRIORITY("Audio Priority"),
+ RECORD("Record"),
+ SITE("Site"),
+ STATUS("Status"),
+ TALKGROUP("Talkgroup"),
+ TALKGROUP_RANGE("Talkgroup Range"),
- INVERT( "Audio Inversion" ),
- PRIORITY( "Audio Priority" ),
- NON_RECORDABLE( "Audio Non-Recordable" ),
- BROADCAST_CHANNEL( "Audio Broadcast Channel" );
-
- private String mLabel;
-
- private AliasIDType( String label )
- {
- mLabel = label;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ //Legacy identifier types - no longer used
+ FLEETSYNC("Fleetsync"),
+ LEGACY_TALKGROUP("Legacy Talkgroup"),
+ MDC1200("MDC-1200"),
+ MPT1327("MPT-1327"),
+ NON_RECORDABLE("Audio Non-Recordable");
+
+ private String mLabel;
+
+ AliasIDType(String label)
+ {
+ mLabel = label;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java b/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java
index d0d68901..e6bb7b9d 100644
--- a/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java
+++ b/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java
@@ -1,20 +1,22 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.alias.id;
import io.github.dsheirer.alias.Alias;
@@ -26,10 +28,19 @@ import io.github.dsheirer.gui.editor.Editor;
import io.github.dsheirer.gui.editor.EmptyEditor;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JList;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
-import java.awt.*;
+import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
@@ -40,328 +51,327 @@ import java.util.List;
public class AliasIdentifierEditor extends Editor
{
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- private static ListModel EMPTY_MODEL = new DefaultListModel<>();
- private JList mAliasIDList = new JList<>( EMPTY_MODEL );
- private JButton mNewIDButton;
- private JButton mCloneIDButton;
- private JButton mDeleteIDButton;
- private EditorContainer mEditorContainer = new EditorContainer();
+ private static ListModel EMPTY_MODEL = new DefaultListModel<>();
+ private JList mAliasIDList = new JList<>(EMPTY_MODEL);
+ private JButton mNewIDButton;
+ private JButton mCloneIDButton;
+ private JButton mDeleteIDButton;
+ private EditorContainer mEditorContainer = new EditorContainer();
- private AliasModel mAliasModel;
+ private AliasModel mAliasModel;
private BroadcastModel mBroadcastModel;
-
- public AliasIdentifierEditor( AliasModel aliasModel, BroadcastModel broadcastModel )
- {
- mAliasModel = aliasModel;
+
+ public AliasIdentifierEditor(AliasModel aliasModel, BroadcastModel broadcastModel)
+ {
+ mAliasModel = aliasModel;
mBroadcastModel = broadcastModel;
- init();
- }
+ init();
+ }
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 3",
- "[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]" ) );
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3",
+ "[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]"));
- mAliasIDList.setVisibleRowCount( 6 );
- mAliasIDList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
- mAliasIDList.setLayoutOrientation( JList.VERTICAL );
- mAliasIDList.addListSelectionListener( new ListSelectionListener()
- {
- @Override
- public void valueChanged( ListSelectionEvent event )
- {
- if( !event.getValueIsAdjusting() )
- {
- JList> list = (JList>)event.getSource();
-
- Object selectedItem = list.getSelectedValue();
-
- if( selectedItem != null && selectedItem instanceof AliasID )
- {
- AliasID selected = (AliasID)selectedItem;
+ mAliasIDList.setVisibleRowCount(6);
+ mAliasIDList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ mAliasIDList.setLayoutOrientation(JList.VERTICAL);
+ mAliasIDList.addListSelectionListener(new ListSelectionListener()
+ {
+ @Override
+ public void valueChanged(ListSelectionEvent event)
+ {
+ if(!event.getValueIsAdjusting())
+ {
+ JList> list = (JList>)event.getSource();
- mEditorContainer.setAliasID( selected );
-
- mCloneIDButton.setEnabled( true );
- mDeleteIDButton.setEnabled( true );
- }
- else
- {
- mCloneIDButton.setEnabled( false );
- mDeleteIDButton.setEnabled( false );
- }
- }
- }
- } );
-
- JScrollPane scroller = new JScrollPane( mAliasIDList );
- add( scroller, "span,grow" );
-
- add( mEditorContainer, "span,grow" );
+ Object selectedItem = list.getSelectedValue();
- mNewIDButton = new JButton( "New ..." );
- mNewIDButton.setToolTipText( "Create a new Alias Identifier" );
- mNewIDButton.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JPopupMenu menu = new JPopupMenu();
+ if(selectedItem != null && selectedItem instanceof AliasID)
+ {
+ AliasID selected = (AliasID)selectedItem;
- menu.add( new AddAliasIdentifierItem( AliasIDType.ESN ) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.FLEETSYNC) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.LOJACK) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.LTR_NET_UID) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.MDC1200 ) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.MPT1327 ) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.MIN ) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.SITE) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.STATUS) );
- menu.add( new AddAliasIdentifierItem( AliasIDType.TALKGROUP) );
+ mEditorContainer.setAliasID(selected);
- menu.addSeparator();
+ mCloneIDButton.setEnabled(true);
+ mDeleteIDButton.setEnabled(true);
+ }
+ else
+ {
+ mCloneIDButton.setEnabled(false);
+ mDeleteIDButton.setEnabled(false);
+ }
+ }
+ }
+ });
- menu.add( new AddAliasIdentifierItem( AliasIDType.BROADCAST_CHANNEL) );
+ JScrollPane scroller = new JScrollPane(mAliasIDList);
+ add(scroller, "span,grow");
- if( hasItem() )
- {
- Alias alias = getItem();
+ add(mEditorContainer, "span,grow");
- if( alias.isRecordable() )
- {
- menu.add( new AddAliasIdentifierItem( AliasIDType.NON_RECORDABLE) );
- }
+ mNewIDButton = new JButton("New ...");
+ mNewIDButton.setToolTipText("Create a new Alias Identifier");
+ mNewIDButton.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JPopupMenu menu = new JPopupMenu();
- if( !alias.hasCallPriority() )
- {
- menu.add( new AddAliasIdentifierItem( AliasIDType.PRIORITY) );
- }
- }
+ menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP_RANGE));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.ESN));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.LOJACK));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.LTR_NET_UID));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.MDC1200));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.MIN));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.SITE));
+ menu.add(new AddAliasIdentifierItem(AliasIDType.STATUS));
- menu.show( e.getComponent(), e.getX(), e.getY() );
- }
- } );
-
- add( mNewIDButton );
-
- mCloneIDButton = new JButton( "Clone" );
- mCloneIDButton.setToolTipText( "Create a copy of the currently selected identifier" );
- mCloneIDButton.setEnabled( false );
- mCloneIDButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- AliasID selected = mAliasIDList.getSelectedValue();
-
- if( selected != null )
- {
- AliasID clone = AliasFactory.copyOf( selected );
+ menu.addSeparator();
- if( clone != null )
- {
- addAliasIDToList( clone );
- }
- }
- }
- } );
- add( mCloneIDButton );
-
- mDeleteIDButton = new JButton( "Delete" );
- mDeleteIDButton.setToolTipText( "Delete the currently selected identifier" );
- mDeleteIDButton.setEnabled( false );
- mDeleteIDButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final AliasID selected = mAliasIDList.getSelectedValue();
-
- if( selected != null )
- {
- int choice = JOptionPane.showConfirmDialog( mDeleteIDButton,
- "Do you want to delete [" + selected.toString() + "]",
- "Are you sure?", JOptionPane.YES_NO_OPTION );
-
- if( choice == JOptionPane.YES_OPTION && hasItem() )
- {
- Alias alias = getItem();
-
- alias.removeAliasID( selected );
-
- mAliasModel.broadcast( new AliasEvent( alias, AliasEvent.Event.CHANGE ) );
+ menu.add(new AddAliasIdentifierItem(AliasIDType.BROADCAST_CHANNEL));
- setItem( alias );
- }
- }
- }
- } );
- add( mDeleteIDButton, "wrap" );
- }
-
- @Override
- public void setItem( Alias alias )
- {
- super.setItem( alias );
-
- if( alias == null || alias.getId().isEmpty() )
- {
- mAliasIDList.setModel( EMPTY_MODEL );
- }
- else
- {
- DefaultListModel model = new DefaultListModel();
+ if(hasItem())
+ {
+ Alias alias = getItem();
- List ids = alias.getId();
-
- Collections.sort( ids, new Comparator()
- {
- @Override
- public int compare( AliasID o1, AliasID o2 )
- {
- return o1.toString().compareTo( o2.toString() );
- }
- } );
-
- for( AliasID id: ids )
- {
- model.addElement( id );
- }
-
- mAliasIDList.setModel( model );
- }
-
- mEditorContainer.setAliasID( null );
- }
-
- @Override
- public void save()
- {
- if( isModified() || mEditorContainer.isModified() )
- {
- if( mEditorContainer.isModified() )
- {
- mEditorContainer.save();
- }
-
- setModified( false );
-
- if( hasItem() )
- {
- mAliasModel.broadcast( new AliasEvent( getItem(), AliasEvent.Event.CHANGE ) );
- }
- }
- }
-
- public class EditorContainer extends JPanel
- {
- private static final long serialVersionUID = 1L;
+ if(!alias.isRecordable())
+ {
+ menu.add(new AddAliasIdentifierItem(AliasIDType.RECORD));
+ }
- private Editor mEditor = new EmptyEditor<>();
+ if(!alias.hasCallPriority())
+ {
+ menu.add(new AddAliasIdentifierItem(AliasIDType.PRIORITY));
+ }
+ }
- public EditorContainer()
- {
- setLayout( new MigLayout( "","[grow,fill]", "[grow,fill]" ) );
+ menu.show(e.getComponent(), e.getX(), e.getY());
+ }
+ });
- add( mEditor );
- }
-
- public boolean isModified()
- {
- if( mEditor != null )
- {
- return mEditor.isModified();
- }
-
- return false;
- }
-
- public void save()
- {
- if( mEditor != null )
- {
- mEditor.save();
- }
- }
-
- public void setAliasID( AliasID aliasID )
- {
- if( mEditor != null )
- {
- if( mEditor.isModified() )
- {
- int option = JOptionPane.showConfirmDialog(
- EditorContainer.this,
- "Identifier settings have changed. Do you want to save these changes?",
- "Save Changes?",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE );
-
- if( option == JOptionPane.YES_OPTION )
- {
- mEditor.save();
- }
- }
- }
- removeAll();
-
- //This will always give us an editor
- mEditor = AliasFactory.getEditor( aliasID, mBroadcastModel );
-
- add( mEditor );
+ add(mNewIDButton);
- revalidate();
- }
- }
-
- private void addAliasIDToList( final AliasID id )
- {
- if( id != null && hasItem() )
- {
- final Alias alias = getItem();
-
- alias.addAliasID( id );
-
- EventQueue.invokeLater( new Runnable()
- {
- @Override
- public void run()
- {
- setItem( alias );
-
- mAliasIDList.setSelectedValue( id, true );
-
- AliasIdentifierEditor.this.setModified( true );
- }
- } );
- }
- }
-
- public class AddAliasIdentifierItem extends JMenuItem
- {
- private static final long serialVersionUID = 1L;
-
- private AliasIDType mAliasIDType;
+ mCloneIDButton = new JButton("Clone");
+ mCloneIDButton.setToolTipText("Create a copy of the currently selected identifier");
+ mCloneIDButton.setEnabled(false);
+ mCloneIDButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ AliasID selected = mAliasIDList.getSelectedValue();
- public AddAliasIdentifierItem( AliasIDType type )
- {
- super( type.toString() );
-
- mAliasIDType = type;
-
- addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final AliasID id = AliasFactory.getAliasID( mAliasIDType );
-
- addAliasIDToList( id );
- }
- } );
- }
- }
+ if(selected != null)
+ {
+ AliasID clone = AliasFactory.copyOf(selected);
+
+ if(clone != null)
+ {
+ addAliasIDToList(clone);
+ }
+ }
+ }
+ });
+ add(mCloneIDButton);
+
+ mDeleteIDButton = new JButton("Delete");
+ mDeleteIDButton.setToolTipText("Delete the currently selected identifier");
+ mDeleteIDButton.setEnabled(false);
+ mDeleteIDButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ final AliasID selected = mAliasIDList.getSelectedValue();
+
+ if(selected != null)
+ {
+ int choice = JOptionPane.showConfirmDialog(mDeleteIDButton,
+ "Do you want to delete [" + selected.toString() + "]",
+ "Are you sure?", JOptionPane.YES_NO_OPTION);
+
+ if(choice == JOptionPane.YES_OPTION && hasItem())
+ {
+ Alias alias = getItem();
+
+ alias.removeAliasID(selected);
+
+ mAliasModel.broadcast(new AliasEvent(alias, AliasEvent.Event.CHANGE));
+
+ setItem(alias);
+ }
+ }
+ }
+ });
+ add(mDeleteIDButton, "wrap");
+ }
+
+ @Override
+ public void setItem(Alias alias)
+ {
+ super.setItem(alias);
+
+ if(alias == null || alias.getId().isEmpty())
+ {
+ mAliasIDList.setModel(EMPTY_MODEL);
+ }
+ else
+ {
+ DefaultListModel model = new DefaultListModel();
+
+ List ids = alias.getId();
+
+ Collections.sort(ids, new Comparator()
+ {
+ @Override
+ public int compare(AliasID o1, AliasID o2)
+ {
+ return o1.toString().compareTo(o2.toString());
+ }
+ });
+
+ for(AliasID id : ids)
+ {
+ model.addElement(id);
+ }
+
+ mAliasIDList.setModel(model);
+ }
+
+ mEditorContainer.setAliasID(null);
+ }
+
+ @Override
+ public void save()
+ {
+ if(isModified() || mEditorContainer.isModified())
+ {
+ if(mEditorContainer.isModified())
+ {
+ mEditorContainer.save();
+ }
+
+ setModified(false);
+
+ if(hasItem())
+ {
+ mAliasModel.broadcast(new AliasEvent(getItem(), AliasEvent.Event.CHANGE));
+ }
+ }
+ }
+
+ public class EditorContainer extends JPanel
+ {
+ private static final long serialVersionUID = 1L;
+
+ private Editor mEditor = new EmptyEditor<>();
+
+ public EditorContainer()
+ {
+ setLayout(new MigLayout("", "[grow,fill]", "[grow,fill]"));
+
+ add(mEditor);
+ }
+
+ public boolean isModified()
+ {
+ if(mEditor != null)
+ {
+ return mEditor.isModified();
+ }
+
+ return false;
+ }
+
+ public void save()
+ {
+ if(mEditor != null)
+ {
+ mEditor.save();
+ }
+ }
+
+ public void setAliasID(AliasID aliasID)
+ {
+ if(mEditor != null)
+ {
+ if(mEditor.isModified())
+ {
+ int option = JOptionPane.showConfirmDialog(
+ EditorContainer.this,
+ "Identifier settings have changed. Do you want to save these changes?",
+ "Save Changes?",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+
+ if(option == JOptionPane.YES_OPTION)
+ {
+ mEditor.save();
+ }
+ }
+ }
+ removeAll();
+
+ //This will always give us an editor
+ mEditor = AliasFactory.getEditor(aliasID, mBroadcastModel);
+
+ add(mEditor);
+
+ revalidate();
+ }
+ }
+
+ private void addAliasIDToList(final AliasID id)
+ {
+ if(id != null && hasItem())
+ {
+ final Alias alias = getItem();
+
+ alias.addAliasID(id);
+
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ setItem(alias);
+
+ mAliasIDList.setSelectedValue(id, true);
+
+ AliasIdentifierEditor.this.setModified(true);
+ }
+ });
+ }
+ }
+
+ public class AddAliasIdentifierItem extends JMenuItem
+ {
+ private static final long serialVersionUID = 1L;
+
+ private AliasIDType mAliasIDType;
+
+ public AddAliasIdentifierItem(AliasIDType type)
+ {
+ super(type.toString());
+
+ mAliasIDType = type;
+
+ addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ final AliasID id = AliasFactory.getAliasID(mAliasIDType);
+
+ addAliasIDToList(id);
+ }
+ });
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java b/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
index 656c7793..a2b66022 100644
--- a/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
+++ b/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
@@ -48,7 +48,13 @@ public class Esn extends AliasID
public String toString()
{
- return "ESN: " + mEsn;
+ StringBuilder sb = new StringBuilder();
+ sb.append("ESN: ").append(mEsn != null ? mEsn : "(empty)");
+ if(!isValid())
+ {
+ sb.append(" **NOT VALID**");
+ }
+ return sb.toString();
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
similarity index 53%
rename from src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncID.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
index 19473bdf..3076d3b7 100644
--- a/src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
@@ -1,21 +1,23 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.fleetsync;
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.fleetsync;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.id.AliasID;
@@ -48,7 +50,7 @@ public class FleetsyncID extends AliasID
public String toString()
{
- return "Fleetsync: " + mID;
+ return "Fleetsync: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD";
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java
similarity index 69%
rename from src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncIDEditor.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java
index 89fe739c..85f7a2ba 100644
--- a/src/main/java/io/github/dsheirer/alias/id/fleetsync/FleetsyncIDEditor.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java
@@ -1,21 +1,23 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.fleetsync;
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.fleetsync;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
@@ -23,9 +25,13 @@ import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.swing.*;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;
-import java.awt.*;
+import java.awt.Color;
+import java.awt.Cursor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
diff --git a/src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200ID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
similarity index 56%
rename from src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200ID.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
index e8f50df7..85dc60d9 100644
--- a/src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200ID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
@@ -1,21 +1,23 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.mdc;
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.mdc;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@@ -49,7 +51,7 @@ public class MDC1200ID extends AliasID
public String toString()
{
- return "MDC-1200: " + mID;
+ return "MDC-1200: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD**";
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java
new file mode 100644
index 00000000..f472e6d5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java
@@ -0,0 +1,133 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.mdc;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import net.miginfocom.swing.MigLayout;
+
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import javax.swing.text.MaskFormatter;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class MDC1200IDEditor extends DocumentListenerEditor
+{
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT = ""
+ + "
MDC-1200 Identifier
"
+ + "MDC-1200: four digit [0-9] value (e.g. 1234) "
+ + "Wildcard: use an asterisk (*) to wildcard individual "
+ + "digits (e.g. 123* or **34)"
+ + "";
+
+ private JTextField mTextField;
+
+ public MDC1200IDEditor(AliasID aliasID)
+ {
+ initGUI();
+
+ setItem(aliasID);
+ }
+
+ private void initGUI()
+ {
+ setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
+
+ add(new JLabel("MDC-1200 ID:"));
+
+ MaskFormatter formatter = null;
+
+ try
+ {
+ //Mask: 4 digits
+ formatter = new MaskFormatter("####");
+ }
+ catch(Exception e)
+ {
+ //Do nothing, the mask was invalid
+ }
+
+ mTextField = new JFormattedTextField(formatter);
+ mTextField.getDocument().addDocumentListener(this);
+ mTextField.setToolTipText(HELP_TEXT);
+ add(mTextField, "growx,push");
+
+ JLabel help = new JLabel("Help ...");
+ help.setForeground(Color.BLUE.brighter());
+ help.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ help.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JOptionPane.showMessageDialog(MDC1200IDEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ add(help, "align left");
+ }
+
+ public MDC1200ID getMDC1200ID()
+ {
+ if(getItem() instanceof MDC1200ID)
+ {
+ return (MDC1200ID)getItem();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setItem(AliasID aliasID)
+ {
+ super.setItem(aliasID);
+
+ MDC1200ID mdc = getMDC1200ID();
+
+ if(mdc != null)
+ {
+ mTextField.setText(mdc.getIdent());
+ }
+
+ setModified(false);
+
+ repaint();
+ }
+
+ @Override
+ public void save()
+ {
+ MDC1200ID mdc = getMDC1200ID();
+
+ if(mdc != null)
+ {
+ mdc.setIdent(mTextField.getText());
+ }
+
+ setModified(false);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327ID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
similarity index 55%
rename from src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327ID.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
index 53208bbb..b27ad6ee 100644
--- a/src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327ID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
@@ -1,21 +1,23 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.mpt1327;
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.mpt1327;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@@ -49,7 +51,7 @@ public class MPT1327ID extends AliasID
public String toString()
{
- return "MPT-1327: " + mID;
+ return "MPT-1327: " + (mID != null ? mID : "(empty)") + " **INVALID - USE TALKGROUP INSTEAD**";
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327IDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java
similarity index 68%
rename from src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327IDEditor.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java
index 6ce3ccad..36c38ecc 100644
--- a/src/main/java/io/github/dsheirer/alias/id/mpt1327/MPT1327IDEditor.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java
@@ -1,29 +1,35 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.mpt1327;
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.mpt1327;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.gui.editor.DocumentListenerEditor;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;
-import java.awt.*;
+import java.awt.Color;
+import java.awt.Cursor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java
new file mode 100644
index 00000000..b9d10706
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java
@@ -0,0 +1,53 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.alias.id.legacy.nonrecordable;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+
+public class NonRecordable extends AliasID
+{
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.NON_RECORDABLE;
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Audio Non-Recordable - **INVALID - USE RECORD INSTEAD**";
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java
new file mode 100644
index 00000000..51a3438a
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java
@@ -0,0 +1,78 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.nonrecordable;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import net.miginfocom.swing.MigLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class NonRecordableEditor extends DocumentListenerEditor
+{
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT = ""
+ + "
Audio Non-Recordable
"
+ + "This identifies an alias as non-recordable.
"
+ + "The alias can still be monitored but associated audio will "
+ + "not be recorded.
"
+ + "The default behavior when audio recording is enabled for a "
+ + "channel is to record all aliases except any alias with a "
+ + "non-recordable identifier";
+
+ public NonRecordableEditor(AliasID aliasID)
+ {
+ initGUI();
+
+ setItem(aliasID);
+ }
+
+ private void initGUI()
+ {
+ setLayout(new MigLayout("fill,wrap 1", "[]", "[][]"));
+
+ add(new JLabel("Non-Recordable"), "wrap");
+
+ JLabel help = new JLabel("Help ...");
+ help.setForeground(Color.BLUE.brighter());
+ help.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ help.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JOptionPane.showMessageDialog(NonRecordableEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ add(help, "align left");
+ }
+
+ @Override
+ public void save()
+ {
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
similarity index 50%
rename from src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupID.java
rename to src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
index c70accbd..bc925e83 100644
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
@@ -1,37 +1,39 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.talkgroup;
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.talkgroup;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.AliasIDType;
-public class TalkgroupID extends AliasID
+public class LegacyTalkgroupID extends AliasID
{
private String mTalkgroup;
- public TalkgroupID()
+ public LegacyTalkgroupID()
{
//No arg JAXB constructor
}
- public TalkgroupID(String talkgroup)
+ public LegacyTalkgroupID(String talkgroup)
{
mTalkgroup = talkgroup;
}
@@ -57,7 +59,7 @@ public class TalkgroupID extends AliasID
{
StringBuilder sb = new StringBuilder();
- sb.append("Talkgroup: " + mTalkgroup);
+ sb.append("Legacy Talkgroup:").append(mTalkgroup).append(" *Disabled - Please Convert");
return sb.toString();
}
@@ -67,9 +69,9 @@ public class TalkgroupID extends AliasID
{
boolean retVal = false;
- if(id instanceof TalkgroupID)
+ if(id instanceof LegacyTalkgroupID)
{
- TalkgroupID tgid = (TalkgroupID)id;
+ LegacyTalkgroupID tgid = (LegacyTalkgroupID)id;
//Create a pattern - replace * wildcards with regex single-char wildcard
String pattern = mTalkgroup.replace("*", ".?");
@@ -84,6 +86,6 @@ public class TalkgroupID extends AliasID
@Override
public AliasIDType getType()
{
- return AliasIDType.TALKGROUP;
+ return AliasIDType.LEGACY_TALKGROUP;
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java
new file mode 100644
index 00000000..7d88b587
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java
@@ -0,0 +1,121 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.legacy.talkgroup;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import net.miginfocom.swing.MigLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class LegacyTalkgroupIDEditor extends DocumentListenerEditor
+{
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT =
+ "
Talkgroup Identifier
"
+ + "P25: 4 or 6 hex characters (e.g. AB12 or ABC123) "
+ + "LTR: A-HH-TTT where A=Area H=Home T=Talkgroup (0-01-128) "
+ + "Passport: 5-digit number (12345 or 00023) "
+ + " "
+ + "Wildcard: use an asterisk (*) in place of each talkgroup digit (e.g. 0*1*5)"
+ + "";
+
+ private JTextField mTextField;
+
+ public LegacyTalkgroupIDEditor(AliasID aliasID)
+ {
+ initGUI();
+
+ setItem(aliasID);
+ }
+
+ private void initGUI()
+ {
+ setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
+
+ add(new JLabel("Talkgroup:"));
+
+ mTextField = new JTextField();
+ mTextField.getDocument().addDocumentListener(this);
+ mTextField.setToolTipText(HELP_TEXT);
+ add(mTextField, "growx,push");
+
+ JLabel help = new JLabel("Help ...");
+ help.setForeground(Color.BLUE.brighter());
+ help.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ help.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JOptionPane.showMessageDialog(LegacyTalkgroupIDEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ add(help, "align left");
+ }
+
+ public LegacyTalkgroupID getTalkgroupID()
+ {
+ if(getItem() instanceof LegacyTalkgroupID)
+ {
+ return (LegacyTalkgroupID)getItem();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setItem(AliasID aliasID)
+ {
+ super.setItem(aliasID);
+
+ LegacyTalkgroupID talkgroup = getTalkgroupID();
+
+ if(talkgroup != null)
+ {
+ mTextField.setText(talkgroup.getTalkgroup());
+ }
+
+ setModified(false);
+
+ repaint();
+ }
+
+ @Override
+ public void save()
+ {
+ LegacyTalkgroupID talkgroup = getTalkgroupID();
+
+ if(talkgroup != null)
+ {
+ talkgroup.setTalkgroup(mTextField.getText());
+ }
+
+ setModified(false);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java b/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
index 95f15688..8ec2802e 100644
--- a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
@@ -26,7 +26,7 @@ import io.github.dsheirer.module.decode.lj1200.LJ1200Message;
public class LoJackFunctionAndID extends AliasID
{
private LJ1200Message.Function mFunction = LJ1200Message.Function.F0_UNKNOWN;
- private String mID = "*****";
+ private String mID = null;
public LoJackFunctionAndID()
{
@@ -62,7 +62,8 @@ public class LoJackFunctionAndID extends AliasID
public String toString()
{
- return "LoJack FUNC: " + mFunction.getLabel() + " ID:" + (mID == null ? "" : mID);
+ return "LoJack FUNCTION: " + mFunction.getLabel() +
+ " ID:" + (mID == null ? "" : mID) + (isValid() ? "" : " **NOT VALID**");
}
/**
diff --git a/src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200IDEditor.java b/src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200IDEditor.java
deleted file mode 100644
index e688421e..00000000
--- a/src/main/java/io/github/dsheirer/alias/id/mdc/MDC1200IDEditor.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.mdc;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.text.MaskFormatter;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class MDC1200IDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
MDC-1200 Identifier
"
- + "MDC-1200: four digit [0-9] value (e.g. 1234) "
- + "Wildcard: use an asterisk (*) to wildcard individual "
- + "digits (e.g. 123* or **34)"
- + "";
-
- private JTextField mTextField;
-
- public MDC1200IDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "MDC-1200 ID:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 4 digits
- formatter = new MaskFormatter( "####" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( MDC1200IDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public MDC1200ID getMDC1200ID()
- {
- if( getItem() instanceof MDC1200ID )
- {
- return (MDC1200ID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- MDC1200ID mdc = getMDC1200ID();
-
- if( mdc != null )
- {
- mTextField.setText( mdc.getIdent() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- MDC1200ID mdc = getMDC1200ID();
-
- if( mdc != null )
- {
- mdc.setIdent( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/mobileID/Min.java b/src/main/java/io/github/dsheirer/alias/id/mobileID/Min.java
index aec0eb72..89282fc6 100644
--- a/src/main/java/io/github/dsheirer/alias/id/mobileID/Min.java
+++ b/src/main/java/io/github/dsheirer/alias/id/mobileID/Min.java
@@ -52,7 +52,7 @@ public class Min extends AliasID
public String toString()
{
- return "MIN: " + mMin;
+ return "MIN: " + (mMin != null ? mMin : "(empty)") + (isValid() ? "" : " **NOT VALID**");
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordable.java b/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordable.java
deleted file mode 100644
index b6a2fcb9..00000000
--- a/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordable.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.github.dsheirer.alias.id.nonrecordable;
-
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.alias.id.AliasIDType;
-
-public class NonRecordable extends AliasID
-{
- @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
- @Override
- public AliasIDType getType()
- {
- return AliasIDType.NON_RECORDABLE;
- }
-
- @Override
- public boolean isValid()
- {
- return true;
- }
-
- @Override
- public boolean matches(AliasID id)
- {
- return false;
- }
-
- @Override
- public String toString()
- {
- return "Audio Non-Recordable";
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordableEditor.java b/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordableEditor.java
deleted file mode 100644
index 02726cc9..00000000
--- a/src/main/java/io/github/dsheirer/alias/id/nonrecordable/NonRecordableEditor.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.nonrecordable;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class NonRecordableEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Audio Non-Recordable
"
- + "This identifies an alias as non-recordable.
"
- + "The alias can still be monitored but associated audio will "
- + "not be recorded.
"
- + "The default behavior when audio recording is enabled for a "
- + "channel is to record all aliases except any alias with a "
- + "non-recordable identifier";
-
- public NonRecordableEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
-
- add( new JLabel( "Non-Recordable" ), "wrap" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( NonRecordableEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- @Override
- public void save()
- {
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/record/Record.java b/src/main/java/io/github/dsheirer/alias/id/record/Record.java
new file mode 100644
index 00000000..85ab55ca
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/record/Record.java
@@ -0,0 +1,56 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.alias.id.record;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+
+/**
+ * Alias identifier to flag an alias for audio recording
+ */
+public class Record extends AliasID
+{
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.RECORD;
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Record Audio";
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java b/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java
new file mode 100644
index 00000000..91b8c809
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java
@@ -0,0 +1,73 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.record;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import net.miginfocom.swing.MigLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class RecordEditor extends DocumentListenerEditor
+{
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT = ""
+ + "
Record Audio
"
+ + "Any audio associated with this alias will be recorded.
";
+
+ public RecordEditor(AliasID aliasID )
+ {
+ initGUI();
+
+ setItem( aliasID );
+ }
+
+ private void initGUI()
+ {
+ setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
+
+ add( new JLabel( "Record Audio" ), "wrap" );
+
+ JLabel help = new JLabel( "Help ..." );
+ help.setForeground( Color.BLUE.brighter() );
+ help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
+ help.addMouseListener( new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked( MouseEvent e )
+ {
+ JOptionPane.showMessageDialog( RecordEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
+ }
+ } );
+ add( help, "align left" );
+ }
+
+ @Override
+ public void save()
+ {
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/siteID/SiteID.java b/src/main/java/io/github/dsheirer/alias/id/siteID/SiteID.java
index acf3016e..f4bdbca8 100644
--- a/src/main/java/io/github/dsheirer/alias/id/siteID/SiteID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/siteID/SiteID.java
@@ -48,7 +48,7 @@ public class SiteID extends AliasID
public String toString()
{
- return "Site: " + mSite;
+ return "Site: " + (mSite != null ? mSite : "(empty)") + (isValid() ? "" : " **NOT VALID**");
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java
new file mode 100644
index 00000000..7562ef84
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java
@@ -0,0 +1,107 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.talkgroup;
+
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+import io.github.dsheirer.protocol.Protocol;
+
+/**
+ * Integer talkgroup identifier with protocol.
+ */
+public class Talkgroup extends AliasID
+{
+ private Protocol mProtocol;
+ private int mValue;
+
+ public Talkgroup()
+ {
+ //No arg JAXB constructor
+ }
+
+ public Talkgroup(Protocol protocol, int value)
+ {
+ mProtocol = protocol;
+ mValue = value;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "value")
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ public void setValue(int value)
+ {
+ mValue = value;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "protocol")
+ public Protocol getProtocol()
+ {
+ return mProtocol;
+ }
+
+ public void setProtocol(Protocol protocol)
+ {
+ mProtocol = protocol;
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return mValue != 0;
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("Talkgroup:").append(mValue).append(" Protocol:").append((mProtocol != null ? mProtocol : "(unspecified)"));
+
+ if(!isValid())
+ {
+ sb.append(" **NOT VALID**");
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ if(id instanceof Talkgroup)
+ {
+ Talkgroup tgid = (Talkgroup)id;
+ return (getProtocol() == tgid.getProtocol()) && (getValue() == tgid.getValue());
+ }
+
+ return false;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.TALKGROUP;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java
new file mode 100644
index 00000000..68132da5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java
@@ -0,0 +1,164 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.talkgroup;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import io.github.dsheirer.protocol.Protocol;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class TalkgroupEditor extends DocumentListenerEditor
+{
+ private final static Logger mLog = LoggerFactory.getLogger(TalkgroupEditor.class);
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT =
+ "
Talkgroup Identifier
";
+
+ private JComboBox mComboProtocol;
+ private JFormattedTextField mTalkgroupField;
+
+ public TalkgroupEditor(AliasID aliasID)
+ {
+ initGUI();
+ setItem(aliasID);
+ }
+
+ private void initGUI()
+ {
+ setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
+
+ add(new JLabel("Protocol:"));
+
+ mComboProtocol = new JComboBox();
+
+ DefaultComboBoxModel model = new DefaultComboBoxModel<>();
+
+ for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
+ {
+ model.addElement(protocol);
+ }
+
+ mComboProtocol.setModel(model);
+ mComboProtocol.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ Protocol selected = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
+ setModified(true);
+// ValidatingEditor editor = DecoderFactory.getEditor(selected, mChannelMapModel);
+// setEditor(editor);
+ }
+ });
+
+ add(mComboProtocol);
+
+ add(new JLabel("Value:"));
+
+ mTalkgroupField = new JFormattedTextField();
+ mTalkgroupField.setColumns(10);
+ mTalkgroupField.setValue(new Integer(0));
+ mTalkgroupField.getDocument().addDocumentListener(this);
+ mTalkgroupField.setToolTipText(HELP_TEXT);
+ add(mTalkgroupField, "growx,push");
+
+ JLabel help = new JLabel("Help ...");
+ help.setForeground(Color.BLUE.brighter());
+ help.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ help.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JOptionPane.showMessageDialog(TalkgroupEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ add(help, "align left");
+ }
+
+ public Talkgroup getTalkgroup()
+ {
+ if(getItem() instanceof Talkgroup)
+ {
+ return (Talkgroup)getItem();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setItem(AliasID aliasID)
+ {
+ super.setItem(aliasID);
+
+ Talkgroup talkgroup = getTalkgroup();
+
+ if(talkgroup != null)
+ {
+ mComboProtocol.setSelectedItem(talkgroup.getProtocol());
+ mTalkgroupField.setValue(new Integer(talkgroup.getValue()));
+ }
+
+ setModified(false);
+
+ repaint();
+ }
+
+ @Override
+ public void save()
+ {
+ Talkgroup talkgroup = getTalkgroup();
+
+ if(talkgroup != null)
+ {
+ Protocol selected = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
+ talkgroup.setProtocol(selected);
+
+ try
+ {
+ int value = ((Number)mTalkgroupField.getValue()).intValue();
+ talkgroup.setValue(value);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error parsing minimum talkgroup value from [" + mTalkgroupField.getValue() + "]");
+ }
+ }
+
+ setModified(false);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupIDEditor.java
deleted file mode 100644
index 8cf061c5..00000000
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupIDEditor.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.alias.id.talkgroup;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class TalkgroupIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT =
- "
Talkgroup Identifier
"
- + "P25: 4 or 6 hex characters (e.g. AB12 or ABC123) "
- + "LTR: A-HH-TTT where A=Area H=Home T=Talkgroup (0-01-128) "
- + "Passport: 5-digit number (12345 or 00023) "
- + " "
- + "Wildcard: use an asterisk (*) in place of each talkgroup digit (e.g. 0*1*5)"
- + "";
-
- private JTextField mTextField;
-
- public TalkgroupIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "Talkgroup:" ) );
-
- mTextField = new JTextField();
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( TalkgroupIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public TalkgroupID getTalkgroupID()
- {
- if( getItem() instanceof TalkgroupID )
- {
- return (TalkgroupID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- TalkgroupID talkgroup = getTalkgroupID();
-
- if( talkgroup != null )
- {
- mTextField.setText( talkgroup.getTalkgroup() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- TalkgroupID talkgroup = getTalkgroupID();
-
- if( talkgroup != null )
- {
- talkgroup.setTalkgroup( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java
new file mode 100644
index 00000000..ba0f92cd
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java
@@ -0,0 +1,129 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.talkgroup;
+
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+import io.github.dsheirer.protocol.Protocol;
+
+/**
+ * Integer talkgroup identifier range of values with protocol.
+ */
+public class TalkgroupRange extends AliasID
+{
+ private Protocol mProtocol;
+ private int mMinTalkgroup;
+ private int mMaxTalkgroup;
+
+ public TalkgroupRange()
+ {
+ //No arg JAXB constructor
+ }
+
+ /**
+ * Creates a talkgroup range of from - to talkgroup values (inclusive) for the specified protocol
+ * @param protocol for the talkgroup range
+ * @param minTalkgroup starting or minimum talkgroup value
+ * @param maxTalkgroup ending or maximum talkgroup value
+ */
+ public TalkgroupRange(Protocol protocol, int minTalkgroup, int maxTalkgroup)
+ {
+ mProtocol = protocol;
+ mMinTalkgroup = minTalkgroup;
+ mMaxTalkgroup = maxTalkgroup;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "min")
+ public int getMinTalkgroup()
+ {
+ return mMinTalkgroup;
+ }
+
+ public void setMinTalkgroup(int minTalkgroup)
+ {
+ mMinTalkgroup = minTalkgroup;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "max")
+ public int getMaxTalkgroup()
+ {
+ return mMaxTalkgroup;
+ }
+
+ public void setMaxTalkgroup(int maxTalkgroup)
+ {
+ mMaxTalkgroup = maxTalkgroup;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "protocol")
+ public Protocol getProtocol()
+ {
+ return mProtocol;
+ }
+
+ public void setProtocol(Protocol protocol)
+ {
+ mProtocol = protocol;
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return mProtocol != null && mMinTalkgroup != 0 && mMaxTalkgroup != 0 && mMinTalkgroup <= mMaxTalkgroup;
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("Talkgroup Range:").append(mMinTalkgroup).append(" to ").append(mMaxTalkgroup)
+ .append(" Protocol:").append(mProtocol == null ? "unspecified" : mProtocol);
+
+ if(!isValid())
+ {
+ sb.append(" **NOT VALID**");
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ if(id instanceof TalkgroupRange)
+ {
+ TalkgroupRange tgid = (TalkgroupRange)id;
+ return (getProtocol() == tgid.getProtocol()) &&
+ (getMinTalkgroup() == tgid.getMinTalkgroup()) &&
+ (getMaxTalkgroup() == tgid.getMaxTalkgroup());
+ }
+
+ return false;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.TALKGROUP_RANGE;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java
new file mode 100644
index 00000000..0f1c613b
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java
@@ -0,0 +1,185 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.alias.id.talkgroup;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.gui.editor.DocumentListenerEditor;
+import io.github.dsheirer.protocol.Protocol;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class TalkgroupRangeEditor extends DocumentListenerEditor
+{
+ private final static Logger mLog = LoggerFactory.getLogger(TalkgroupRangeEditor.class);
+ private static final long serialVersionUID = 1L;
+
+ private static final String HELP_TEXT =
+ "
Talkgroup Range Identifier
Identifies a range of talkgroup values";
+
+ private JComboBox mComboProtocol;
+ private JFormattedTextField mMinTalkgroupField;
+ private JFormattedTextField mMaxTalkgroupField;
+
+ public TalkgroupRangeEditor(AliasID aliasID)
+ {
+ initGUI();
+
+ setItem(aliasID);
+ }
+
+ private void initGUI()
+ {
+ setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
+
+ add(new JLabel("Protocol:"));
+
+ mComboProtocol = new JComboBox();
+
+ DefaultComboBoxModel model = new DefaultComboBoxModel<>();
+
+ for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
+ {
+ model.addElement(protocol);
+ }
+
+ mComboProtocol.setModel(model);
+ mComboProtocol.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ Protocol selected = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
+ setModified(true);
+// ValidatingEditor editor = DecoderFactory.getEditor(selected, mChannelMapModel);
+// setEditor(editor);
+ }
+ });
+
+ add(mComboProtocol);
+
+ add(new JLabel("Min:"));
+
+ mMinTalkgroupField = new JFormattedTextField();
+ mMinTalkgroupField.setColumns(10);
+ mMinTalkgroupField.setValue(new Integer(0));
+ mMinTalkgroupField.getDocument().addDocumentListener(this);
+ mMinTalkgroupField.setToolTipText(HELP_TEXT);
+ add(mMinTalkgroupField, "growx,push");
+
+ add(new JLabel("Max:"));
+
+ mMaxTalkgroupField = new JFormattedTextField();
+ mMaxTalkgroupField.setColumns(10);
+ mMaxTalkgroupField.setValue(new Integer(0));
+ mMaxTalkgroupField.getDocument().addDocumentListener(this);
+ mMaxTalkgroupField.setToolTipText(HELP_TEXT);
+ add(mMaxTalkgroupField, "growx,push");
+
+ JLabel help = new JLabel("Help ...");
+ help.setForeground(Color.BLUE.brighter());
+ help.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ help.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ JOptionPane.showMessageDialog(TalkgroupRangeEditor.this,
+ HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ add(help, "align left");
+ }
+
+ public TalkgroupRange getTalkgroupRange()
+ {
+ if(getItem() instanceof TalkgroupRange)
+ {
+ return (TalkgroupRange)getItem();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setItem(AliasID aliasID)
+ {
+ super.setItem(aliasID);
+
+ TalkgroupRange talkgroupRange = getTalkgroupRange();
+
+ if(talkgroupRange != null)
+ {
+ mComboProtocol.setSelectedItem(talkgroupRange.getProtocol());
+ mMinTalkgroupField.setValue(new Integer(talkgroupRange.getMinTalkgroup()));
+ mMaxTalkgroupField.setValue(new Integer(talkgroupRange.getMaxTalkgroup()));
+ }
+
+ setModified(false);
+
+ repaint();
+ }
+
+ @Override
+ public void save()
+ {
+ TalkgroupRange talkgroupRange = getTalkgroupRange();
+
+ if(talkgroupRange != null)
+ {
+ Protocol selected = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
+ talkgroupRange.setProtocol(selected);
+
+ try
+ {
+ int minTalkgroup = ((Number)mMinTalkgroupField.getValue()).intValue();
+ talkgroupRange.setMinTalkgroup(minTalkgroup);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error parsing minimum talkgroup value from [" + mMinTalkgroupField.getText() + "]");
+ }
+
+ try
+ {
+ int maxTalkgroup = ((Number)mMaxTalkgroupField.getValue()).intValue();
+ talkgroupRange.setMaxTalkgroup(maxTalkgroup);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error parsing maximum talkgroup value from [" + mMaxTalkgroupField.getText() + "]");
+ }
+ }
+
+ setModified(false);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java b/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
new file mode 100644
index 00000000..b243dc70
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
@@ -0,0 +1,111 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.audio;
+
+import io.github.dsheirer.audio.squelch.ISquelchStateListener;
+import io.github.dsheirer.identifier.IdentifierUpdateListener;
+import io.github.dsheirer.identifier.IdentifierUpdateNotification;
+import io.github.dsheirer.identifier.MutableIdentifierCollection;
+import io.github.dsheirer.module.Module;
+import io.github.dsheirer.sample.Listener;
+import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
+
+/**
+ * Base audio module implementation.
+ */
+public abstract class AbstractAudioModule extends Module implements IAudioPacketProvider, IdentifierUpdateListener,
+ ISquelchStateListener
+{
+ //Static unique audio channel identifier.
+ private static int AUDIO_CHANNEL_ID_GENERATOR = 1;
+
+ private int mAudioChannelId = AUDIO_CHANNEL_ID_GENERATOR++;
+ private Listener mAudioPacketListener;
+ private MutableIdentifierCollection mIdentifierCollection = new MutableIdentifierCollection();
+
+ /**
+ * Constructs an abstract audio module
+ */
+ public AbstractAudioModule()
+ {
+ }
+
+ /**
+ * Unique channel identifier for use in tagging audio packets with an audio channel ID so that they can
+ * be identified within a combined audio packet stream
+ */
+ public int getAudioChannelId()
+ {
+ return mAudioChannelId;
+ }
+
+ /**
+ * Receive updated identifiers from decoder state(s).
+ */
+ @Override
+ public Listener getIdentifierUpdateListener()
+ {
+ return mIdentifierCollection;
+ }
+
+ /**
+ * Identifier collection containing the current set of identifiers received from the decoder state(s).
+ */
+ public MutableIdentifierCollection getIdentifierCollection()
+ {
+ return mIdentifierCollection;
+ }
+
+ /**
+ * Registers an audio packet listener to receive the output from this audio module.
+ */
+ @Override
+ public void setAudioPacketListener(Listener listener)
+ {
+ mAudioPacketListener = listener;
+ }
+
+ /**
+ * Unregisters the audio packet listener from receiving audio packets from this module.
+ */
+ @Override
+ public void removeAudioPacketListener()
+ {
+ mAudioPacketListener = null;
+ }
+
+ /**
+ * Registered listener for receiving audio packets produced by this module
+ */
+ public Listener getAudioPacketListener()
+ {
+ return mAudioPacketListener;
+ }
+
+ /**
+ * Indicates if there is a listener registered to receive audio packets from this audio module.
+ */
+ public boolean hasAudioPacketListener()
+ {
+ return mAudioPacketListener != null;
+ }
+
+}
diff --git a/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java b/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java
new file mode 100644
index 00000000..4541195e
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java
@@ -0,0 +1,79 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.audio;
+
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Processes audio packets to assign attributes to each packet based on alias list settings. Updates the
+ * monitoring, recording and streaming attributes.
+ */
+public class AudioMetadataProcessor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(AudioMetadataProcessor.class);
+ private AliasModel mAliasModel;
+ private Map mAliasListMap = new HashMap<>();
+ private Set mAliasListRetrievedSet = new TreeSet<>();
+
+ public AudioMetadataProcessor(AliasModel aliasModel)
+ {
+ mAliasModel = aliasModel;
+ }
+
+ public void process(ReusableAudioPacket audioPacket)
+ {
+ if(audioPacket.hasIdentifierCollection() && audioPacket.getIdentifierCollection().hasAliasListConfiguration())
+ {
+ AliasList aliasList = null;
+
+ if(mAliasListRetrievedSet.contains(audioPacket.getAudioChannelId()))
+ {
+ aliasList = mAliasListMap.get(audioPacket.getAudioChannelId());
+ }
+ else
+ {
+ aliasList = mAliasModel.getAliasList(audioPacket.getIdentifierCollection().getAliasListConfiguration());
+
+ if(aliasList != null)
+ {
+ mAliasListMap.put(audioPacket.getAudioChannelId(), aliasList);
+ mAliasListRetrievedSet.add(audioPacket.getAudioChannelId());
+ }
+ }
+
+ if(aliasList != null)
+ {
+ audioPacket.addBroadcastChannels(aliasList.getBroadcastChannels(audioPacket.getIdentifierCollection()));
+ audioPacket.setRecordable(aliasList.isRecordable(audioPacket.getIdentifierCollection()));
+ audioPacket.setMonitoringPriority(aliasList.getAudioPlaybackPriority(audioPacket.getIdentifierCollection()));
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/audio/AudioModule.java b/src/main/java/io/github/dsheirer/audio/AudioModule.java
index 5e60c0ca..ceb0efe1 100644
--- a/src/main/java/io/github/dsheirer/audio/AudioModule.java
+++ b/src/main/java/io/github/dsheirer/audio/AudioModule.java
@@ -15,14 +15,11 @@
******************************************************************************/
package io.github.dsheirer.audio;
-import io.github.dsheirer.audio.squelch.ISquelchStateListener;
import io.github.dsheirer.audio.squelch.SquelchState;
-import io.github.dsheirer.channel.metadata.Metadata;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter2;
import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner;
-import io.github.dsheirer.module.Module;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.IReusableBufferListener;
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
@@ -39,12 +36,10 @@ import org.slf4j.LoggerFactory;
*
* This class is designed to support 8 kHz sample rate demodulated audio.
*/
-public class AudioModule extends Module implements IAudioPacketProvider, IReusableBufferListener,
- ISquelchStateListener, Listener
+public class AudioModule extends AbstractAudioModule implements IReusableBufferListener, Listener
{
- protected static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
- private ReusableAudioPacketQueue mAudioPacketQueue = new ReusableAudioPacketQueue("AudioModule");
+ private static final Logger mLog = LoggerFactory.getLogger(AudioModule.class);
private static float[] sHighPassFilterCoefficients;
static
@@ -73,32 +68,29 @@ public class AudioModule extends Module implements IAudioPacketProvider, IReusab
}
}
+ private ReusableAudioPacketQueue mAudioPacketQueue = new ReusableAudioPacketQueue("AudioModule");
private RealFIRFilter2 mHighPassFilter = new RealFIRFilter2(sHighPassFilterCoefficients);
private SquelchStateListener mSquelchStateListener = new SquelchStateListener();
private SquelchState mSquelchState = SquelchState.SQUELCH;
- private Listener mAudioPacketListener;
- private Metadata mMetadata;
/**
* Creates an Audio Module.
- *
- * @param metadata to use for audio packets produced by this audio module.
*/
- public AudioModule(Metadata metadata)
+ public AudioModule()
{
- mMetadata = metadata;
}
@Override
public void dispose()
{
- mAudioPacketListener = null;
+ removeAudioPacketListener();
mSquelchStateListener = null;
}
@Override
public void reset()
{
+ getIdentifierCollection().clear();
}
@Override
@@ -111,26 +103,17 @@ public class AudioModule extends Module implements IAudioPacketProvider, IReusab
public void stop()
{
/* Issue an end-audio packet in case a recorder is still rolling */
- if(mAudioPacketListener != null)
+ if(hasAudioPacketListener())
{
ReusableAudioPacket endAudioPacket = mAudioPacketQueue.getEndAudioBuffer();
- endAudioPacket.setMetadata(mMetadata.copyOf());
+ endAudioPacket.resetAttributes();
+ endAudioPacket.setAudioChannelId(getAudioChannelId());
+ endAudioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
endAudioPacket.incrementUserCount();
- mAudioPacketListener.receive(endAudioPacket);
+ getAudioPacketListener().receive(endAudioPacket);
}
}
- @Override
- public void setAudioPacketListener(Listener listener)
- {
- mAudioPacketListener = listener;
- }
-
- @Override
- public void removeAudioPacketListener()
- {
- mAudioPacketListener = null;
- }
@Override
public Listener getSquelchStateListener()
@@ -141,15 +124,17 @@ public class AudioModule extends Module implements IAudioPacketProvider, IReusab
@Override
public void receive(ReusableFloatBuffer reusableFloatBuffer)
{
- if(mAudioPacketListener != null && mSquelchState == SquelchState.UNSQUELCH)
+ if(hasAudioPacketListener() && mSquelchState == SquelchState.UNSQUELCH)
{
ReusableFloatBuffer highPassFiltered = mHighPassFilter.filter(reusableFloatBuffer);
ReusableAudioPacket audioPacket = mAudioPacketQueue.getBuffer(highPassFiltered.getSampleCount());
+ audioPacket.resetAttributes();
+ audioPacket.setAudioChannelId(getAudioChannelId());
audioPacket.loadAudioFrom(highPassFiltered);
- audioPacket.setMetadata(mMetadata.copyOf());
+ audioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
- mAudioPacketListener.receive(audioPacket);
+ getAudioPacketListener().receive(audioPacket);
highPassFiltered.decrementUserCount();
}
@@ -174,11 +159,13 @@ public class AudioModule extends Module implements IAudioPacketProvider, IReusab
@Override
public void receive(SquelchState state)
{
- if(state == SquelchState.SQUELCH && mAudioPacketListener != null)
+ if(state == SquelchState.SQUELCH && hasAudioPacketListener())
{
ReusableAudioPacket endAudioPacket = mAudioPacketQueue.getEndAudioBuffer();
- endAudioPacket.setMetadata(mMetadata.copyOf());
- mAudioPacketListener.receive(endAudioPacket);
+ endAudioPacket.resetAttributes();
+ endAudioPacket.setAudioChannelId(getAudioChannelId());
+ endAudioPacket.setIdentifierCollection(getIdentifierCollection().copyOf());
+ getAudioPacketListener().receive(endAudioPacket);
}
mSquelchState = state;
diff --git a/src/main/java/io/github/dsheirer/audio/AudioPacketManager.java b/src/main/java/io/github/dsheirer/audio/AudioPacketManager.java
new file mode 100644
index 00000000..e6c0ae36
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/audio/AudioPacketManager.java
@@ -0,0 +1,98 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.audio;
+
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.dsp.filter.channelizer.ContinuousReusableBufferProcessor;
+import io.github.dsheirer.sample.Listener;
+import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
+import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Processes audio packets from all decoder channels, assigns alias attributes and distributes packets
+ * for playback, streaming and recording.
+ */
+public class AudioPacketManager implements Listener
+{
+ private final static Logger mLog = LoggerFactory.getLogger(AudioPacketManager.class);
+ private AudioMetadataProcessor mAudioMetadataProcessor;
+ private ReusableBufferBroadcaster mBroadcaster = new ReusableBufferBroadcaster<>();
+ private ContinuousReusableBufferProcessor mBufferProcessor;
+
+ public AudioPacketManager(AliasModel aliasModel)
+ {
+ mAudioMetadataProcessor = new AudioMetadataProcessor(aliasModel);
+ mBufferProcessor = new ContinuousReusableBufferProcessor<>(10000, 500);
+ mBufferProcessor.setListener(new Listener>()
+ {
+ @Override
+ public void receive(List reusableAudioPackets)
+ {
+ for(ReusableAudioPacket audioPacket: reusableAudioPackets)
+ {
+ mAudioMetadataProcessor.process(audioPacket);
+ mBroadcaster.broadcast(audioPacket);
+ }
+ }
+ });
+ }
+
+ public void start()
+ {
+ mLog.info("Audio packet manager started");
+ mBufferProcessor.start();
+ }
+
+ public void stop()
+ {
+ mLog.info("Audio packet manager stopped");
+ mBufferProcessor.stop();
+ }
+
+ /**
+ * Primary processing method for receiving audio packets from all processing channels.
+ */
+ @Override
+ public void receive(ReusableAudioPacket audioPacket)
+ {
+ mBufferProcessor.receive(audioPacket);
+ }
+
+ /**
+ * Adds the listener to receive enriched audio packets from this manager
+ */
+ public void addListener(Listener listener)
+ {
+ mBroadcaster.addListener(listener);
+ }
+
+ /**
+ * Removes the listener from receiving enriched audio packets from this manager
+ */
+ public void removeListener(Listener listener)
+ {
+ mBroadcaster.removeListener(listener);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/audio/IAudioController.java b/src/main/java/io/github/dsheirer/audio/IAudioController.java
index a6fe007b..e374b3ce 100644
--- a/src/main/java/io/github/dsheirer/audio/IAudioController.java
+++ b/src/main/java/io/github/dsheirer/audio/IAudioController.java
@@ -1,6 +1,6 @@
package io.github.dsheirer.audio;
-import io.github.dsheirer.audio.output.AudioOutput;
+import io.github.dsheirer.audio.playback.AudioOutput;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
diff --git a/src/main/java/io/github/dsheirer/audio/InversionFrequency.java b/src/main/java/io/github/dsheirer/audio/InversionFrequency.java
deleted file mode 100644
index 071dc8bd..00000000
--- a/src/main/java/io/github/dsheirer/audio/InversionFrequency.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package io.github.dsheirer.audio;
-
-/**
- * Standard voice inversion foldover frequencies
- *
- * Reference: http://en.wikipedia.org/wiki/Voice_inversion
- */
-public enum InversionFrequency
-{
- HZ_2500( 2500 ),
- HZ_2550( 2550 ),
- HZ_2600( 2600 ),
- HZ_2632( 2632 ),
- HZ_2675( 2675 ),
- HZ_2718( 2718 ),
- HZ_2800( 2800 ),
- HZ_2868( 2868 ),
- HZ_2950( 2950 ),
- HZ_3023( 3023 ),
- HZ_3075( 3075 ),
- HZ_3107( 3107 ),
- HZ_3150( 3150 ),
- HZ_3196( 3196 ),
- HZ_3333( 3333 ),
- HZ_3339( 3339 ),
- HZ_3400( 3400 ),
- HZ_3496( 3496 ),
- HZ_3729( 3729 ),
- HZ_4096( 4096 );
-
- private int mFrequency;
-
- private InversionFrequency( int frequency )
- {
- mFrequency = frequency;
- }
-
- public int getFrequency()
- {
- return mFrequency;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
index 876e2ea9..2c48963f 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
@@ -19,7 +19,7 @@
package io.github.dsheirer.audio.broadcast;
import io.github.dsheirer.audio.convert.ISilenceGenerator;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.util.ThreadPool;
import org.slf4j.Logger;
@@ -99,15 +99,15 @@ public abstract class AudioBroadcaster implements Listener
/**
* Broadcasts the next song's audio metadata prior to streaming the next song.
*
- * @param metadata for the next recording that will be streamed
+ * @param identifierCollection for the next recording that will be streamed
*/
- protected void broadcastMetadata(Metadata metadata)
+ protected void broadcastMetadata(IdentifierCollection identifierCollection)
{
IBroadcastMetadataUpdater metadataUpdater = getMetadataUpdater();
if(metadataUpdater != null)
{
- metadataUpdater.update(metadata);
+ metadataUpdater.update(identifierCollection);
}
}
@@ -442,7 +442,7 @@ public abstract class AudioBroadcaster implements Listener
if(connected())
{
- broadcastMetadata(nextRecording.getMetadata());
+ broadcastMetadata(nextRecording.getIdentifierCollection());
}
metadataUpdateRequired = false;
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/AudioRecording.java b/src/main/java/io/github/dsheirer/audio/broadcast/AudioRecording.java
index 5edbe272..aa672063 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/AudioRecording.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/AudioRecording.java
@@ -18,7 +18,7 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.IdentifierCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,20 +33,20 @@ public class AudioRecording implements Comparable
private long mStartTime;
private long mRecordingLength;
private AtomicInteger mPendingReplayCount = new AtomicInteger();
- private Metadata mMetadata;
+ private IdentifierCollection mIdentifierCollection;
/**
* Audio recording that is ready to be streamed
*
* @param path to the audio recording file
- * @param metadata associated with the recording
+ * @param identifierCollection associated with the recording
* @param start time of recording in milliseconds since epoch
* @param recordingLength in milliseconds
*/
- public AudioRecording(Path path, Metadata metadata, long start, long recordingLength)
+ public AudioRecording(Path path, IdentifierCollection identifierCollection, long start, long recordingLength)
{
mPath = path;
- mMetadata = metadata;
+ mIdentifierCollection = identifierCollection;
mStartTime = start;
mRecordingLength = recordingLength;
}
@@ -60,11 +60,19 @@ public class AudioRecording implements Comparable
}
/**
- * Optional audio metadata for the recording.
+ * Optional audio metadata/identifiers for the recording.
*/
- public Metadata getMetadata()
+ public IdentifierCollection getIdentifierCollection()
{
- return mMetadata;
+ return mIdentifierCollection;
+ }
+
+ /**
+ * Indicates if this recording contains an optional identifier collection.
+ */
+ public boolean hasIdentifierCollection()
+ {
+ return mIdentifierCollection != null;
}
/**
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
index 85f6e43c..bacd227b 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
@@ -60,7 +60,7 @@ public class BroadcastFactory
* @param configuration describing the server and audio types
* @return configured broadcaster or null
*/
- public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration)
+ public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration, AliasModel aliasModel)
{
if(configuration != null)
{
@@ -71,15 +71,15 @@ public class BroadcastFactory
switch(configuration.getBroadcastServerType())
{
case BROADCASTIFY:
- return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration);
+ return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration, aliasModel);
case ICECAST_TCP:
- return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration);
+ return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration, aliasModel);
case ICECAST_HTTP:
- return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration);
+ return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration, aliasModel);
case SHOUTCAST_V1:
- return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration);
+ return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration, aliasModel);
case SHOUTCAST_V2:
- return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration);
+ return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration, aliasModel);
case UNKNOWN:
default:
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
index 986306fd..30d482e2 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
@@ -18,8 +18,9 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.channel.metadata.Metadata;
import io.github.dsheirer.icon.IconManager;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.sample.Broadcaster;
@@ -72,13 +73,15 @@ public class BroadcastModel extends AbstractTableModel implements Listener mBroadcasterMap = new HashMap<>();
private IconManager mIconManager;
private StreamManager mStreamManager;
+ private AliasModel mAliasModel;
private Broadcaster mBroadcastEventBroadcaster = new Broadcaster<>();
/**
* Model for managing Broadcast configurations and any associated broadcaster instances.
*/
- public BroadcastModel(IconManager iconManager)
+ public BroadcastModel(AliasModel aliasModel, IconManager iconManager)
{
+ mAliasModel = aliasModel;
mIconManager = iconManager;
mStreamManager = new StreamManager(new CompletedRecordingListener(), BroadcastFormat.MP3,
SystemProperties.getInstance().getApplicationFolder(TEMPORARY_STREAM_DIRECTORY));
@@ -278,9 +281,9 @@ public class BroadcastModel extends AbstractTableModel implements Listener
@Override
public void receive(ReusableAudioPacket audioPacket)
{
- if(mRunning.get() && audioPacket.hasMetadata())
+ if(mRunning.get() && audioPacket.hasIdentifierCollection())
{
synchronized(mStreamRecorders)
{
- int channelMetadataID = audioPacket.getMetadata().getMetadataID();
+ int channelMetadataID = audioPacket.getAudioChannelId();
ReusableAudioPacket.Type type = audioPacket.getType();
@@ -139,8 +139,7 @@ public class StreamManager implements Listener
}
else
{
- AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
- mBroadcastFormat);
+ AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(), mBroadcastFormat);
recorder.start();
audioPacket.incrementUserCount();
recorder.receive(audioPacket);
@@ -181,7 +180,7 @@ public class StreamManager implements Listener
public void receive(AudioRecorder audioRecorder)
{
AudioRecording audioRecording =
- new AudioRecording(audioRecorder.getPath(), audioRecorder.getMetadata(),
+ new AudioRecording(audioRecorder.getPath(), audioRecorder.getIdentifierCollection(),
audioRecorder.getTimeRecordingStart(), audioRecorder.getRecordingLength());
if(mAudioRecordingListener != null)
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastAudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastAudioBroadcaster.java
index 87bc5dae..3ce48058 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastAudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastAudioBroadcaster.java
@@ -18,6 +18,7 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.icecast;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
@@ -25,10 +26,12 @@ import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
{
private IBroadcastMetadataUpdater mMetadataUpdater;
+ private AliasModel mAliasModel;
- public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
+ public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, AliasModel aliasModel)
{
super(broadcastConfiguration);
+ mAliasModel = aliasModel;
}
/**
@@ -44,7 +47,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
{
if(mMetadataUpdater == null)
{
- mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration());
+ mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration(), mAliasModel);
}
return mMetadataUpdater;
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
index 924fd8ec..3c084c2b 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
@@ -18,8 +18,15 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.icecast;
+import io.github.dsheirer.alias.Alias;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.Form;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierClass;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.util.ThreadPool;
import org.apache.mina.core.RuntimeIoException;
@@ -52,7 +59,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
private final static String UTF8 = "UTF-8";
private IcecastConfiguration mIcecastConfiguration;
-
+ private AliasModel mAliasModel;
private NioSocketConnector mSocketConnector;
private AtomicBoolean mUpdating = new AtomicBoolean();
private Queue mMetadataQueue = new LinkedTransferQueue<>();
@@ -65,9 +72,10 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
* sequence, those updates will be queued and processed in the order received.
*/
- public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration)
+ public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration, AliasModel aliasModel)
{
mIcecastConfiguration = icecastConfiguration;
+ mAliasModel = aliasModel;
}
/**
@@ -113,9 +121,9 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
* and will remain in the update queue until the next metadata update is requested. However, this is a design
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
*/
- public void update(Metadata metadata)
+ public void update(IdentifierCollection identifierCollection)
{
- mMetadataQueue.offer(getSong(metadata));
+ mMetadataQueue.offer(getSong(identifierCollection));
if(!mUpdating.get() && !mMetadataQueue.isEmpty())
{
@@ -181,45 +189,54 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
/**
* Creates the song information for a metadata update
*/
- private static String getSong(Metadata metadata)
+ private String getSong(IdentifierCollection identifierCollection)
{
StringBuilder sb = new StringBuilder();
- if(metadata != null)
+ if(identifierCollection != null)
{
- String to = metadata.getPrimaryAddressTo().getIdentifier();
+ AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
- sb.append("TO:");
+ Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
- if(metadata.getPrimaryAddressTo().hasAlias())
+ if(to == null)
{
- sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
+ to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
}
- else if(metadata.getPrimaryAddressTo().hasIdentifier())
+
+ if(to != null)
{
- sb.append(metadata.getPrimaryAddressTo().getIdentifier());
+ sb.append("TO:").append(to);
+
+ Alias toAlias = aliasList != null ? aliasList.getAlias(to) : null;
+
+ if(toAlias != null)
+ {
+ sb.append(" ").append(toAlias.getName());
+ }
}
else
{
- sb.append("UNKNOWN");
+ sb.append("TO:UNKNOWN");
}
+ Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
- sb.append(" FROM:");
+ if(from != null)
+ {
+ sb.append(" FROM:").append(from);
- if(metadata.getPrimaryAddressFrom().hasAlias())
- {
- sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
- }
- else if(metadata.getPrimaryAddressFrom().hasIdentifier())
- {
- sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
+ Alias fromAlias = aliasList != null ? aliasList.getAlias(from) : null;
+
+ if(fromAlias != null)
+ {
+ sb.append(" ").append(fromAlias.getName());
+ }
}
else
{
- sb.append("UNKNOWN");
+ sb.append(" FROM:UNKNOWN");
}
-
}
else
{
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
index 3655dc20..2f72a8f6 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
@@ -18,6 +18,7 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.icecast;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.BroadcastState;
import io.github.dsheirer.audio.convert.MP3AudioConverter;
import io.github.dsheirer.properties.SystemProperties;
@@ -69,9 +70,9 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
*
* @param configuration for the Icecast stream
*/
- public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration)
+ public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration, AliasModel aliasModel)
{
- super(configuration);
+ super(configuration, aliasModel);
}
/**
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
index 8618d6b2..fe496762 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
@@ -18,6 +18,7 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.icecast;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.BroadcastState;
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
import io.github.dsheirer.audio.convert.MP3AudioConverter;
@@ -65,9 +66,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
*
* @param configuration for the Icecast stream
*/
- public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration)
+ public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration, AliasModel aliasModel)
{
- super(configuration);
+ super(configuration, aliasModel);
}
/**
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
index 7dea307a..e3d3f0c9 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
@@ -18,6 +18,7 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.shoutcast.v1;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
import io.github.dsheirer.audio.broadcast.BroadcastState;
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
@@ -47,7 +48,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
private NioSocketConnector mSocketConnector;
private IoSession mStreamingSession = null;
private IBroadcastMetadataUpdater mMetadataUpdater;
-
+ private AliasModel mAliasModel;
private long mLastConnectionAttempt = 0;
private AtomicBoolean mConnecting = new AtomicBoolean();
@@ -61,9 +62,10 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
*
* @param configuration for the Shoutcast stream
*/
- public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration)
+ public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration, AliasModel aliasModel)
{
super(configuration);
+ mAliasModel = aliasModel;
}
/**
@@ -79,7 +81,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
{
if(mMetadataUpdater == null)
{
- mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration());
+ mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration(), mAliasModel);
}
return mMetadataUpdater;
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
index faf672d1..f1865ba4 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
@@ -18,8 +18,15 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.shoutcast.v1;
+import io.github.dsheirer.alias.Alias;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.Form;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierClass;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.util.ThreadPool;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
@@ -50,7 +57,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
private final static String UTF8 = "UTF-8";
private ShoutcastV1Configuration mShoutcastV1Configuration;
-
+ private AliasModel mAliasModel;
private NioSocketConnector mSocketConnector;
private AtomicBoolean mUpdating = new AtomicBoolean();
private Queue mMetadataQueue = new LinkedTransferQueue<>();
@@ -62,9 +69,10 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
* sequence, those updates will be queued and processed in the order received.
*/
- public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration)
+ public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration, AliasModel aliasModel)
{
mShoutcastV1Configuration = shoutcastV1Configuration;
+ mAliasModel = aliasModel;
}
/**
@@ -111,9 +119,9 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
* and will remain in the update queue until the next metadata update is requested. However, this is a design
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
*/
- public void update(Metadata metadata)
+ public void update(IdentifierCollection identifierCollection)
{
- mMetadataQueue.offer(getSong(metadata));
+ mMetadataQueue.offer(getSong(identifierCollection));
if(mUpdating.compareAndSet(false, true))
{
@@ -177,45 +185,52 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
/**
* Creates the song information for a metadata update
*/
- private static String getSong(Metadata metadata)
+ private String getSong(IdentifierCollection identifierCollection)
{
StringBuilder sb = new StringBuilder();
- if(metadata != null)
+ if(identifierCollection != null)
{
- String to = metadata.getPrimaryAddressTo().getIdentifier();
+ AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
- sb.append("TO:");
+ Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
- if(metadata.getPrimaryAddressTo().hasAlias())
+ if(to == null)
{
- sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
+ to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
}
- else if(metadata.getPrimaryAddressTo().hasIdentifier())
+
+ Alias toAlias = aliasList != null ? aliasList.getAlias(to) : null;
+
+ if(toAlias != null)
{
- sb.append(metadata.getPrimaryAddressTo().getIdentifier());
+ sb.append("TO:").append(toAlias.getName());
+ }
+ else if(to != null)
+ {
+ sb.append("TO:").append(to.toString());
}
else
{
- sb.append("UNKNOWN");
+ sb.append("TO:UNKNOWN");
}
+ Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
- sb.append(" FROM:");
+ Alias fromAlias = aliasList != null ? aliasList.getAlias(from) : null;
- if(metadata.getPrimaryAddressFrom().hasAlias())
+ if(fromAlias != null)
{
- sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
+ sb.append(" FROM:").append(fromAlias.getName());
}
- else if(metadata.getPrimaryAddressFrom().hasIdentifier())
+ else if(from != null)
{
- sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
+ sb.append(" FROM:").append(from.toString());
}
else
{
- sb.append("UNKNOWN");
+ sb.append(" FROM:UNKNOWN");
}
-
}
else
{
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
index b0d3c377..ea31260a 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
@@ -18,6 +18,9 @@
******************************************************************************/
package io.github.dsheirer.audio.broadcast.shoutcast.v2;
+import io.github.dsheirer.alias.Alias;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.AudioBroadcaster;
import io.github.dsheirer.audio.broadcast.BroadcastState;
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
@@ -36,7 +39,11 @@ import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageF
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.Form;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierClass;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.util.ThreadPool;
import org.apache.mina.core.RuntimeIoException;
@@ -66,7 +73,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
private NioSocketConnector mSocketConnector;
private IoSession mStreamingSession = null;
-
+ private AliasModel mAliasModel;
private long mLastConnectionAttempt = 0;
private AtomicBoolean mConnecting = new AtomicBoolean();
private LinkedTransferQueue mMetadataMessageQueue = new LinkedTransferQueue<>();
@@ -83,9 +90,10 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
*
* @param configuration for the Shoutcast V2 stream
*/
- public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration)
+ public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration, AliasModel aliasModel)
{
super(configuration);
+ mAliasModel = aliasModel;
}
public ShoutcastV2Configuration getConfiguration()
@@ -119,9 +127,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
}
@Override
- public void update(Metadata metadata)
+ public void update(IdentifierCollection identifierCollection)
{
- List metadataMessages = getMetadataMessages(metadata);
+ List metadataMessages = getMetadataMessages(identifierCollection);
if(!metadataMessages.isEmpty())
{
@@ -241,10 +249,10 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
*
* See UltravoxMetadata.TAG.asXML(String value)
*
- * @param metadata containing audio metadata tags and attributes
+ * @param identifierCollection containing audio metadata tags and attributes
* @return a sequence of CacheableXMLMetadata messages sufficient to carry the complete set of metadata
*/
- private List getMetadataMessages(Metadata metadata)
+ private List getMetadataMessages(IdentifierCollection identifierCollection)
{
StringBuilder sb = new StringBuilder();
@@ -266,24 +274,37 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
sb.append(UltravoxMetadata.URL.asXML(getConfiguration().getURL()));
}
- if(metadata != null)
+ if(identifierCollection != null)
{
- if(metadata.getPrimaryAddressTo().hasAlias())
+ AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
+
+ Identifier to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.PATCH_GROUP, Role.TO);
+ if(to == null)
{
- sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName()));
- }
- else if(metadata.getPrimaryAddressTo().hasIdentifier())
- {
- sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
+ to = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.TO);
}
- if(metadata.getPrimaryAddressFrom().hasAlias())
+ Alias toAlias = aliasList != null ? aliasList.getAlias(to) : null;
+
+ if(toAlias != null)
{
- sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName()));
+ sb.append(UltravoxMetadata.TITLE_2.asXML(toAlias.getName()));
}
- else if(metadata.getPrimaryAddressFrom().hasIdentifier())
+ else if(to != null)
{
- sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier()));
+ sb.append(UltravoxMetadata.TITLE_2.asXML(to.toString()));
+ }
+
+ Identifier from = identifierCollection.getIdentifier(IdentifierClass.USER, Form.TALKGROUP, Role.FROM);
+ Alias fromAlias = aliasList != null ? aliasList.getAlias(from) : null;
+
+ if(fromAlias != null)
+ {
+ sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + fromAlias.getName()));
+ }
+ else if(from != null)
+ {
+ sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + from.toString()));
}
}
else
diff --git a/src/main/java/io/github/dsheirer/audio/invert/AudioInverter.java b/src/main/java/io/github/dsheirer/audio/invert/AudioInverter.java
index 63b6b6d9..f91ae5f7 100644
--- a/src/main/java/io/github/dsheirer/audio/invert/AudioInverter.java
+++ b/src/main/java/io/github/dsheirer/audio/invert/AudioInverter.java
@@ -17,7 +17,6 @@
******************************************************************************/
package io.github.dsheirer.audio.invert;
-import io.github.dsheirer.audio.InversionFrequency;
import io.github.dsheirer.dsp.filter.Filters;
import io.github.dsheirer.dsp.filter.FloatFIRFilter;
import io.github.dsheirer.dsp.mixer.IOscillator;
diff --git a/src/main/java/io/github/dsheirer/audio/invert/InversionFrequency.java b/src/main/java/io/github/dsheirer/audio/invert/InversionFrequency.java
new file mode 100644
index 00000000..5c0f4957
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/audio/invert/InversionFrequency.java
@@ -0,0 +1,61 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.invert;
+
+/**
+ * Standard voice inversion foldover frequencies
+ *
+ * Reference: http://en.wikipedia.org/wiki/Voice_inversion
+ */
+public enum InversionFrequency
+{
+ HZ_2500( 2500 ),
+ HZ_2550( 2550 ),
+ HZ_2600( 2600 ),
+ HZ_2632( 2632 ),
+ HZ_2675( 2675 ),
+ HZ_2718( 2718 ),
+ HZ_2800( 2800 ),
+ HZ_2868( 2868 ),
+ HZ_2950( 2950 ),
+ HZ_3023( 3023 ),
+ HZ_3075( 3075 ),
+ HZ_3107( 3107 ),
+ HZ_3150( 3150 ),
+ HZ_3196( 3196 ),
+ HZ_3333( 3333 ),
+ HZ_3339( 3339 ),
+ HZ_3400( 3400 ),
+ HZ_3496( 3496 ),
+ HZ_3729( 3729 ),
+ HZ_4096( 4096 );
+
+ private int mFrequency;
+
+ private InversionFrequency( int frequency )
+ {
+ mFrequency = frequency;
+ }
+
+ public int getFrequency()
+ {
+ return mFrequency;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/audio/AudioChannelPanel.java b/src/main/java/io/github/dsheirer/audio/playback/AudioChannelPanel.java
similarity index 53%
rename from src/main/java/io/github/dsheirer/audio/AudioChannelPanel.java
rename to src/main/java/io/github/dsheirer/audio/playback/AudioChannelPanel.java
index 7e6c1aa3..fbf05360 100644
--- a/src/main/java/io/github/dsheirer/audio/AudioChannelPanel.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/AudioChannelPanel.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,14 +15,24 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.audio;
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.playback;
+import com.google.common.eventbus.Subscribe;
import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.audio.output.AudioOutput;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.audio.AudioEvent;
+import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.icon.IconManager;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierClass;
+import io.github.dsheirer.identifier.IdentifierCollection;
+import io.github.dsheirer.identifier.Role;
+import io.github.dsheirer.preference.PreferenceType;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.preference.identifier.TalkgroupFormatPreference;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.settings.ColorSetting;
@@ -32,11 +43,15 @@ import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.util.List;
-public class AudioChannelPanel extends JPanel
- implements Listener, SettingChangeListener
+public class AudioChannelPanel extends JPanel implements Listener, SettingChangeListener
{
private static final long serialVersionUID = 1L;
private static final Logger mLog = LoggerFactory.getLogger(AudioChannelPanel.class);
@@ -56,27 +71,35 @@ public class AudioChannelPanel extends JPanel
private IconManager mIconManager;
private SettingsManager mSettingsManager;
+ private UserPreferences mUserPreferences;
+ private TalkgroupFormatPreference mTalkgroupFormatPreference;
private AudioOutput mAudioOutput;
private JLabel mMutedLabel = new JLabel("M");
private JLabel mChannelName = new JLabel(" ");
- private JLabel mToAlias = new JLabel(" ");
- private JLabel mTo = new JLabel("-----");
+ private JLabel mIconLabel = new JLabel(" ");
+ private JLabel mIdentifierLabel = new JLabel("-----");
+ private Identifier mIdentifier;
+ private Alias mAlias;
private boolean mConfigured = false;
+ private AliasModel mAliasModel;
- public AudioChannelPanel(IconManager iconManager, SettingsManager settingsManager, AudioOutput audioOutput)
+ public AudioChannelPanel(IconManager iconManager, UserPreferences userPreferences, SettingsManager settingsManager,
+ AudioOutput audioOutput, AliasModel aliasModel)
{
mIconManager = iconManager;
mSettingsManager = settingsManager;
mSettingsManager.addListener(this);
-
+ mAliasModel = aliasModel;
+ mUserPreferences = userPreferences;
+ mTalkgroupFormatPreference = mUserPreferences.getTalkgroupFormatPreference();
mAudioOutput = audioOutput;
if(mAudioOutput != null)
{
mAudioOutput.addAudioEventListener(this);
- mAudioOutput.setMetadataListener(new AudioMetadataProcessor());
+ mAudioOutput.setIdentifierCollectionListener(new AudioMetadataProcessor());
}
mBackgroundColor = SystemProperties.getInstance().get(PROPERTY_COLOR_BACKGROUND, Color.BLACK);
@@ -87,8 +110,30 @@ public class AudioChannelPanel extends JPanel
init();
}
+ /**
+ * Receives preference update notifications via the event bus
+ * @param preferenceType that was updated
+ */
+ @Subscribe
+ public void preferenceUpdated(PreferenceType preferenceType)
+ {
+ if(preferenceType == PreferenceType.IDENTIFIER)
+ {
+ updateLabels();
+ }
+ }
+
+ public void dispose()
+ {
+ //Deregister from receiving preference update notifications
+ MyEventBus.getEventBus().unregister(this);
+ }
+
private void init()
{
+ //Register to receive preference updates
+ MyEventBus.getEventBus().register(this);
+
setLayout(new MigLayout("align center center, insets 0 0 0 0",
"[][][align right]0[grow,fill]", ""));
setBackground(mBackgroundColor);
@@ -103,13 +148,13 @@ public class AudioChannelPanel extends JPanel
mChannelName.setForeground(mLabelColor);
add(mChannelName);
- mToAlias.setFont(mFont);
- mToAlias.setForeground(mValueColor);
- add(mToAlias);
+ mIconLabel.setFont(mFont);
+ mIconLabel.setForeground(mValueColor);
+ add(mIconLabel);
- mTo.setFont(mFont);
- mTo.setForeground(mValueColor);
- add(mTo,"wmin 10lp");
+ mIdentifierLabel.setFont(mFont);
+ mIdentifierLabel.setForeground(mValueColor);
+ add(mIdentifierLabel, "wmin 10lp");
}
@Override
@@ -149,72 +194,67 @@ public class AudioChannelPanel extends JPanel
*/
private void resetLabels()
{
- updateLabel(mTo, null, mToAlias, null);
-
+ mIdentifier = null;
+ mAlias = null;
+ updateLabels();
mConfigured = false;
}
+ /**
+ * Truncates the string to the specified length using an ellipses at the end
+ * @param value to optionally truncate
+ * @param length of the final formatted string
+ * @return formatted string or null
+ */
+ private static String truncate(String value, int length)
+ {
+ if(value != null && value.length() > length)
+ {
+ return value.substring(0, length - 3) + "...";
+ }
+
+ return value;
+ }
+
/**
* Updates the alias label with text and icon from the alias. Note: this
* does not occur on the Swing event thread -- wrap any calls to this
* method with an event thread call.
*/
- private void updateLabel(JLabel textLabel, String value, JLabel iconLabel, Alias alias)
+ private void updateLabels()
{
- if(value != null)
+ String identifier = mAlias != null ? mAlias.getName() : mTalkgroupFormatPreference.format(mIdentifier);
+ final ImageIcon icon = mAlias != null ? mIconManager.getIcon(mAlias.getIconName(), 18) : null;
+ final String identifierText = (identifier != null ? truncate(identifier, 33) : "-----");
+
+ EventQueue.invokeLater(new Runnable()
{
-
- if(alias != null)
+ @Override
+ public void run()
{
- iconLabel.setIcon(mIconManager.getIcon(alias.getIconName(), 18));
-
- String aliasName = alias.getName();
-
- //Truncate label if length exceeds 33 characters - hack!
- if(aliasName.length() > 33)
- {
- textLabel.setText(aliasName.substring(0,30) + "...");
- }
- else
- {
- textLabel.setText(aliasName);
- }
+ mIdentifierLabel.setText(identifierText);
+ mIconLabel.setIcon(icon);
+ mConfigured = true;
}
- else
- {
- iconLabel.setIcon(null);
- textLabel.setText(value);
- }
- }
- else
- {
- iconLabel.setIcon(null);
- textLabel.setText("-----");
- }
+ });
+
}
/**
* Processes audio metadata to update this panel's display values
*/
- public class AudioMetadataProcessor implements Listener
+ public class AudioMetadataProcessor implements Listener
{
@Override
- public void receive(final Metadata metadata)
+ public void receive(final IdentifierCollection identifierCollection)
{
- if(metadata.isUpdated() || !mConfigured)
+ if(identifierCollection != null && (identifierCollection.isUpdated() || !mConfigured))
{
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- updateLabel(mTo, metadata.getPrimaryAddressTo().getIdentifier(),
- mToAlias, metadata.getPrimaryAddressTo().getAlias());
-
- mConfigured = true;
- }
- });
-
+ List toIds = identifierCollection.getIdentifiers(IdentifierClass.USER, Role.TO);
+ mIdentifier = !toIds.isEmpty() ? toIds.get(0) : null;
+ AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
+ mAlias = (aliasList != null ? aliasList.getAlias(mIdentifier) : null);
+ updateLabels();
}
}
}
@@ -225,18 +265,18 @@ public class AudioChannelPanel extends JPanel
{
if(setting instanceof ColorSetting)
{
- ColorSetting colorSetting = (ColorSetting) setting;
+ ColorSetting colorSetting = (ColorSetting)setting;
switch(colorSetting.getColorSettingName())
{
case CHANNEL_STATE_LABEL_DECODER:
- if(mTo != null)
+ if(mIdentifierLabel != null)
{
- mTo.setForeground(mLabelColor);
+ mIdentifierLabel.setForeground(mLabelColor);
}
- if(mToAlias != null)
+ if(mIconLabel != null)
{
- mToAlias.setForeground(mLabelColor);
+ mIconLabel.setForeground(mLabelColor);
}
break;
default:
diff --git a/src/main/java/io/github/dsheirer/audio/AudioChannelsPanel.java b/src/main/java/io/github/dsheirer/audio/playback/AudioChannelsPanel.java
similarity index 58%
rename from src/main/java/io/github/dsheirer/audio/AudioChannelsPanel.java
rename to src/main/java/io/github/dsheirer/audio/playback/AudioChannelsPanel.java
index a3db071b..42e77155 100644
--- a/src/main/java/io/github/dsheirer/audio/AudioChannelsPanel.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/AudioChannelsPanel.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,24 +15,29 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.audio;
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.playback;
-import io.github.dsheirer.audio.output.AudioOutput;
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.audio.IAudioController;
import io.github.dsheirer.icon.IconManager;
+import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.settings.SettingsManager;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+import java.awt.Color;
+import java.awt.Component;
import java.util.List;
public class AudioChannelsPanel extends JPanel
{
private static final long serialVersionUID = 1L;
- public AudioChannelsPanel(IconManager iconManager, SettingsManager settingsManager, IAudioController controller)
+ public AudioChannelsPanel(IconManager iconManager, UserPreferences userPreferences, SettingsManager settingsManager,
+ IAudioController controller, AliasModel aliasModel)
{
setLayout(new MigLayout("insets 0 0 0 0", "[][sg abc,grow,fill][][sg abc,grow,fill]", "[grow,fill]"));
@@ -43,7 +49,7 @@ public class AudioChannelsPanel extends JPanel
for(int x = 0; x < outputs.size(); x++)
{
- add(new AudioChannelPanel(iconManager, settingsManager, outputs.get(x)));
+ add(new AudioChannelPanel(iconManager, userPreferences, settingsManager, outputs.get(x), aliasModel));
if(x < outputs.size() - 1)
{
@@ -56,7 +62,21 @@ public class AudioChannelsPanel extends JPanel
if(outputs.size() == 1)
{
addSeparator();
- add(new AudioChannelPanel(iconManager, settingsManager, null), "growx");
+ add(new AudioChannelPanel(iconManager, userPreferences, settingsManager, null, aliasModel), "growx");
+ }
+ }
+
+ /**
+ * Prepares for dispose to allow deregistering from services
+ */
+ public void dispose()
+ {
+ for(Component component: getComponents())
+ {
+ if(component instanceof AudioChannelPanel)
+ {
+ ((AudioChannelPanel)component).dispose();
+ }
}
}
diff --git a/src/main/java/io/github/dsheirer/audio/output/AudioOutput.java b/src/main/java/io/github/dsheirer/audio/playback/AudioOutput.java
similarity index 92%
rename from src/main/java/io/github/dsheirer/audio/output/AudioOutput.java
rename to src/main/java/io/github/dsheirer/audio/playback/AudioOutput.java
index fa0af9e6..45504cfd 100644
--- a/src/main/java/io/github/dsheirer/audio/output/AudioOutput.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/AudioOutput.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,12 +15,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.audio.output;
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.playback;
import io.github.dsheirer.audio.AudioEvent;
-import io.github.dsheirer.channel.metadata.Metadata;
+import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
@@ -54,7 +55,7 @@ public abstract class AudioOutput implements Listener, Line
private int mBufferStartThreshold;
private int mBufferStopThreshold;
- private Listener mMetadataListener;
+ private Listener mIdentifierCollectionListener;
private Broadcaster mAudioEventBroadcaster = new Broadcaster<>();
private ScheduledFuture> mProcessorTask;
@@ -85,10 +86,7 @@ public abstract class AudioOutput implements Listener, Line
* @param lineInfo to use when obtaining the source data line
* @param requestedBufferSize of approximately 1 second of audio
*/
- public AudioOutput(Mixer mixer,
- MixerChannel mixerChannel,
- AudioFormat audioFormat,
- Line.Info lineInfo,
+ public AudioOutput(Mixer mixer, MixerChannel mixerChannel, AudioFormat audioFormat, Line.Info lineInfo,
int requestedBufferSize)
{
mMixer = mixer;
@@ -174,7 +172,7 @@ public abstract class AudioOutput implements Listener, Line
mAudioEventBroadcaster.dispose();
mAudioEventBroadcaster = null;
- mMetadataListener = null;
+ mIdentifierCollectionListener = null;
if(mOutput != null)
{
@@ -233,24 +231,24 @@ public abstract class AudioOutput implements Listener, Line
* Registers a single listener to receive the audio metadata from each
* audio packet
*/
- public void setMetadataListener(Listener listener)
+ public void setIdentifierCollectionListener(Listener listener)
{
- mMetadataListener = listener;
+ mIdentifierCollectionListener = listener;
}
public void removeAudioMetadataListener()
{
- mMetadataListener = null;
+ mIdentifierCollectionListener = null;
}
/**
- * Broadcasts audio metadata to the registered listener
+ * Broadcasts audio identifier collection metadata to the registered listener
*/
- private void broadcast(Metadata metadata)
+ private void broadcast(IdentifierCollection identifierCollection)
{
- if(mMetadataListener != null)
+ if(mIdentifierCollectionListener != null)
{
- mMetadataListener.receive(metadata);
+ mIdentifierCollectionListener.receive(identifierCollection);
}
}
@@ -312,7 +310,7 @@ public abstract class AudioOutput implements Listener, Line
{
if(packet.getType() == ReusableAudioPacket.Type.AUDIO)
{
- broadcast(packet.getMetadata());
+ broadcast(packet.getIdentifierCollection());
ByteBuffer buffer = convert(packet);
diff --git a/src/main/java/io/github/dsheirer/audio/AudioPanel.java b/src/main/java/io/github/dsheirer/audio/playback/AudioPanel.java
similarity index 92%
rename from src/main/java/io/github/dsheirer/audio/AudioPanel.java
rename to src/main/java/io/github/dsheirer/audio/playback/AudioPanel.java
index 66d80147..5b2333f4 100644
--- a/src/main/java/io/github/dsheirer/audio/AudioPanel.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/AudioPanel.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,12 +15,16 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.audio;
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.playback;
-import io.github.dsheirer.audio.output.AudioOutput;
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.audio.AudioEvent;
+import io.github.dsheirer.audio.AudioException;
+import io.github.dsheirer.audio.IAudioController;
import io.github.dsheirer.icon.IconManager;
+import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.settings.SettingsManager;
import io.github.dsheirer.source.SourceManager;
@@ -60,17 +65,21 @@ public class AudioPanel extends JPanel implements Listener
private SettingsManager mSettingsManager;
private SourceManager mSourceManager;
private IAudioController mController;
+ private AliasModel mAliasModel;
+ private UserPreferences mUserPreferences;
private JButton mMuteButton;
private AudioChannelsPanel mAudioChannelsPanel;
- public AudioPanel(IconManager iconManager, SettingsManager settingsManager, SourceManager sourceManager,
- IAudioController controller)
+ public AudioPanel(IconManager iconManager, UserPreferences userPreferences, SettingsManager settingsManager,
+ SourceManager sourceManager, IAudioController controller, AliasModel aliasModel)
{
mIconManager = iconManager;
mSettingsManager = settingsManager;
mSourceManager = sourceManager;
mController = controller;
+ mAliasModel = aliasModel;
+ mUserPreferences = userPreferences;
mController.addControllerListener(this);
@@ -86,7 +95,7 @@ public class AudioPanel extends JPanel implements Listener
mMuteButton.setBackground(getBackground());
add(mMuteButton);
- mAudioChannelsPanel = new AudioChannelsPanel(mIconManager, mSettingsManager, mController);
+ mAudioChannelsPanel = new AudioChannelsPanel(mIconManager, mUserPreferences, mSettingsManager, mController, mAliasModel);
add(mAudioChannelsPanel);
@@ -107,13 +116,10 @@ public class AudioPanel extends JPanel implements Listener
public void run()
{
remove(mAudioChannelsPanel);
-
- mAudioChannelsPanel = new AudioChannelsPanel(mIconManager, mSettingsManager, mController);
-
+ mAudioChannelsPanel.dispose();
+ mAudioChannelsPanel = new AudioChannelsPanel(mIconManager, mUserPreferences, mSettingsManager, mController, mAliasModel);
add(mAudioChannelsPanel);
-
mAudioChannelsPanel.repaint();
-
revalidate();
repaint();
}
diff --git a/src/main/java/io/github/dsheirer/audio/AudioManager.java b/src/main/java/io/github/dsheirer/audio/playback/AudioPlaybackManager.java
similarity index 89%
rename from src/main/java/io/github/dsheirer/audio/AudioManager.java
rename to src/main/java/io/github/dsheirer/audio/playback/AudioPlaybackManager.java
index e48cf36a..449354d6 100644
--- a/src/main/java/io/github/dsheirer/audio/AudioManager.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/AudioPlaybackManager.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,13 +15,13 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.audio;
+ * *****************************************************************************
+ */
+package io.github.dsheirer.audio.playback;
-import io.github.dsheirer.audio.output.AudioOutput;
-import io.github.dsheirer.audio.output.MonoAudioOutput;
-import io.github.dsheirer.audio.output.StereoAudioOutput;
+import io.github.dsheirer.audio.AudioEvent;
+import io.github.dsheirer.audio.AudioException;
+import io.github.dsheirer.audio.IAudioController;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
@@ -44,9 +45,9 @@ import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-public class AudioManager implements Listener, IAudioController
+public class AudioPlaybackManager implements Listener, IAudioController
{
- private static final Logger mLog = LoggerFactory.getLogger(AudioManager.class);
+ private static final Logger mLog = LoggerFactory.getLogger(AudioPlaybackManager.class);
public static final int AUDIO_TIMEOUT = 1000; //1 second
@@ -79,7 +80,7 @@ public class AudioManager implements Listener, IAudioContro
* packets to any combination of outputs based on any alias audio routing
* options specified by the user.
*/
- public AudioManager(MixerManager mixerManager)
+ public AudioPlaybackManager(MixerManager mixerManager)
{
mMixerManager = mixerManager;
@@ -185,9 +186,9 @@ public class AudioManager implements Listener, IAudioContro
for(AudioOutputConnection connection : mAudioOutputConnections)
{
- if(connection.isInactive() && mChannelConnectionMap.containsKey(connection.getChannelMetadataID()))
+ if(connection.isInactive() && mChannelConnectionMap.containsKey(connection.getAudioChannelId()))
{
- mChannelConnectionMap.remove(connection.getChannelMetadataID());
+ mChannelConnectionMap.remove(connection.getAudioChannelId());
connection.disconnect();
mAvailableConnectionCount++;
changed = true;
@@ -365,12 +366,12 @@ public class AudioManager implements Listener, IAudioContro
*/
private AudioOutputConnection getConnection(ReusableAudioPacket audioPacket)
{
- int channelMetadataID = audioPacket.getMetadata().getMetadataID();
+ int audioChannelId = audioPacket.getAudioChannelId();
//Use an existing connection
- if(mChannelConnectionMap.containsKey(channelMetadataID))
+ if(mChannelConnectionMap.containsKey(audioChannelId))
{
- return mChannelConnectionMap.get(channelMetadataID);
+ return mChannelConnectionMap.get(audioChannelId);
}
//Connect to an unused, available connection
@@ -380,8 +381,8 @@ public class AudioManager implements Listener, IAudioContro
{
if(connection.isDisconnected())
{
- connection.connect(channelMetadataID, audioPacket.getMetadata().getAudioPriority());
- mChannelConnectionMap.put(channelMetadataID, connection);
+ connection.connect(audioChannelId, audioPacket.getMonitoringPriority());
+ mChannelConnectionMap.put(audioChannelId, connection);
mAvailableConnectionCount--;
return connection;
}
@@ -390,17 +391,17 @@ public class AudioManager implements Listener, IAudioContro
//Preempt an existing lower priority connection and connect when this is a higher priority packet
else
{
- int priority = audioPacket.getMetadata().getAudioPriority();
+ int priority = audioPacket.getMonitoringPriority();
AudioOutputConnection connection = mLowestPriorityConnection;
if(connection != null && priority < connection.getPriority())
{
- mChannelConnectionMap.remove(connection.getChannelMetadataID());
+ mChannelConnectionMap.remove(connection.getAudioChannelId());
- connection.connect(channelMetadataID, priority);
+ connection.connect(audioChannelId, priority);
- mChannelConnectionMap.put(channelMetadataID, connection);
+ mChannelConnectionMap.put(audioChannelId, connection);
return connection;
}
@@ -427,7 +428,7 @@ public class AudioManager implements Listener, IAudioContro
for(ReusableAudioPacket packet : mPackets)
{
/* Don't process any packet's marked as do not monitor */
- if(!packet.getMetadata().isDoNotMonitor() && packet.getType() == ReusableAudioPacket.Type.AUDIO)
+ if(!packet.isDoNotMonitor() && packet.getType() == ReusableAudioPacket.Type.AUDIO)
{
AudioOutputConnection connection = getConnection(packet);
@@ -469,11 +470,11 @@ public class AudioManager implements Listener, IAudioContro
*/
public class AudioOutputConnection
{
- private static final int DISCONNECTED = -1;
+ private static final int DISCONNECTED = Integer.MIN_VALUE;
private AudioOutput mAudioOutput;
private int mPriority = 0;
- private int mChannelMetadataID = DISCONNECTED;
+ private int mAudioChannelId = DISCONNECTED;
public AudioOutputConnection(AudioOutput audioOutput)
{
@@ -482,9 +483,9 @@ public class AudioManager implements Listener, IAudioContro
public void receive(ReusableAudioPacket packet)
{
- if(packet.hasMetadata() && packet.getMetadata().getMetadataID() == mChannelMetadataID)
+ if(packet.hasIdentifierCollection() && packet.getAudioChannelId() == mAudioChannelId)
{
- int priority = packet.getMetadata().getAudioPriority();
+ int priority = packet.getMonitoringPriority();
if(mPriority != priority)
{
@@ -499,10 +500,10 @@ public class AudioManager implements Listener, IAudioContro
}
else
{
- if(packet.hasMetadata())
+ if(packet.hasIdentifierCollection())
{
- mLog.error("Received audio packet from channel metadata [" + packet.getMetadata().getMetadataID() +
- "] however this assignment is currently connected to metadata [" + mChannelMetadataID + "]");
+ mLog.error("Received audio packet from channel metadata [" + packet.getAudioChannelId() +
+ "] however this assignment is currently connected to metadata [" + mAudioChannelId + "]");
}
else
{
@@ -525,7 +526,7 @@ public class AudioManager implements Listener, IAudioContro
*/
public boolean isDisconnected()
{
- return mChannelMetadataID == DISCONNECTED;
+ return mAudioChannelId == DISCONNECTED;
}
/**
@@ -542,7 +543,7 @@ public class AudioManager implements Listener, IAudioContro
*/
public void connect(int source, int priority)
{
- mChannelMetadataID = source;
+ mAudioChannelId = source;
mPriority = priority;
updateLowestPriorityAssignment();
@@ -552,9 +553,9 @@ public class AudioManager implements Listener, IAudioContro
/**
* Currently connected source or -1 if disconnected
*/
- public int getChannelMetadataID()
+ public int getAudioChannelId()
{
- return mChannelMetadataID;
+ return mAudioChannelId;
}
/**
@@ -563,7 +564,7 @@ public class AudioManager implements Listener, IAudioContro
*/
public void disconnect()
{
- mChannelMetadataID = DISCONNECTED;
+ mAudioChannelId = DISCONNECTED;
mPriority = 0;
}
diff --git a/src/main/java/io/github/dsheirer/audio/output/MonoAudioOutput.java b/src/main/java/io/github/dsheirer/audio/playback/MonoAudioOutput.java
similarity index 98%
rename from src/main/java/io/github/dsheirer/audio/output/MonoAudioOutput.java
rename to src/main/java/io/github/dsheirer/audio/playback/MonoAudioOutput.java
index b1722b5f..2fad8bfc 100644
--- a/src/main/java/io/github/dsheirer/audio/output/MonoAudioOutput.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/MonoAudioOutput.java
@@ -16,7 +16,7 @@
* along with this program. If not, see
*
******************************************************************************/
-package io.github.dsheirer.audio.output;
+package io.github.dsheirer.audio.playback;
import io.github.dsheirer.audio.AudioFormats;
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
diff --git a/src/main/java/io/github/dsheirer/audio/output/StereoAudioOutput.java b/src/main/java/io/github/dsheirer/audio/playback/StereoAudioOutput.java
similarity index 98%
rename from src/main/java/io/github/dsheirer/audio/output/StereoAudioOutput.java
rename to src/main/java/io/github/dsheirer/audio/playback/StereoAudioOutput.java
index 7a7cc828..c8538c7f 100644
--- a/src/main/java/io/github/dsheirer/audio/output/StereoAudioOutput.java
+++ b/src/main/java/io/github/dsheirer/audio/playback/StereoAudioOutput.java
@@ -16,7 +16,7 @@
* along with this program. If not, see
*
******************************************************************************/
-package io.github.dsheirer.audio.output;
+package io.github.dsheirer.audio.playback;
import io.github.dsheirer.audio.AudioFormats;
import io.github.dsheirer.sample.buffer.ReusableAudioPacket;
diff --git a/src/main/java/io/github/dsheirer/bits/BinaryMessage.java b/src/main/java/io/github/dsheirer/bits/BinaryMessage.java
index 8ce03554..3a3e2cc6 100644
--- a/src/main/java/io/github/dsheirer/bits/BinaryMessage.java
+++ b/src/main/java/io/github/dsheirer/bits/BinaryMessage.java
@@ -1,17 +1,17 @@
/*******************************************************************************
* 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
******************************************************************************/
@@ -24,14 +24,14 @@ import java.util.BitSet;
public class BinaryMessage extends BitSet
{
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
/**
* Logical (ie constructed) size of this bitset, despite the actual size of
* the super bitset that this class is based on
*/
private int mSize = 0;
-
+
/**
* Pointer to the next fill index location, when adding bits to this bitset
* one at a time.
@@ -41,49 +41,49 @@ public class BinaryMessage extends BitSet
/**
* Bitset that buffers bits added one at a time, up to the size of the this
* bitset.
- *
+ *
* Note: the super class bitset behind this class may have a size larger
* that the size parameter specified.
* @param size
*/
-
+
/**
* Used for temporary storage of CRC check results when we're passing this
* message to an EDAC function.
*/
private CRC mCRC;
-
- public BinaryMessage( int size )
+
+ public BinaryMessage(int size)
{
- super( size );
+ super(size);
mSize = size;
}
-
+
/**
* Constructs a bitset buffer and preloads it with the bits contained in
* the bitsToPreload parameter. If the bitsToPreload are longer than the
* size of the bitset, only those bits that fit will be preloaded
- *
+ *
* @param size
* @param bitsToPreload
*/
- public BinaryMessage( int size, boolean[] bitsToPreload )
+ public BinaryMessage(int size, boolean[] bitsToPreload)
{
- this( size );
-
+ this(size);
+
int pointer = 0;
-
- while( !this.isFull() && pointer < bitsToPreload.length )
+
+ while(!this.isFull() && pointer < bitsToPreload.length)
{
try
{
- this.add( bitsToPreload[ pointer ] );
+ this.add(bitsToPreload[pointer]);
}
- catch( BitSetFullException e )
+ catch(BitSetFullException e)
{
e.printStackTrace();
}
-
+
pointer++;
}
}
@@ -91,17 +91,17 @@ public class BinaryMessage extends BitSet
/**
* Constructs a new BitSetBuffer from an existing one
*/
- private BinaryMessage( BinaryMessage toCopyFrom )
+ private BinaryMessage(BinaryMessage toCopyFrom)
{
- this( toCopyFrom.size() );
- this.or( toCopyFrom );
+ this(toCopyFrom.size());
+ this.or(toCopyFrom);
this.mPointer = toCopyFrom.pointer();
}
- public BinaryMessage( BitSet bitset, int size )
+ public BinaryMessage(BitSet bitset, int size)
{
- this( size );
- this.or( bitset );
+ this(size);
+ this.or(bitset);
this.mPointer = size - 1;
}
@@ -109,43 +109,43 @@ public class BinaryMessage extends BitSet
{
this(BitSet.valueOf(data), data.length * 8);
}
-
+
/**
* Returns a mew binary message containing the bits from (inclusive) to
* end (exclusive).
- *
+ *
* @param start
* @param end
* @return
*/
- public BinaryMessage getSubMessage( int start, int end )
+ public BinaryMessage getSubMessage(int start, int end)
{
- BitSet subset = this.get( start, end );
-
- return new BinaryMessage( subset, end - start );
+ BitSet subset = this.get(start, end);
+
+ return new BinaryMessage(subset, end - start);
}
-
+
public CRC getCRC()
{
- return mCRC;
+ return mCRC;
}
-
- public void setCRC( CRC crc )
+
+ public void setCRC(CRC crc)
{
- mCRC = crc;
+ mCRC = crc;
}
/**
* Indicates the number of bit errors that were corrected in this message.
*
- * @see CorrectedBinaryMessage subclass that supports setting this value
* @return number of corrected bits in this message
+ * @see CorrectedBinaryMessage subclass that supports setting this value
*/
public int getCorrectedBitCount()
{
return 0;
}
-
+
/**
* Current pointer index
*/
@@ -156,64 +156,66 @@ public class BinaryMessage extends BitSet
/**
* Sets the pointer to a specific value
+ *
* @param index
*/
- public void setPointer( int index )
+ public void setPointer(int index)
{
- mPointer = index;
+ mPointer = index;
}
/**
- * Moves the current pointer position left (negative adjustment) or
+ * Moves the current pointer position left (negative adjustment) or
* right (positive adjustment)
*/
- public void adjustPointer( int adjustment )
+ public void adjustPointer(int adjustment)
{
- mPointer += adjustment;
+ mPointer += adjustment;
}
/**
* Static method to construct a new BitSetBuffer, preloaded with the bits
* from the preload parameter, and then filled with the bits from the
* second bitsetbuffer parameter.
- *
+ *
* @param preloadBits - boolean array of bits to be prepended to the new
- * bitset
+ * bitset
* @param bitsetToAppend - full bitset to be appended to the residual bits array
* @return - new Bitset preloaded with residual bits and new bitset
*/
- public static BinaryMessage merge( boolean[] preloadBits, BinaryMessage bitsetToAppend )
+ public static BinaryMessage merge(boolean[] preloadBits, BinaryMessage bitsetToAppend)
{
- BinaryMessage returnValue = new BinaryMessage( preloadBits.length + bitsetToAppend.size(), preloadBits );
+ BinaryMessage returnValue = new BinaryMessage(preloadBits.length + bitsetToAppend.size(), preloadBits);
int pointer = 0;
-
- while( pointer < bitsetToAppend.size() && !returnValue.isFull() )
+
+ while(pointer < bitsetToAppend.size() && !returnValue.isFull())
{
try
{
- returnValue.add( bitsetToAppend.get( pointer ) );
+ returnValue.add(bitsetToAppend.get(pointer));
}
- catch( BitSetFullException e )
+ catch(BitSetFullException e)
{
e.printStackTrace();
}
-
+
pointer++;
}
-
+
return returnValue;
}
-
+
/**
* Returns a (new) copy of this bitsetbuffer
+ *
* @return
*/
public BinaryMessage copy()
{
- return new BinaryMessage( this );
+ return new BinaryMessage(this);
}
-
+
public boolean isFull()
{
return mPointer >= mSize;
@@ -229,10 +231,10 @@ public class BinaryMessage extends BitSet
{
return mSize;
}
-
- public void setSize( int size )
+
+ public void setSize(int size)
{
- mSize = size;
+ mSize = size;
}
/**
@@ -242,41 +244,57 @@ public class BinaryMessage extends BitSet
@Override
public void clear()
{
- this.clear( 0, mSize );
+ this.clear(0, mSize);
mPointer = 0;
}
/**
- * Adds a the bit parameters to this bitset, placing it in the index
+ * Adds a the bit parameters to this bitset, placing it in the index
* specified by mPointer, and incrementing mPointer to prepare for the next
* call to this method
+ *
* @param value
* @throws BitSetFullException - if the size specified at construction is
- * exceeded. Invoke full() to determine if the bitset is full either before
- * adding a new bit, or after adding a bit.
+ * exceeded. Invoke full() to determine if the bitset is full either before
+ * adding a new bit, or after adding a bit.
*/
- public void add( boolean value ) throws BitSetFullException
+ public void add(boolean value) throws BitSetFullException
{
- if( !isFull() )
+ if(!isFull())
{
- this.set( mPointer++, value );
+ this.set(mPointer++, value);
}
else
{
- throw new BitSetFullException( "bitset is full -- contains " +
- ( mPointer + 1 ) + "bits");
+ throw new BitSetFullException("bitset is full -- contains " +
+ (mPointer + 1) + "bits");
}
}
-
+
public String toString()
{
StringBuilder sb = new StringBuilder();
-
- for( int x = 0; x < mSize; x++ )
+
+ for(int x = 0; x < mSize; x++)
{
- sb.append( ( this.get( x ) ? "1" : "0" ) );
+ sb.append((this.get(x) ? "1" : "0"));
}
-
+
+ return sb.toString();
+ }
+
+ public String toHexString()
+ {
+ int pointer = 0;
+
+ StringBuilder sb = new StringBuilder();
+
+ while(pointer < size())
+ {
+ sb.append(getHex(pointer, pointer + 3, 1));
+ pointer += 4;
+ }
+
return sb.toString();
}
@@ -285,19 +303,20 @@ public class BinaryMessage extends BitSet
*/
public int[] toIntegerArray()
{
- int[] values = new int[ mSize ];
-
- for (int i = nextSetBit( 0 ); i >= 0 && i < mSize; i = nextSetBit( i+1 ) )
- {
- values[ i ] = 1;
- }
-
- return values;
+ int[] values = new int[mSize];
+
+ for(int i = nextSetBit(0); i >= 0 && i < mSize; i = nextSetBit(i + 1))
+ {
+ values[i] = 1;
+ }
+
+ return values;
}
/**
* Returns this message as a little endian byte array. Extra 0 bits will be padded to the end to make the overall
* length a multiple of 8.
+ *
* @return little endian message byte array
*/
public byte[] toByteArray()
@@ -306,7 +325,7 @@ public class BinaryMessage extends BitSet
if(length * 8 < size())
{
- length ++;
+ length++;
}
byte[] bytes = new byte[length];
@@ -321,59 +340,59 @@ public class BinaryMessage extends BitSet
return bytes;
}
-
+
/**
* Returns this bitset as a reversed bit order array of integer ones and zeros
* from the specified index range
*/
- public int[] toReverseIntegerArray( int start, int end )
+ public int[] toReverseIntegerArray(int start, int end)
{
- int[] values = new int[ end - start + 1 ];
-
- for (int i = nextSetBit( start ); i >= start && i <= end; i = nextSetBit( i+1 ) )
- {
- values[ end - i ] = 1;
- }
-
- return values;
+ int[] values = new int[end - start + 1];
+
+ for(int i = nextSetBit(start); i >= start && i <= end; i = nextSetBit(i + 1))
+ {
+ values[end - i] = 1;
+ }
+
+ return values;
}
-
+
/**
* Returns a boolean array from startIndex to end of the bitset
*/
- public boolean[] getBits( int startIndex )
+ public boolean[] getBits(int startIndex)
{
- return getBits( startIndex, mSize - 1 );
+ return getBits(startIndex, mSize - 1);
}
-
+
/**
* Returns a boolean array of the right-most bitCount number of bits
*/
- public boolean[] right( int bitCount )
+ public boolean[] right(int bitCount)
{
- return getBits( mSize - bitCount - 1 );
+ return getBits(mSize - bitCount - 1);
}
-
+
/**
* Returns a boolean array representing the bits located from startIndex
* through endIndex
*/
- public boolean[] getBits( int startIndex, int endIndex )
+ public boolean[] getBits(int startIndex, int endIndex)
{
boolean[] returnValue = null;
-
- if( startIndex >= 0 &&
- startIndex < endIndex &&
- endIndex < mSize )
+
+ if(startIndex >= 0 &&
+ startIndex < endIndex &&
+ endIndex < mSize)
{
- returnValue = new boolean[ endIndex - startIndex + 1 ];
+ returnValue = new boolean[endIndex - startIndex + 1];
int bitsetPointer = startIndex;
int returnPointer = 0;
-
- while( bitsetPointer <= endIndex )
+
+ while(bitsetPointer <= endIndex)
{
- returnValue[ returnPointer ] = this.get( bitsetPointer );
+ returnValue[returnPointer] = this.get(bitsetPointer);
bitsetPointer++;
returnPointer++;
}
@@ -381,42 +400,75 @@ public class BinaryMessage extends BitSet
return returnValue;
}
-
+
/**
* Returns the integer value represented by the bit array
+ *
* @param bits - an array of bit positions that will be treated as if they
- * were contiguous bits, with index 0 being the MSB and index
- * length - 1 being the LSB
+ * were contiguous bits, with index 0 being the MSB and index
+ * length - 1 being the LSB
* @return - integer value of the bit array
*/
- public int getInt( int[] bits )
+ public int getInt(int[] bits)
{
- if( bits.length > 32 )
- {
- throw new IllegalArgumentException( "Overflow - must be 32 bits "
- + "or less to fit into a primitive integer value" );
- }
+ if(bits.length > 32)
+ {
+ throw new IllegalArgumentException("Overflow - must be 32 bits "
+ + "or less to fit into a primitive integer value");
+ }
- int value = 0;
+ int value = 0;
- for( int index: bits )
- {
- value = Integer.rotateLeft( value, 1 );
-
- if( get( index ) )
- {
- value++;
- }
- }
-
- return value;
+ for(int index : bits)
+ {
+ value = Integer.rotateLeft(value, 1);
+
+ if(get(index))
+ {
+ value++;
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Returns the integer value represented by the bit array
+ *
+ * @param bits - an array of bit positions that will be treated as if they
+ * were contiguous bits, with index 0 being the MSB and index
+ * length - 1 being the LSB
+ * @param offset to apply to each of the bit position in the bits array.
+ * @return - integer value of the bit array
+ */
+ public int getInt(int[] bits, int offset)
+ {
+ if(bits.length > 32)
+ {
+ throw new IllegalArgumentException("Overflow - must be 32 bits "
+ + "or less to fit into a primitive integer value");
+ }
+
+ int value = 0;
+
+ for(int index : bits)
+ {
+ value = Integer.rotateLeft(value, 1);
+
+ if(get(index + offset))
+ {
+ value++;
+ }
+ }
+
+ return value;
}
public void setInt(int value, int[] indices)
{
for(int x = 0; x < indices.length; x++)
{
- int mask = 1<<(indices.length - x - 1);
+ int mask = 1 << (indices.length - x - 1);
if((value & mask) == mask)
{
@@ -431,36 +483,70 @@ public class BinaryMessage extends BitSet
/**
* Returns the byte value represented by the bit array
+ *
* @param bits - an array of bit positions that will be treated as if they
- * were contiguous bits, with index 0 being the MSB and index
- * length - 1 being the LSB
+ * were contiguous bits, with index 0 being the MSB and index
+ * length - 1 being the LSB
* @return - byte value of the bit array
*/
- public byte getByte( int[] bits )
+ public byte getByte(int[] bits)
{
- if( bits.length != 8 )
- {
- throw new IllegalArgumentException( "Invalid - there must be 8"
- + "indexes to form a proper byte" );
- }
+ if(bits.length != 8)
+ {
+ throw new IllegalArgumentException("Invalid - there must be 8"
+ + "indexes to form a proper byte");
+ }
- int value = 0;
+ int value = 0;
- for( int index: bits )
- {
- value = Integer.rotateLeft( value, 1 );
-
- if( get( index ) )
- {
- value++;
- }
- }
-
- return (byte)( value & 0xFF );
+ for(int index : bits)
+ {
+ value = Integer.rotateLeft(value, 1);
+
+ if(get(index))
+ {
+ value++;
+ }
+ }
+
+ return (byte)(value & 0xFF);
+ }
+
+ /**
+ * Returns the byte value represented by the bit array
+ *
+ * @param bits - an array of bit positions that will be treated as if they
+ * were contiguous bits, with index 0 being the MSB and index
+ * length - 1 being the LSB
+ * @param offset to apply to each of the bit positions
+ * @return - byte value of the bit array
+ */
+ public byte getByte(int[] bits, int offset)
+ {
+ if(bits.length != 8)
+ {
+ throw new IllegalArgumentException("Invalid - there must be 8"
+ + "indexes to form a proper byte");
+ }
+
+ int value = 0;
+
+ for(int index : bits)
+ {
+ value = Integer.rotateLeft(value, 1);
+
+ if(get(index + offset))
+ {
+ value++;
+ }
+ }
+
+ return (byte)(value & 0xFF);
}
/**
* Returns the byte value contained between index and index + 7 bit positions
+ *
* @param index specifying the start of the byte value
* @return byte value contained at index <> index + 7 bit positions
*/
@@ -512,390 +598,404 @@ public class BinaryMessage extends BitSet
/**
* Returns the long value represented by the bit array
+ *
* @param bits - an array of bit positions that will be treated as if they
- * were contiguous bits, with index 0 being the MSB and index
- * length - 1 being the LSB
+ * were contiguous bits, with index 0 being the MSB and index
+ * length - 1 being the LSB
* @return - integer value of the bit array
*/
- public long getLong( int[] bits )
+ public long getLong(int[] bits)
{
- if( bits.length > 64 )
- {
- throw new IllegalArgumentException( "Overflow - must be 64 bits "
- + "or less to fit into a primitive long value" );
- }
+ if(bits.length > 64)
+ {
+ throw new IllegalArgumentException("Overflow - must be 64 bits "
+ + "or less to fit into a primitive long value");
+ }
- long value = 0;
+ long value = 0;
- for( int index: bits )
- {
- value = Long.rotateLeft( value, 1 );
-
- if( get( index ) )
- {
- value++;
- }
- }
-
- return value;
+ for(int index : bits)
+ {
+ value = Long.rotateLeft(value, 1);
+
+ if(get(index))
+ {
+ value++;
+ }
+ }
+
+ return value;
}
-
-
+
/**
* Converts up to 63 bits from the bit array into an integer and then
* formats the value into hexadecimal, prefixing the value with zeros to
* provide a total length of digitDisplayCount;
- *
+ *
* @param bits
* @param digitDisplayCount
* @return
*/
- public String getHex( int[] bits, int digitDisplayCount )
+ public String getHex(int[] bits, int digitDisplayCount)
{
- if( bits.length <= 32 )
- {
- int value = getInt( bits );
-
- return String.format( "%0" + digitDisplayCount + "X", value );
- }
- else if( bits.length <= 64 )
- {
- long value = getLong( bits );
-
- return String.format( "%0" + digitDisplayCount + "X", value );
- }
- else
- {
- throw new IllegalArgumentException( "BitSetBuffer.getHex() "
- + "maximum array length is 63 bits" );
- }
+ if(bits.length <= 32)
+ {
+ int value = getInt(bits);
+
+ return String.format("%0" + digitDisplayCount + "X", value);
+ }
+ else if(bits.length <= 64)
+ {
+ long value = getLong(bits);
+
+ return String.format("%0" + digitDisplayCount + "X", value);
+ }
+ else
+ {
+ throw new IllegalArgumentException("BitSetBuffer.getHex() "
+ + "maximum array length is 63 bits");
+ }
}
- public String getHex( int msb, int lsb, int digitDisplayCount )
+ public String getHex(int msb, int lsb, int digitDisplayCount)
{
- int length = lsb - msb;
-
- if( length <= 32 )
- {
- int value = getInt( msb, lsb );
-
- return String.format( "%0" + digitDisplayCount + "X", value );
- }
- else if( length <= 64 )
- {
- long value = getLong( msb, lsb );
-
- return String.format( "%0" + digitDisplayCount + "X", value );
- }
- else
- {
- throw new IllegalArgumentException( "BitSetBuffer.getHex() "
- + "maximum array length is 64 bits" );
- }
+ int length = lsb - msb;
+
+ if(length <= 32)
+ {
+ int value = getInt(msb, lsb);
+
+ return String.format("%0" + digitDisplayCount + "X", value);
+ }
+ else if(length <= 64)
+ {
+ long value = getLong(msb, lsb);
+
+ return String.format("%0" + digitDisplayCount + "X", value);
+ }
+ else
+ {
+ throw new IllegalArgumentException("BitSetBuffer.getHex() "
+ + "maximum array length is 64 bits");
+ }
}
/**
* Returns the int value represented by the bit range. This method will
* parse the bits in big endian or little endian format. The start value
* represents the MSB and the end value represents the LSB of the value.
- *
+ *
* start < end: little endian interpretation
* end < start: big endian interpretation
- *
+ *
* @param start - MSB of the value
* @param end - LSB of the value
- *
* @return - int value of the bit range
*/
- public int getInt( int start, int end )
+ public int getInt(int start, int end)
{
- if( Math.abs( end - start ) > 32 )
- {
- throw new IllegalArgumentException( "Overflow - must be 32 bits "
- + "or less to fit into a primitive integer value" );
- }
-
- int value = 0;
+ if(Math.abs(end - start) > 32)
+ {
+ throw new IllegalArgumentException("Overflow - must be 32 bits "
+ + "or less to fit into a primitive integer value");
+ }
- if( start < end )
- {
- for( int x = start; x <= end; x++ )
- {
- value = Integer.rotateLeft( value, 1 );
+ int value = 0;
- if( get( x ) )
- {
- value++;;
- }
- }
- }
- else
- {
- for( int x = end; x >= start; x-- )
- {
- value = Integer.rotateLeft( value, 1 );
+ if(start < end)
+ {
+ for(int x = start; x <= end; x++)
+ {
+ value = Integer.rotateLeft(value, 1);
- if( get( x ) )
- {
- value++;;
- }
- }
- }
-
- return value;
+ if(get(x))
+ {
+ value++;
+ ;
+ }
+ }
+ }
+ else
+ {
+ for(int x = end; x >= start; x--)
+ {
+ value = Integer.rotateLeft(value, 1);
+
+ if(get(x))
+ {
+ value++;
+ ;
+ }
+ }
+ }
+
+ return value;
}
-
+
/**
* Returns the long value represented by the bit range. This method will
* parse the bits in big endian or little endian format. The start value
* represents the MSB and the end value represents the LSB of the value.
- *
+ *
* start < end: little endian interpretation
* end < start: big endian interpretation
- *
+ *
* @param start - MSB of the value
* @param end - LSB of the value
- *
* @return - long value of the bit range
*/
- public long getLong( int start, int end )
+ public long getLong(int start, int end)
{
- if( Math.abs( end - start ) > 64 )
- {
- throw new IllegalArgumentException( "Overflow - must be 64 bits "
- + "or less to fit into a primitive long value" );
- }
-
- long value = 0;
+ if(Math.abs(end - start) > 64)
+ {
+ throw new IllegalArgumentException("Overflow - must be 64 bits "
+ + "or less to fit into a primitive long value");
+ }
- if( start < end )
- {
- for( int x = start; x <= end; x++ )
- {
- value = Long.rotateLeft( value, 1 );
-
- if( get( x ) )
- {
- value++;
- }
- }
- }
- else
- {
- for( int x = end; x >= start; x-- )
- {
- value = Long.rotateLeft( value, 1 );
-
- if( get( x ) )
- {
- value++;
- }
- }
- }
-
- return value;
+ long value = 0;
+
+ if(start < end)
+ {
+ for(int x = start; x <= end; x++)
+ {
+ value = Long.rotateLeft(value, 1);
+
+ if(get(x))
+ {
+ value++;
+ }
+ }
+ }
+ else
+ {
+ for(int x = end; x >= start; x--)
+ {
+ value = Long.rotateLeft(value, 1);
+
+ if(get(x))
+ {
+ value++;
+ }
+ }
+ }
+
+ return value;
}
/**
* Creates a buffer of size=width and fills the buffer with the fill value
+ *
* @param width - size of the buffer
* @param fill - initial fill value
* @return - filled buffer
*/
- public static BinaryMessage getBuffer( int width, long fill )
- {
- BinaryMessage buffer = new BinaryMessage( width );
-
- buffer.load( 0, width, fill );
-
- return buffer;
- }
-
- /**
- * Loads the value into the buffer starting at the offset index, and
- * assuming that the value represents (width) number of bits. The MSB of
- * the value will be located at the offset and the LSB of the value will
- * be located at ( offset + width ).
- *
- * @param offset - starting bit index for the MSB of the value
- * @param width - representative bit width of the value
- * @param value - value to be loaded into the buffer
- */
- public void load( int offset, int width, long value )
- {
- for( int x = 0; x < width; x++ )
- {
- long mask = Long.rotateLeft( 1, width - x - 1 );
-
- if( ( mask & value ) == mask )
- {
- set( offset + x );
- }
- else
- {
- clear( offset + x );
- }
- }
- }
-
- /**
- * Generates an array of message bit position indexes to support accessing
- * a contiguous field value
- *
- * @param start - starting bit position of the field
- * @param length - field length
- * @return - array of field indexes
- */
- public static int[] getFieldIndexes( int start, int length, boolean bigEndian )
- {
- int[] checksumIndexes = new int[ length ];
-
- for( int x = 0; x < length; x++ )
- {
- if( bigEndian )
- {
- checksumIndexes[ length - x - 1 ] = start + x;
- }
- else
- {
- checksumIndexes[ x ] = start + x;
- }
- }
-
- return checksumIndexes;
- }
-
- /**
- * Creates a bitsetbuffer loaded from a string of zeros and ones
- *
- * @param message - string containing only zeros and ones
- * @return - loaded buffer
- */
- public static BinaryMessage load( String message )
- {
- if( !message.matches( "[01]*" ) )
- {
- throw new IllegalArgumentException(
- "Message must contain only zeros and ones" );
- }
-
- BinaryMessage buffer = new BinaryMessage( message.length() );
-
- for( int x = 0; x < message.length(); x++ )
- {
- if( message.substring( x, x + 1 ).contentEquals( "1" ) )
- {
- buffer.set( x );
- }
- }
-
- return buffer;
- }
-
- /**
- * Left rotates the bits between start and end indices, number of places.
- */
- public void rotateLeft( int places, int startIndex, int endIndex )
- {
- for( int x = 0; x < places; x++ )
- {
- rotateLeft( startIndex, endIndex );
- }
- }
-
- /**
- * Left rotates the bits between start and end and wraps the left-most
- * bit around to the end.
- */
- public void rotateLeft( int startIndex, int endIndex )
- {
- boolean wrapBit = get( startIndex );
-
- for( int x = startIndex; x < endIndex; x++ )
- {
- if( get( x + 1 ) )
- {
- set( x );
- }
- else
- {
- clear( x );
- }
- }
-
- if( wrapBit )
- {
- set( endIndex );
- }
- else
- {
- clear( endIndex );
- }
- }
-
- /**
- * Right rotates the bits between start and end indices, number of places.
- */
- public void rotateRight( int places, int startIndex, int endIndex )
- {
- for( int x = 0; x < places; x++ )
- {
- rotateRight( startIndex, endIndex );
- }
- }
-
- /**
- * Right rotates the bits between start and end and wraps the right-most
- * bit around to the start.
- */
- public void rotateRight( int startIndex, int endIndex )
- {
- boolean wrapBit = get( endIndex );
-
- for( int x = endIndex - 1; x >= startIndex; x-- )
- {
- if( get( x ) )
- {
- set( x + 1 );
- }
- else
- {
- clear( x + 1 );
- }
- }
-
- if( wrapBit )
- {
- set( startIndex );
- }
- else
- {
- clear( startIndex );
- }
- }
-
- /**
- * Performs exclusive or of the value against this bitset starting at the
- * offset position using width bits from the value.
- */
- public void xor( int offset, int width, int value )
- {
- BinaryMessage mask = new BinaryMessage( this.size() );
-
- mask.load( offset, width, value );
-
- this.xor( mask );
- }
-
- public static void main(String[] args)
+ public static BinaryMessage getBuffer(int width, long fill)
{
- BinaryMessage b = new BinaryMessage(32);
+ BinaryMessage buffer = new BinaryMessage(width);
- int[] indices = {2,3,7,8};
+ buffer.load(0, width, fill);
- b.setInt(0xF, indices);
+ return buffer;
+ }
- System.out.println(b.toString());
+ /**
+ * Loads the value into the buffer starting at the offset index, and
+ * assuming that the value represents (width) number of bits. The MSB of
+ * the value will be located at the offset and the LSB of the value will
+ * be located at ( offset + width ).
+ *
+ * @param offset - starting bit index for the MSB of the value
+ * @param width - representative bit width of the value
+ * @param value - value to be loaded into the buffer
+ */
+ public void load(int offset, int width, long value)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ long mask = Long.rotateLeft(1, width - x - 1);
+
+ if((mask & value) == mask)
+ {
+ set(offset + x);
+ }
+ else
+ {
+ clear(offset + x);
+ }
+ }
+ }
+
+ /**
+ * Loads the binary message into this message starting at the offset. Note: this method
+ * does not do any length checking for the message being loaded and if that message is longer
+ * than this message, it would be loaded outside of the size (length) boundary of this message, but will not
+ * produce an error.
+ *
+ * @param offset into this message to load the binary message
+ * @param binaryMessage to load
+ */
+ public void load(int offset, BinaryMessage binaryMessage)
+ {
+ for(int x = 0; x < binaryMessage.size(); x++)
+ {
+ if(binaryMessage.get(x))
+ {
+ set(x + offset);
+ }
+ else
+ {
+ clear(x + offset);
+ }
+ }
+ }
+
+ /**
+ * Generates an array of message bit position indexes to support accessing
+ * a contiguous field value
+ *
+ * @param start - starting bit position of the field
+ * @param length - field length
+ * @return - array of field indexes
+ */
+ public static int[] getFieldIndexes(int start, int length, boolean bigEndian)
+ {
+ int[] checksumIndexes = new int[length];
+
+ for(int x = 0; x < length; x++)
+ {
+ if(bigEndian)
+ {
+ checksumIndexes[length - x - 1] = start + x;
+ }
+ else
+ {
+ checksumIndexes[x] = start + x;
+ }
+ }
+
+ return checksumIndexes;
+ }
+
+ /**
+ * Creates a bitsetbuffer loaded from a string of zeros and ones
+ *
+ * @param message - string containing only zeros and ones
+ * @return - loaded buffer
+ */
+ public static BinaryMessage load(String message)
+ {
+ if(!message.matches("[01]*"))
+ {
+ throw new IllegalArgumentException(
+ "Message must contain only zeros and ones");
+ }
+
+ BinaryMessage buffer = new BinaryMessage(message.length());
+
+ for(int x = 0; x < message.length(); x++)
+ {
+ if(message.substring(x, x + 1).contentEquals("1"))
+ {
+ buffer.set(x);
+ }
+ }
+
+ return buffer;
+ }
+
+ /**
+ * Left rotates the bits between start and end indices, number of places.
+ */
+ public void rotateLeft(int places, int startIndex, int endIndex)
+ {
+ for(int x = 0; x < places; x++)
+ {
+ rotateLeft(startIndex, endIndex);
+ }
+ }
+
+ /**
+ * Left rotates the bits between start and end and wraps the left-most
+ * bit around to the end.
+ */
+ public void rotateLeft(int startIndex, int endIndex)
+ {
+ boolean wrapBit = get(startIndex);
+
+ for(int x = startIndex; x < endIndex; x++)
+ {
+ if(get(x + 1))
+ {
+ set(x);
+ }
+ else
+ {
+ clear(x);
+ }
+ }
+
+ if(wrapBit)
+ {
+ set(endIndex);
+ }
+ else
+ {
+ clear(endIndex);
+ }
+ }
+
+ /**
+ * Right rotates the bits between start and end indices, number of places.
+ */
+ public void rotateRight(int places, int startIndex, int endIndex)
+ {
+ for(int x = 0; x < places; x++)
+ {
+ rotateRight(startIndex, endIndex);
+ }
+ }
+
+ /**
+ * Right rotates the bits between start and end and wraps the right-most
+ * bit around to the start.
+ */
+ public void rotateRight(int startIndex, int endIndex)
+ {
+ boolean wrapBit = get(endIndex);
+
+ for(int x = endIndex - 1; x >= startIndex; x--)
+ {
+ if(get(x))
+ {
+ set(x + 1);
+ }
+ else
+ {
+ clear(x + 1);
+ }
+ }
+
+ if(wrapBit)
+ {
+ set(startIndex);
+ }
+ else
+ {
+ clear(startIndex);
+ }
+ }
+
+ /**
+ * Performs exclusive or of the value against this bitset starting at the
+ * offset position using width bits from the value.
+ */
+ public void xor(int offset, int width, int value)
+ {
+ BinaryMessage mask = new BinaryMessage(this.size());
+
+ mask.load(offset, width, value);
+
+ this.xor(mask);
}
}
diff --git a/src/main/java/io/github/dsheirer/bits/CorrectedBinaryMessage.java b/src/main/java/io/github/dsheirer/bits/CorrectedBinaryMessage.java
index a06f45af..a0465be1 100644
--- a/src/main/java/io/github/dsheirer/bits/CorrectedBinaryMessage.java
+++ b/src/main/java/io/github/dsheirer/bits/CorrectedBinaryMessage.java
@@ -62,4 +62,14 @@ public class CorrectedBinaryMessage extends BinaryMessage
{
mCorrectedBitCount = count;
}
+
+ /**
+ * Increases the current corrected bit count by the argument value.
+ * @param additionalCount to add to the current corrected bit count
+ */
+ public void incrementCorrectedBitCount(int additionalCount)
+ {
+ mCorrectedBitCount += additionalCount;
+ }
+
}
diff --git a/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java b/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java
index a46185ad..83c71e75 100644
--- a/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java
+++ b/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java
@@ -1,21 +1,25 @@
-/*******************************************************************************
- * sdr-trunk
+/*
+ * ******************************************************************************
+ * sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with this program.
- * If not, see
- *
- ******************************************************************************/
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.bits;
public interface IBinarySymbolProcessor
{
- void receive(boolean symbol);
+ void process(boolean symbol);
}
diff --git a/src/main/java/io/github/dsheirer/bits/MessageFramer.java b/src/main/java/io/github/dsheirer/bits/MessageFramer.java
index 27bdcabe..97fb43e4 100644
--- a/src/main/java/io/github/dsheirer/bits/MessageFramer.java
+++ b/src/main/java/io/github/dsheirer/bits/MessageFramer.java
@@ -1,18 +1,22 @@
-/*******************************************************************************
- * sdr-trunk
+/*
+ * ******************************************************************************
+ * sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with this program.
- * If not, see
- *
- ******************************************************************************/
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.bits;
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
@@ -37,9 +41,9 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
private boolean[] mSyncPattern;
private int mMessageLength;
private ISyncDetectListener mSyncDetectListener;
- private Broadcaster mBroadcaster = new Broadcaster();
- private List mMessageAssemblers = new ArrayList();
- private List mCompletedMessageAssemblers = new ArrayList();
+ private Broadcaster mBroadcaster = new Broadcaster<>();
+ private List mMessageAssemblers = new ArrayList<>();
+ private List mCompletedMessageAssemblers = new ArrayList<>();
private SyncPatternMatcher mMatcher;
public MessageFramer(boolean[] syncPattern, int messageLength)
@@ -63,10 +67,9 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
{
mBroadcaster.dispose();
mCompletedMessageAssemblers.clear();
- mMessageAssemblers.clear();
}
- public void receive(boolean bit)
+ public void process(boolean bit)
{
mMatcher.receive(bit);
@@ -99,7 +102,7 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
/* Notify any sync detect listener(s) */
if(mSyncDetectListener != null)
{
- mSyncDetectListener.syncDetected();
+ mSyncDetectListener.syncDetected(0);
}
}
}
@@ -108,20 +111,7 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
@Override
public void receive(Boolean bit)
{
- receive(bit);
- }
-
- /**
- * Causes all messages currently under assembly to be forcibly
- * sent (ie flushed) to all registered message listeners, and
- * subsequently, all assemblers to be deleted
- */
- public void flush()
- {
- for(MessageAssembler assembler : mMessageAssemblers)
- {
- assembler.flush();
- }
+ process(bit);
}
@Override
@@ -134,12 +124,12 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
* Allow a message listener to register with this framer to receive
* all framed messages
*/
- public void addMessageListener(Listener listener)
+ public void addMessageListener(Listener listener)
{
mBroadcaster.addListener(listener);
}
- public void removeMessageListener(Listener listener)
+ public void removeMessageListener(Listener listener)
{
mBroadcaster.removeListener(listener);
}
@@ -152,7 +142,6 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
mMessageAssemblers.add(assembler);
}
- @SuppressWarnings("unused")
private void removeMessageAssembler(MessageAssembler assembler)
{
mMessageAssemblers.remove(assembler);
@@ -169,12 +158,12 @@ public class MessageFramer implements IBinarySymbolProcessor, Listener,
*/
private class MessageAssembler implements Listener
{
- BinaryMessage mMessage;
+ CorrectedBinaryMessage mMessage;
boolean mComplete = false;
MessageAssembler(int messageLength)
{
- mMessage = new BinaryMessage(messageLength);
+ mMessage = new CorrectedBinaryMessage(messageLength);
}
MessageAssembler(int messageLength, boolean[] initialFill)
diff --git a/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java b/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java
index 4b4e8621..89e939d3 100644
--- a/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java
+++ b/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java
@@ -88,7 +88,6 @@ public class MultiSyncPatternMatcher
{
if(processor.checkSync(mBits))
{
- mSyncDetectListener.syncDetected();
mBitCount = 0;
}
}
@@ -100,6 +99,15 @@ public class MultiSyncPatternMatcher
}
}
+ /**
+ * Returns the number of bit errors for the current value against the sync pattern.
+ * @return
+ */
+ public long getCurrentValue()
+ {
+ return mBits;
+ }
+
/**
* Processes one bit before checking sync processors for a match.
*/
diff --git a/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java b/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java
index 6362e160..4322dbad 100644
--- a/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java
+++ b/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java
@@ -16,22 +16,19 @@
package io.github.dsheirer.bits;
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
+import org.apache.commons.lang3.Validate;
public class SoftSyncDetector implements ISyncProcessor
{
private ISyncDetectListener mListener;
private long mPattern;
private int mThreshold;
+ private int mBitErrorCount;
- public SoftSyncDetector(ISyncDetectListener listener, long pattern, int threshold)
+ public SoftSyncDetector(long pattern, int threshold, ISyncDetectListener listener)
{
- this(pattern, threshold);
-
+ Validate.notNull(listener, "Sync detect listener cannot be null");
mListener = listener;
- }
-
- public SoftSyncDetector(long pattern, int threshold)
- {
mPattern = pattern;
mThreshold = threshold;
}
@@ -46,12 +43,21 @@ public class SoftSyncDetector implements ISyncProcessor
{
long difference = value ^ mPattern;
- if((difference == 0 || Long.bitCount(difference) <= mThreshold) &&
- mListener != null)
+ if(difference == 0)
{
- mListener.syncDetected();
+ mListener.syncDetected(0);
return true;
}
+ else
+ {
+ mBitErrorCount = Long.bitCount(difference);
+
+ if(mBitErrorCount <= mThreshold)
+ {
+ mListener.syncDetected(mBitErrorCount);
+ return true;
+ }
+ }
return false;
}
diff --git a/src/main/java/io/github/dsheirer/bits/SyncDetector.java b/src/main/java/io/github/dsheirer/bits/SyncDetector.java
index aedaceec..25a8d30e 100644
--- a/src/main/java/io/github/dsheirer/bits/SyncDetector.java
+++ b/src/main/java/io/github/dsheirer/bits/SyncDetector.java
@@ -46,7 +46,7 @@ public class SyncDetector implements ISyncProcessor
{
if(mListener != null)
{
- mListener.syncDetected();
+ mListener.syncDetected(0);
}
return true;
diff --git a/src/main/java/io/github/dsheirer/channel/IChannelDescriptor.java b/src/main/java/io/github/dsheirer/channel/IChannelDescriptor.java
new file mode 100644
index 00000000..18a35963
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/channel/IChannelDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+package io.github.dsheirer.channel;
+
+import io.github.dsheirer.module.decode.p25.message.IFrequencyBand;
+import io.github.dsheirer.protocol.Protocol;
+
+/**
+ * Channel descriptor
+ */
+public interface IChannelDescriptor
+{
+ /**
+ * Downlink frequency for the channel
+ * @return frequency in hertz
+ */
+ long getDownlinkFrequency();
+
+ /**
+ * Uplink frequency for the channel
+ * @return frequency in hertz
+ */
+ long getUplinkFrequency();
+
+ /**
+ * Frequency band identifiers (0 - 15)
+ */
+ int[] getFrequencyBandIdentifiers();
+
+ /**
+ * Assigns the frequency band message to the channel to use in calculating the up/downlink frequencies
+ * @param bandIdentifier
+ */
+ void setFrequencyBand(IFrequencyBand bandIdentifier);
+
+ /**
+ * Indicates if the timeslot count is greater than 1;
+ */
+ boolean isTDMAChannel();
+
+ /**
+ * Number of timeslots. FDMA has 1 timeslot and TDMA has at least 2 timeslots
+ */
+ int getTimeslotCount();
+
+ /**
+ * Protocol associated with the channel
+ */
+ Protocol getProtocol();
+}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/AliasedIdentifier.java b/src/main/java/io/github/dsheirer/channel/metadata/AliasedIdentifier.java
deleted file mode 100644
index a9bf91f2..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/AliasedIdentifier.java
+++ /dev/null
@@ -1,111 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.alias.Alias;
-
-public class AliasedIdentifier
-{
- private String mIdentifier;
- private Alias mAlias;
-
- /**
- * Identifier and corresponding optional alias
- */
- public AliasedIdentifier()
- {
- }
-
- /**
- * Resets alias and value to null
- *
- * Package Private - should only be changed within MutableMetadata
- */
- void reset()
- {
- mIdentifier = null;
- mAlias = null;
- }
-
- /**
- * Identifier
- */
- public String getIdentifier()
- {
- return mIdentifier;
- }
-
- /**
- * Sets the identifier to the argument value
- *
- * Package Private - should only be changed within MutableMetadata
- */
- void setIdentifier(String identifier)
- {
- mIdentifier = identifier;
- }
-
- /**
- * Indicates if there is a non-null, non-empty identifier
- */
- public boolean hasIdentifier()
- {
- return mIdentifier != null && !mIdentifier.isEmpty();
- }
-
- /**
- * Alias for the identifier.
- */
- public Alias getAlias()
- {
- return mAlias;
- }
-
- /**
- * Sets the alias to the argument
- *
- * Package Private - should only be changed within MutableMetadata
- */
- void setAlias(Alias alias)
- {
- mAlias = alias;
- }
-
- /**
- * Indicates if there is an alias corresponding to the identifier
- */
- public boolean hasAlias()
- {
- return mAlias != null;
- }
-
- public AliasedIdentifier copyOf()
- {
- AliasedIdentifier copy = new AliasedIdentifier();
-
- copy.setAlias(mAlias);
-
- if(mIdentifier != null)
- {
- copy.setIdentifier(new String(mIdentifier));
- }
-
- return copy;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/AliasedIntegerAttributeMonitor.java b/src/main/java/io/github/dsheirer/channel/metadata/AliasedIntegerAttributeMonitor.java
deleted file mode 100644
index a79bfaf7..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/AliasedIntegerAttributeMonitor.java
+++ /dev/null
@@ -1,101 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.alias.AliasList;
-import io.github.dsheirer.alias.id.AliasIDType;
-import io.github.dsheirer.sample.Listener;
-
-import static io.github.dsheirer.alias.id.AliasIDType.LTR_NET_UID;
-import static io.github.dsheirer.alias.id.AliasIDType.STATUS;
-
-
-public class AliasedIntegerAttributeMonitor extends AttributeMonitor
-{
- private static final AliasIDType[] VALID_ID_TYPES = {STATUS, LTR_NET_UID};
-
- private AliasList mAliasList;
- private AliasIDType mAliasIDType;
-
- /**
- * Provides monitoring of a String attribute's values with occurrence heuristics enabled and alias lookup with each
- * change in the attribute's value.
- *
- * @param attribute to monitor
- * @param listener to receive change requests
- * @param aliasList to lookup alias from
- * @param aliasIDType to determine correct alias lookup method in alias list
- */
- public AliasedIntegerAttributeMonitor(Attribute attribute, Listener listener, AliasList aliasList,
- AliasIDType aliasIDType)
- {
- super(attribute, listener);
-
- if(!isValidIDType(aliasIDType))
- {
- throw new IllegalArgumentException("Alias ID Type [" + aliasIDType.name() + "] is not supported");
- }
- mAliasList = aliasList;
- mAliasIDType = aliasIDType;
- }
-
- /**
- * Indicates if the alias ID type is a supported/valid type for this monitor.
- */
- public static boolean isValidIDType(AliasIDType type)
- {
- for(AliasIDType validType: VALID_ID_TYPES)
- {
- if(type == validType)
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Lookup of the alias that corresponds to the value's alias ID type
- */
- @Override
- protected Alias getAlias()
- {
- Alias alias = null;
-
- if(mAliasList != null)
- {
- if(hasValue())
- {
- switch(mAliasIDType)
- {
- case STATUS:
- alias = mAliasList.getStatus(getValue());
- break;
- case LTR_NET_UID:
- alias = mAliasList.getUniqueID(getValue());
- break;
- }
- }
- }
-
- return alias;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/AliasedStringAttributeMonitor.java b/src/main/java/io/github/dsheirer/channel/metadata/AliasedStringAttributeMonitor.java
deleted file mode 100644
index 1f224478..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/AliasedStringAttributeMonitor.java
+++ /dev/null
@@ -1,121 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.alias.AliasList;
-import io.github.dsheirer.alias.id.AliasIDType;
-import io.github.dsheirer.sample.Listener;
-
-import static io.github.dsheirer.alias.id.AliasIDType.ESN;
-import static io.github.dsheirer.alias.id.AliasIDType.FLEETSYNC;
-import static io.github.dsheirer.alias.id.AliasIDType.MDC1200;
-import static io.github.dsheirer.alias.id.AliasIDType.MIN;
-import static io.github.dsheirer.alias.id.AliasIDType.MPT1327;
-import static io.github.dsheirer.alias.id.AliasIDType.SITE;
-import static io.github.dsheirer.alias.id.AliasIDType.TALKGROUP;
-
-
-public class AliasedStringAttributeMonitor extends AttributeMonitor
-{
- private static final AliasIDType[] VALID_ID_TYPES = {ESN, FLEETSYNC, MDC1200, MIN, MPT1327, SITE, TALKGROUP};
-
- private AliasList mAliasList;
- private AliasIDType mAliasIDType;
-
- /**
- * Provides monitoring of a String attribute's values with occurrence heuristics enabled and alias lookup with each
- * change in the attribute's value.
- *
- * @param attribute to monitor
- * @param listener to receive change requests
- * @param aliasList to lookup alias from
- * @param aliasIDType to determine correct alias lookup method in alias list
- */
- public AliasedStringAttributeMonitor(Attribute attribute, Listener listener, AliasList aliasList,
- AliasIDType aliasIDType)
- {
- super(attribute, listener);
-
- if(!isValidIDType(aliasIDType))
- {
- throw new IllegalArgumentException("Alias ID Type [" + aliasIDType.name() + "] is not supported");
- }
- mAliasList = aliasList;
- mAliasIDType = aliasIDType;
- }
-
- /**
- * Indicates if the alias ID type is a supported/valid type for this monitor.
- */
- public static boolean isValidIDType(AliasIDType type)
- {
- for(AliasIDType validType: VALID_ID_TYPES)
- {
- if(type == validType)
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Lookup of the alias that corresponds to the value's alias ID type
- */
- @Override
- protected Alias getAlias()
- {
- Alias alias = null;
-
- if(mAliasList != null)
- {
- if(hasValue())
- {
- switch(mAliasIDType)
- {
- case ESN:
- alias = mAliasList.getESNAlias(getValue());
- break;
- case FLEETSYNC:
- alias = mAliasList.getFleetsyncAlias(getValue());
- break;
- case MDC1200:
- alias = mAliasList.getMDC1200Alias(getValue());
- break;
- case MIN:
- alias = mAliasList.getMobileIDNumberAlias(getValue());
- break;
- case MPT1327:
- alias = mAliasList.getMPT1327Alias(getValue());
- break;
- case SITE:
- alias = mAliasList.getSiteID(getValue());
- break;
- case TALKGROUP:
- alias = mAliasList.getTalkgroupAlias(getValue());
- break;
- }
- }
- }
-
- return alias;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/AttributeMonitor.java b/src/main/java/io/github/dsheirer/channel/metadata/AttributeMonitor.java
deleted file mode 100644
index 6bc79da3..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/AttributeMonitor.java
+++ /dev/null
@@ -1,159 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.sample.Listener;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class AttributeMonitor
-{
- private Attribute mAttribute;
- private Listener mListener;
- private boolean mHeuristicsEnabled = true;
- private Map mOccurrenceCounts = new HashMap<>();
- private T mCurrentValue;
- private List mIllegalValues = new ArrayList<>();
-
- public AttributeMonitor(Attribute attribute, Listener listener)
- {
- mAttribute = attribute;
- mListener = listener;
- }
-
- /**
- * Processes the value and emits a change request if the value needs to be changed. If heuristics are enabled,
- * an internal mapping of values to occurrence counts is updated and a change is emitted once a value that is
- * different from the current value, has a higher occurrence count than the current value. If heuristics are
- * disabled, then a change is emitted at each change in the value.
- *
- * @param t type
- * @return true if the value was changed after processing
- */
- public boolean process(T t)
- {
- boolean changed = false;
-
- if(t != null && !mIllegalValues.contains(t))
- {
- if(mHeuristicsEnabled)
- {
- if(mOccurrenceCounts.containsKey(t))
- {
- mOccurrenceCounts.put(t, mOccurrenceCounts.get(t) + 1);
- }
- else
- {
- mOccurrenceCounts.put(t, 1);
- }
- }
-
- if(mCurrentValue == null)
- {
- mCurrentValue = t;
- changed = true;
- }
- else if(!mCurrentValue.equals(t))
- {
- if(mHeuristicsEnabled)
- {
- int count = mOccurrenceCounts.get(mCurrentValue);
-
- for(Map.Entry entry : mOccurrenceCounts.entrySet())
- {
- if(entry.getValue() > count)
- {
- count = entry.getValue();
- mCurrentValue = entry.getKey();
- changed = true;
- }
- }
- }
- else
- {
- mCurrentValue = t;
- changed = true;
- }
- }
-
- if(changed && mListener != null)
- {
- mListener.receive(new AttributeChangeRequest(mAttribute, getValue(), getAlias()));
- }
- }
-
- return changed;
- }
-
- /**
- * Alias for the current value. This class does not return an alias, but subclasses can return an alias that
- * is appropriate for the monitored attribute value.
- *
- * @return an optional alias for the current value
- */
- protected Alias getAlias()
- {
- return null;
- }
-
- /**
- * Resets the attribute value to null and resets occurrence heuristics.
- */
- public void reset()
- {
- mCurrentValue = null;
- mOccurrenceCounts.clear();
-
- if(mListener != null)
- {
- mListener.receive(new AttributeChangeRequest(mAttribute, null, null));
- }
- }
-
- /**
- * Adds a value to the internal list of illegal values. The monitor will not allow the attribute to be changed to
- * any values contained in this list.
- *
- * @param illegalValue to prevent for the monitored alias
- */
- public void addIllegalValue(T illegalValue)
- {
- mIllegalValues.add(illegalValue);
- }
-
- /**
- * Returns the current value or null if the monitor is newly started or reset.
- */
- public T getValue()
- {
- return mCurrentValue;
- }
-
- /**
- * Indicates if the current value is non-null
- */
- public boolean hasValue()
- {
- return mCurrentValue != null;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadata.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadata.java
new file mode 100644
index 00000000..591b1cbc
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadata.java
@@ -0,0 +1,336 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.channel.metadata;
+
+import io.github.dsheirer.alias.Alias;
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.alias.AliasModel;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierUpdateListener;
+import io.github.dsheirer.identifier.IdentifierUpdateNotification;
+import io.github.dsheirer.identifier.Role;
+import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.ChannelNameConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.DecoderTypeConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.FrequencyConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.SiteConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.SystemConfigurationIdentifier;
+import io.github.dsheirer.identifier.decoder.DecoderLogicalChannelNameIdentifier;
+import io.github.dsheirer.identifier.decoder.DecoderStateIdentifier;
+import io.github.dsheirer.sample.Listener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Channel metadata containing details about the channel configuration, decoder state and current
+ * set of decoded user identifiers (ie TO and FROM).
+ */
+public class ChannelMetadata implements Listener, IdentifierUpdateListener
+{
+ private final static Logger mLog = LoggerFactory.getLogger(ChannelMetadata.class);
+
+ private SystemConfigurationIdentifier mSystemConfigurationIdentifier;
+ private SiteConfigurationIdentifier mSiteConfigurationIdentifier;
+ private ChannelNameConfigurationIdentifier mChannelNameConfigurationIdentifier;
+ private FrequencyConfigurationIdentifier mFrequencyConfigurationIdentifier;
+ private DecoderStateIdentifier mDecoderStateIdentifier = DecoderStateIdentifier.IDLE;
+ private DecoderLogicalChannelNameIdentifier mDecoderLogicalChannelNameIdentifier;
+ private DecoderTypeConfigurationIdentifier mDecoderTypeConfigurationIdentifier;
+ private Identifier mFromIdentifier;
+ private Alias mFromIdentifierAlias;
+ private Identifier mToIdentifier;
+ private Alias mToIdentifierAlias;
+
+ private IChannelMetadataUpdateListener mIChannelMetadataUpdateListener;
+ private AliasModel mAliasModel;
+ private AliasList mAliasList;
+
+ public ChannelMetadata(AliasModel aliasModel)
+ {
+ mAliasModel = aliasModel;
+ }
+
+ @Override
+ public Listener getIdentifierUpdateListener()
+ {
+ return this;
+ }
+
+ /**
+ * System configuration identifier
+ */
+ public SystemConfigurationIdentifier getSystemConfigurationIdentifier()
+ {
+ return mSystemConfigurationIdentifier;
+ }
+
+ public boolean hasSystemConfigurationIdentifier()
+ {
+ return mSystemConfigurationIdentifier != null;
+ }
+
+ /**
+ * Site configuration identifier
+ */
+ public SiteConfigurationIdentifier getSiteConfigurationIdentifier()
+ {
+ return mSiteConfigurationIdentifier;
+ }
+
+ public boolean hasSiteConfigurationIdentifier()
+ {
+ return mSiteConfigurationIdentifier != null;
+ }
+
+ /**
+ * Channel configuration identifier
+ */
+ public ChannelNameConfigurationIdentifier getChannelNameConfigurationIdentifier()
+ {
+ return mChannelNameConfigurationIdentifier;
+ }
+
+ public boolean hasChannelConfigurationIdentifier()
+ {
+ return mChannelNameConfigurationIdentifier != null;
+ }
+
+ /**
+ * Logical channel name/number expoded by the decoder
+ */
+ public DecoderLogicalChannelNameIdentifier getDecoderLogicalChannelNameIdentifier()
+ {
+ return mDecoderLogicalChannelNameIdentifier;
+ }
+
+ public boolean hasDecoderLogicalChannelNameIdentifier()
+ {
+ return mDecoderLogicalChannelNameIdentifier != null;
+ }
+
+ /**
+ * Frequency configuration identifier
+ */
+ public FrequencyConfigurationIdentifier getFrequencyConfigurationIdentifier()
+ {
+ return mFrequencyConfigurationIdentifier;
+ }
+
+ public boolean hasFrequencyConfigurationIdentifier()
+ {
+ return mFrequencyConfigurationIdentifier != null;
+ }
+
+ /**
+ * Decoder state identifier
+ */
+ public DecoderStateIdentifier getDecoderStateIdentifier()
+ {
+ return mDecoderStateIdentifier;
+ }
+
+ public boolean hasDecoderStateIdentifier()
+ {
+ return mDecoderStateIdentifier != null;
+ }
+
+ /**
+ * Decoder type identifier
+ */
+ public DecoderTypeConfigurationIdentifier getDecoderTypeConfigurationIdentifier()
+ {
+ return mDecoderTypeConfigurationIdentifier;
+ }
+
+ public boolean hasDecoderTypeIdentifier()
+ {
+ return mDecoderTypeConfigurationIdentifier != null;
+ }
+
+ /**
+ * Current call event FROM identifier
+ */
+ public Identifier getFromIdentifier()
+ {
+ return mFromIdentifier;
+ }
+
+ public boolean hasFromIdentifier()
+ {
+ return mFromIdentifier != null;
+ }
+
+ /**
+ * Optional alias associated with the FROM identifier
+ */
+ public Alias getFromIdentifierAlias()
+ {
+ return mFromIdentifierAlias;
+ }
+
+ /**
+ * Current call event TO identifier
+ */
+ public Identifier getToIdentifier()
+ {
+ return mToIdentifier;
+ }
+
+ public boolean hasToIdentifier()
+ {
+ return mToIdentifier != null;
+ }
+
+ /**
+ * Optional alias associated with the TO identifier
+ */
+ public Alias getToIdentifierAlias()
+ {
+ return mToIdentifierAlias;
+ }
+
+ /**
+ * Registers the listener for receiving field update events
+ */
+ public void setUpdateEventListener(IChannelMetadataUpdateListener listener)
+ {
+ mIChannelMetadataUpdateListener = listener;
+ }
+
+ /**
+ * Deregisters the listener from receiving field update events
+ */
+ public void removeUpdateEventListener()
+ {
+ mIChannelMetadataUpdateListener = null;
+ }
+
+ /**
+ * Broadcasts this metadata and the field that has been updated
+ *
+ * @param field that has been updated
+ */
+ private void broadcastUpdate(ChannelMetadataField field)
+ {
+ if(mIChannelMetadataUpdateListener != null)
+ {
+ mIChannelMetadataUpdateListener.updated(this, field);
+ }
+ }
+
+ @Override
+ public void receive(IdentifierUpdateNotification update)
+ {
+ Identifier identifier = update.getIdentifier();
+
+ switch(identifier.getIdentifierClass())
+ {
+ case CONFIGURATION:
+ switch(identifier.getForm())
+ {
+ case ALIAS_LIST:
+ if(update.isAdded())
+ {
+ mAliasList = mAliasModel.getAliasList((AliasListConfigurationIdentifier)identifier);
+
+ if(mAliasList != null)
+ {
+ if(mToIdentifier != null)
+ {
+ mToIdentifierAlias = mAliasList.getAlias(mToIdentifier);
+ }
+ if(mFromIdentifier != null)
+ {
+ mFromIdentifierAlias = mAliasList.getAlias(mFromIdentifier);
+ }
+ }
+ }
+ break;
+ case CHANNEL:
+ mChannelNameConfigurationIdentifier = update.isAdded() ? (ChannelNameConfigurationIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.CONFIGURATION_CHANNEL);
+ break;
+ case CHANNEL_FREQUENCY:
+ mFrequencyConfigurationIdentifier = update.isAdded() ? (FrequencyConfigurationIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.CONFIGURATION_FREQUENCY);
+ break;
+ case DECODER_TYPE:
+ mDecoderTypeConfigurationIdentifier = update.isAdded() ? (DecoderTypeConfigurationIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.DECODER_TYPE);
+ break;
+ case SITE:
+ mSiteConfigurationIdentifier = update.isAdded() ? (SiteConfigurationIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.CONFIGURATION_SITE);
+ break;
+ case SYSTEM:
+ mSystemConfigurationIdentifier = update.isAdded() ? (SystemConfigurationIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.CONFIGURATION_SYSTEM);
+ break;
+ }
+ break;
+ case DECODER:
+ switch(identifier.getForm())
+ {
+ case CHANNEL_NAME:
+ mDecoderLogicalChannelNameIdentifier = update.isAdded() ? (DecoderLogicalChannelNameIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.DECODER_CHANNEL_NAME);
+ break;
+ case STATE:
+ mDecoderStateIdentifier = update.isAdded() ? (DecoderStateIdentifier)identifier : null;
+ broadcastUpdate(ChannelMetadataField.DECODER_STATE);
+ break;
+ }
+ break;
+ case USER:
+ if(identifier.getRole() == Role.FROM)
+ {
+ mFromIdentifier = update.isAdded() ? identifier : null;
+
+ if(mAliasList != null && mFromIdentifier != null)
+ {
+ mFromIdentifierAlias = mAliasList.getAlias(mFromIdentifier);
+ }
+ else
+ {
+ mFromIdentifierAlias = null;
+ }
+
+ broadcastUpdate(ChannelMetadataField.USER_FROM);
+ }
+ else if(identifier.getRole() == Role.TO)
+ {
+ mToIdentifier = update.isAdded() ? identifier : null;
+
+ if(mAliasList != null && mToIdentifier != null)
+ {
+ mToIdentifierAlias = mAliasList.getAlias(mToIdentifier);
+ }
+ else
+ {
+ mToIdentifierAlias = null;
+ }
+
+ broadcastUpdate(ChannelMetadataField.USER_TO);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataField.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataField.java
new file mode 100644
index 00000000..c68e800f
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataField.java
@@ -0,0 +1,34 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.channel.metadata;
+
+public enum ChannelMetadataField
+{
+ CONFIGURATION_CHANNEL,
+ CONFIGURATION_FREQUENCY,
+ CONFIGURATION_SITE,
+ CONFIGURATION_SYSTEM,
+ DECODER_CHANNEL_NAME,
+ DECODER_STATE,
+ DECODER_TYPE,
+ USER_FROM,
+ USER_TO;
+}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataModel.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataModel.java
index 6e400936..1be1ccef 100644
--- a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataModel.java
+++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataModel.java
@@ -15,44 +15,65 @@
******************************************************************************/
package io.github.dsheirer.channel.metadata;
-import io.github.dsheirer.channel.state.State;
+import com.google.common.eventbus.Subscribe;
+import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.controller.channel.Channel;
-import io.github.dsheirer.sample.Listener;
+import io.github.dsheirer.eventbus.MyEventBus;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.preference.PreferenceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.table.AbstractTableModel;
import java.awt.EventQueue;
-import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-public class ChannelMetadataModel extends AbstractTableModel implements Listener
+public class ChannelMetadataModel extends AbstractTableModel implements IChannelMetadataUpdateListener
{
private final static Logger mLog = LoggerFactory.getLogger(ChannelMetadataModel.class);
- private final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat( "#.00000" );
+ public static final int COLUMN_DECODER_STATE = 0;
+ public static final int COLUMN_DECODER_TYPE = 1;
+ public static final int COLUMN_USER_FROM = 2;
+ public static final int COLUMN_USER_FROM_ALIAS = 3;
+ public static final int COLUMN_USER_TO = 4;
+ public static final int COLUMN_USER_TO_ALIAS = 5;
+ public static final int COLUMN_DECODER_LOGICAL_CHANNEL_NAME = 6;
+ public static final int COLUMN_CONFIGURATION_FREQUENCY = 7;
+ public static final int COLUMN_CONFIGURATION_CHANNEL = 8;
- public static final int COLUMN_STATE = 0;
- public static final int COLUMN_DECODER = 1;
- public static final int COLUMN_CHANNEL = 2;
- public static final int COLUMN_FREQUENCY = 3;
- public static final int COLUMN_PRIMARY_FROM = 4;
- public static final int COLUMN_PRIMARY_TO = 5;
- public static final int COLUMN_SECONDARY_FROM = 6;
- public static final int COLUMN_SECONDARY_TO = 7;
- public static final int COLUMN_CONFIGURATION_NAME = 8;
- public static final int COLUMN_MESSAGE = 9;
+ private static final String[] COLUMNS = {"Status", "Decoder", "From", "Alias", "To", "Alias", "Channel", "Frequency", "Channel Name"};
- private static final String[] COLUMNS = {"Status", "Decoder", "Channel", "Frequency", "Primary From", "Primary To",
- "Secondary From", "Secondary To", "Channel Name", "Message"};
+ private List mChannelMetadata = new ArrayList();
+ private Map mMetadataChannelMap = new HashMap();
- private List mChannelMetadata = new ArrayList();
- private Map mMetadataChannelMap = new HashMap();
+ public ChannelMetadataModel()
+ {
+ MyEventBus.getEventBus().register(this);
+ }
- public void add(MutableMetadata metadata, Channel channel)
+ /**
+ * Receives preference update notifications via the event bus
+ * @param preferenceType that was updated
+ */
+ @Subscribe
+ public void preferenceUpdated(PreferenceType preferenceType)
+ {
+ if(preferenceType == PreferenceType.IDENTIFIER)
+ {
+ for(int row = 0; row < mChannelMetadata.size(); row++)
+ {
+ fireTableCellUpdated(row, COLUMN_USER_FROM);
+ fireTableCellUpdated(row, COLUMN_USER_TO);
+ }
+ }
+ }
+
+
+ public void add(ChannelMetadata channelMetadata, Channel channel)
{
//Execute on the swing thread to avoid threading issues
EventQueue.invokeLater(new Runnable()
@@ -60,19 +81,16 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
@Override
public void run()
{
- mChannelMetadata.add(metadata);
- mMetadataChannelMap.put(metadata, channel);
-
- int index = mChannelMetadata.indexOf(metadata);
-
+ mChannelMetadata.add(channelMetadata);
+ mMetadataChannelMap.put(channelMetadata, channel);
+ int index = mChannelMetadata.indexOf(channelMetadata);
fireTableRowsInserted(index, index);
-
- metadata.addListener(ChannelMetadataModel.this);
+ channelMetadata.setUpdateEventListener(ChannelMetadataModel.this);
}
});
}
- public void remove(MutableMetadata metadata)
+ public void remove(ChannelMetadata channelMetadata)
{
//Execute on the swing thread to avoid threading issues
EventQueue.invokeLater(new Runnable()
@@ -80,13 +98,10 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
@Override
public void run()
{
- metadata.removeListener(ChannelMetadataModel.this);
-
- int index = mChannelMetadata.indexOf(metadata);
-
- mChannelMetadata.remove(metadata);
- mMetadataChannelMap.remove(metadata);
-
+ channelMetadata.removeUpdateEventListener();
+ int index = mChannelMetadata.indexOf(channelMetadata);
+ mChannelMetadata.remove(channelMetadata);
+ mMetadataChannelMap.remove(channelMetadata);
fireTableRowsDeleted(index, index);
}
});
@@ -95,7 +110,7 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
/**
* Get the channel metadata at the specified model row index
*/
- public Metadata getMetadata(int row)
+ public ChannelMetadata getChannelMetadata(int row)
{
if(row < mChannelMetadata.size())
{
@@ -108,9 +123,9 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
/**
* Returns the channel that matches the metadata or null
*/
- public Channel getChannelFromMetadata(Metadata metadata)
+ public Channel getChannelFromMetadata(ChannelMetadata channelMetadata)
{
- return mMetadataChannelMap.get(metadata);
+ return mMetadataChannelMap.get(channelMetadata);
}
@Override
@@ -136,24 +151,14 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
{
switch(columnIndex)
{
- case COLUMN_STATE:
- return State.class;
-
- case COLUMN_DECODER:
- case COLUMN_CHANNEL:
- case COLUMN_FREQUENCY:
- case COLUMN_MESSAGE:
- case COLUMN_CONFIGURATION_NAME:
- return String.class;
-
- case COLUMN_PRIMARY_TO:
- case COLUMN_PRIMARY_FROM:
- case COLUMN_SECONDARY_TO:
- case COLUMN_SECONDARY_FROM:
- return MutableMetadata.class;
-
+ case COLUMN_USER_FROM:
+ case COLUMN_USER_TO:
+ return ChannelMetadata.class;
+ case COLUMN_USER_FROM_ALIAS:
+ case COLUMN_USER_TO_ALIAS:
+ return Alias.class;
default:
- return String.class;
+ return Identifier.class;
}
}
@@ -162,60 +167,28 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
{
if(rowIndex <= mChannelMetadata.size())
{
- Metadata metadata = mChannelMetadata.get(rowIndex);
+ ChannelMetadata channelMetadata = mChannelMetadata.get(rowIndex);
switch(columnIndex)
{
- case COLUMN_STATE:
- return metadata.getState();
- case COLUMN_DECODER:
- if(metadata.hasPrimaryDecoderType())
- {
- return metadata.getPrimaryDecoderType().getShortDisplayString();
- }
-
- return null;
- case COLUMN_CHANNEL:
- return metadata.getChannelFrequencyLabel();
- case COLUMN_FREQUENCY:
- if(metadata.hasChannelFrequency())
- {
- return FREQUENCY_FORMATTER.format((double)metadata.getChannelFrequency() / 1E6d);
- }
-
- return null;
- case COLUMN_MESSAGE:
- if(metadata.isBufferOverflow())
- {
- return "**OVERFLOW**";
- }
- else if(metadata.hasMessageType() || metadata.hasMessage())
- {
- StringBuilder sb = new StringBuilder();
- if(metadata.hasMessageType())
- {
- sb.append(metadata.getMessageType()).append(" ");
- }
-
- if(metadata.hasMessage())
- {
- sb.append(metadata.getMessage());
- }
-
- return sb.toString();
- }
-
- return null;
- case COLUMN_CONFIGURATION_NAME:
- return metadata.getChannelConfigurationName();
- case COLUMN_PRIMARY_TO:
- case COLUMN_PRIMARY_FROM:
- case COLUMN_SECONDARY_TO:
- case COLUMN_SECONDARY_FROM:
- return metadata;
-
- default:
- return String.class;
+ case COLUMN_DECODER_STATE:
+ return channelMetadata.getDecoderStateIdentifier();
+ case COLUMN_DECODER_TYPE:
+ return channelMetadata.getDecoderTypeConfigurationIdentifier();
+ case COLUMN_DECODER_LOGICAL_CHANNEL_NAME:
+ return channelMetadata.getDecoderLogicalChannelNameIdentifier();
+ case COLUMN_CONFIGURATION_FREQUENCY:
+ return channelMetadata.getFrequencyConfigurationIdentifier();
+ case COLUMN_CONFIGURATION_CHANNEL:
+ return channelMetadata.getChannelNameConfigurationIdentifier();
+ case COLUMN_USER_TO:
+ return channelMetadata;
+ case COLUMN_USER_FROM:
+ return channelMetadata;
+ case COLUMN_USER_FROM_ALIAS:
+ return channelMetadata.getFromIdentifierAlias();
+ case COLUMN_USER_TO_ALIAS:
+ return channelMetadata.getToIdentifierAlias();
}
}
@@ -223,59 +196,46 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
}
@Override
- public void receive(MutableMetadataChangeEvent mutableMetadataChangeEvent)
+ public void updated(ChannelMetadata channelMetadata, ChannelMetadataField channelMetadataField)
{
- //Execute on the swing thread to avoid threading issues
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- int rowIndex = mChannelMetadata.indexOf(mutableMetadataChangeEvent.getMetadata());
+ final int rowIndex = mChannelMetadata.indexOf(channelMetadata);
- if(rowIndex >= 0)
+ if(rowIndex >= 0)
+ {
+ //Execute on the swing thread to avoid threading issues
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
{
- switch(mutableMetadataChangeEvent.getAttribute())
+ switch(channelMetadataField)
{
- case CHANNEL_CONFIGURATION_SYSTEM:
+ case CONFIGURATION_CHANNEL:
+ fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_CHANNEL);
break;
- case CHANNEL_CONFIGURATION_SITE:
+ case CONFIGURATION_FREQUENCY:
+ fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_FREQUENCY);
break;
- case CHANNEL_CONFIGURATION_NAME:
- fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_NAME);
+ case DECODER_CHANNEL_NAME:
+ fireTableCellUpdated(rowIndex, COLUMN_DECODER_LOGICAL_CHANNEL_NAME);
break;
- case CHANNEL_FREQUENCY:
- fireTableCellUpdated(rowIndex, COLUMN_FREQUENCY);
+ case DECODER_TYPE:
+ fireTableCellUpdated(rowIndex, COLUMN_DECODER_TYPE);
break;
- case CHANNEL_FREQUENCY_LABEL:
- fireTableCellUpdated(rowIndex, COLUMN_CHANNEL);
+ case DECODER_STATE:
+ fireTableCellUpdated(rowIndex, COLUMN_DECODER_STATE);
break;
- case CHANNEL_STATE:
- fireTableCellUpdated(rowIndex, COLUMN_STATE);
+ case USER_FROM:
+ fireTableCellUpdated(rowIndex, COLUMN_USER_FROM);
+ fireTableCellUpdated(rowIndex, COLUMN_USER_FROM_ALIAS);
break;
- case BUFFER_OVERFLOW:
- case MESSAGE:
- case MESSAGE_TYPE:
- fireTableCellUpdated(rowIndex, COLUMN_MESSAGE);
- break;
- case PRIMARY_ADDRESS_FROM:
- fireTableCellUpdated(rowIndex, COLUMN_PRIMARY_FROM);
- break;
- case PRIMARY_ADDRESS_TO:
- fireTableCellUpdated(rowIndex, COLUMN_PRIMARY_TO);
- break;
- case PRIMARY_DECODER_TYPE:
- fireTableCellUpdated(rowIndex, COLUMN_DECODER);
- break;
- case SECONDARY_ADDRESS_FROM:
- fireTableCellUpdated(rowIndex, COLUMN_SECONDARY_FROM);
- break;
- case SECONDARY_ADDRESS_TO:
- fireTableCellUpdated(rowIndex, COLUMN_SECONDARY_TO);
+ case USER_TO:
+ fireTableCellUpdated(rowIndex, COLUMN_USER_TO);
+ fireTableCellUpdated(rowIndex, COLUMN_USER_TO_ALIAS);
break;
}
}
- }
- });
+ });
+ }
}
}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java
index 1159360e..75f1cc28 100644
--- a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java
+++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java
@@ -1,6 +1,7 @@
-/*******************************************************************************
+/*
+ * ******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,21 +15,26 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
+ * *****************************************************************************
+ */
package io.github.dsheirer.channel.metadata;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.channel.state.State;
import io.github.dsheirer.controller.channel.Channel;
+import io.github.dsheirer.controller.channel.ChannelModel;
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
import io.github.dsheirer.controller.channel.ChannelUtils;
import io.github.dsheirer.icon.IconManager;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.configuration.FrequencyConfigurationIdentifier;
+import io.github.dsheirer.identifier.decoder.DecoderStateIdentifier;
import io.github.dsheirer.module.ProcessingChain;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.preference.identifier.TalkgroupFormatPreference;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
import net.miginfocom.swing.MigLayout;
-import org.apache.commons.lang3.Validate;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
@@ -44,13 +50,16 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
public class ChannelMetadataPanel extends JPanel implements ListSelectionListener
{
+ private ChannelModel mChannelModel;
private ChannelProcessingManager mChannelProcessingManager;
private IconManager mIconManager;
+ private UserPreferences mUserPreferences;
private JTable mTable;
private Broadcaster mSelectedProcessingChainBroadcaster = new Broadcaster<>();
private Map mBackgroundColors = new HashMap<>();
@@ -59,11 +68,13 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
/**
* Table view for currently decoding channel metadata
*/
- public ChannelMetadataPanel(ChannelProcessingManager channelProcessingManager, IconManager iconManager)
+ public ChannelMetadataPanel(ChannelModel channelModel, ChannelProcessingManager channelProcessingManager,
+ IconManager iconManager, UserPreferences userPreferences)
{
- mIconManager = iconManager;
+ mChannelModel = channelModel;
mChannelProcessingManager = channelProcessingManager;
-
+ mIconManager = iconManager;
+ mUserPreferences = userPreferences;
init();
}
@@ -82,16 +93,18 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
mTable.getSelectionModel().addListSelectionListener(this);
mTable.addMouseListener(new MouseSupport());
- mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_STATE)
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_DECODER_STATE)
.setCellRenderer(new ColoredStateCellRenderer());
- mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_TO)
- .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_TO));
- mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_FROM)
- .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_FROM));
- mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_TO)
- .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_TO));
- mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_FROM)
- .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_FROM));
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_USER_FROM)
+ .setCellRenderer(new FromCellRenderer(mUserPreferences.getTalkgroupFormatPreference()));
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_USER_TO)
+ .setCellRenderer(new ToCellRenderer(mUserPreferences.getTalkgroupFormatPreference()));
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_USER_FROM_ALIAS)
+ .setCellRenderer(new AliasCellRenderer());
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_USER_TO_ALIAS)
+ .setCellRenderer(new AliasCellRenderer());
+ mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_CONFIGURATION_FREQUENCY)
+ .setCellRenderer(new FrequencyCellRenderer());
JScrollPane scrollPane = new JScrollPane(mTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
@@ -139,14 +152,16 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
{
int selectedModelRow = mTable.convertRowIndexToModel(selectedViewRow);
- Metadata selectedMetadata = mChannelProcessingManager.getChannelMetadataModel()
- .getMetadata(selectedModelRow);
+ ChannelMetadata selectedMetadata = mChannelProcessingManager.getChannelMetadataModel()
+ .getChannelMetadata(selectedModelRow);
if(selectedMetadata != null)
{
Channel selectedChannel = mChannelProcessingManager.getChannelMetadataModel()
.getChannelFromMetadata(selectedMetadata);
+
+
processingChain = mChannelProcessingManager.getProcessingChain(selectedChannel);
}
}
@@ -164,35 +179,148 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
mSelectedProcessingChainBroadcaster.addListener(listener);
}
- public class AliasedValueCellRenderer extends DefaultTableCellRenderer
+ /**
+ * Cell renderer for frequency values
+ */
+ public class FrequencyCellRenderer extends DefaultTableCellRenderer
{
- private Attribute mAttribute;
+ private final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat( "#.00000" );
- public AliasedValueCellRenderer(Attribute attribute)
+ public FrequencyCellRenderer()
{
- Validate.isTrue(attribute != null);
- mAttribute = attribute;
setHorizontalAlignment(JLabel.CENTER);
}
@Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
- int row, int column)
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- Metadata metadata = (Metadata)value;
- String value1 = metadata.getValue(mAttribute);
- Alias alias = metadata.getAlias(mAttribute);
-
- label.setText(alias != null ? alias.getName() : value1);
- label.setIcon(alias != null ? mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE) : null);
- label.setForeground(alias != null ? alias.getDisplayColor() : table.getForeground());
+ if(value instanceof FrequencyConfigurationIdentifier)
+ {
+ long frequency = ((FrequencyConfigurationIdentifier)value).getValue();
+ label.setText(FREQUENCY_FORMATTER.format(frequency / 1e6d));
+ }
+ else
+ {
+ label.setText(null);
+ }
return label;
}
}
+ /**
+ * Alias cell renderer
+ */
+ public class AliasCellRenderer extends DefaultTableCellRenderer
+ {
+ public AliasCellRenderer()
+ {
+ setHorizontalAlignment(JLabel.LEFT);
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
+ {
+ JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+ if(value instanceof Alias)
+ {
+ Alias alias = (Alias)value;
+
+ label.setText(alias.getName());
+ label.setIcon(mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE));
+ label.setForeground(alias.getDisplayColor());
+
+ }
+ else
+ {
+ label.setText(null);
+ label.setIcon(null);
+ label.setForeground(table.getForeground());
+ }
+
+ return label;
+ }
+ }
+
+ /**
+ * Abstract cell renderer for identifiers
+ */
+ public abstract class IdentifierCellRenderer extends DefaultTableCellRenderer
+ {
+ private final static String EMPTY_VALUE = "-----";
+ private TalkgroupFormatPreference mTalkgroupFormatPreference;
+
+ public IdentifierCellRenderer(TalkgroupFormatPreference talkgroupFormatPreference)
+ {
+ mTalkgroupFormatPreference = talkgroupFormatPreference;
+ setHorizontalAlignment(JLabel.CENTER);
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
+ {
+ JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+ if(value instanceof ChannelMetadata)
+ {
+ ChannelMetadata channelMetadata = (ChannelMetadata)value;
+ Identifier identifier = getIdentifier(channelMetadata);
+ String text = mTalkgroupFormatPreference.format(identifier);
+ if(text == null || text.isEmpty())
+ {
+ text = EMPTY_VALUE;
+ }
+
+ label.setText(text);
+ }
+ else
+ {
+ label.setText(EMPTY_VALUE);
+ }
+
+ return label;
+ }
+
+ public abstract Identifier getIdentifier(ChannelMetadata channelMetadata);
+ }
+
+ /**
+ * Cell renderer for the FROM identifier
+ */
+ public class FromCellRenderer extends IdentifierCellRenderer
+ {
+ public FromCellRenderer(TalkgroupFormatPreference talkgroupFormatPreference)
+ {
+ super(talkgroupFormatPreference);
+ }
+
+ @Override
+ public Identifier getIdentifier(ChannelMetadata channelMetadata)
+ {
+ return channelMetadata.getFromIdentifier();
+ }
+ }
+
+ /**
+ * Cell renderer for the TO identifier
+ */
+ public class ToCellRenderer extends IdentifierCellRenderer
+ {
+ public ToCellRenderer(TalkgroupFormatPreference talkgroupFormatPreference)
+ {
+ super(talkgroupFormatPreference);
+ }
+
+ @Override
+ public Identifier getIdentifier(ChannelMetadata channelMetadata)
+ {
+ return channelMetadata.getToIdentifier();
+ }
+ }
+
public class ColoredStateCellRenderer extends DefaultTableCellRenderer
{
public ColoredStateCellRenderer()
@@ -209,9 +337,9 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
Color background = table.getBackground();
Color foreground = table.getForeground();
- if(value instanceof State)
+ if(value instanceof DecoderStateIdentifier)
{
- State state = (State)value;
+ State state = ((DecoderStateIdentifier)value).getValue();
label.setText(state.getDisplayValue());
if(mBackgroundColors.containsKey(state))
@@ -226,7 +354,7 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
}
else
{
- setText("");
+ setText("----");
}
setBackground(background);
@@ -255,7 +383,7 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
if(modelRowIndex >= 0)
{
- Metadata metadata = mChannelProcessingManager.getChannelMetadataModel().getMetadata(modelRowIndex);
+ ChannelMetadata metadata = mChannelProcessingManager.getChannelMetadataModel().getChannelMetadata(modelRowIndex);
if(metadata != null)
{
@@ -264,9 +392,7 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
if(channel != null)
{
- popupMenu.add(ChannelUtils.getContextMenu(mChannelProcessingManager.getChannelModel(),
- mChannelProcessingManager, channel, mTable));
-
+ popupMenu.add(ChannelUtils.getContextMenu(mChannelModel, mChannelProcessingManager, channel, mTable));
populated = true;
}
}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java
index d0f3fd23..b7b3c65c 100644
--- a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java
+++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java
@@ -20,12 +20,14 @@ package io.github.dsheirer.channel.metadata;
import com.jidesoft.swing.JideSplitPane;
import com.jidesoft.swing.JideTabbedPane;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.channel.details.ChannelDetailPanel;
+import io.github.dsheirer.controller.channel.ChannelModel;
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.module.decode.event.CallEventPanel;
+import io.github.dsheirer.module.decode.event.DecodeEventPanel;
import io.github.dsheirer.module.decode.event.MessageActivityPanel;
-import io.github.dsheirer.settings.SettingsManager;
+import io.github.dsheirer.preference.UserPreferences;
import net.miginfocom.swing.MigLayout;
import javax.swing.JPanel;
@@ -36,20 +38,20 @@ public class ChannelMetadataViewer extends JPanel
private ChannelMetadataPanel mChannelMetadataPanel;
private ChannelDetailPanel mChannelDetailPanel;
- private CallEventPanel mCallEventPanel;
+ private DecodeEventPanel mDecodeEventPanel;
private MessageActivityPanel mMessageActivityPanel;
/**
* GUI panel that combines the currently decoding channels metadata table and viewers for channel details,
* messages, events, and spectral view.
*/
- public ChannelMetadataViewer(ChannelProcessingManager channelProcessingManager, IconManager iconManager,
- SettingsManager settingsManager)
+ public ChannelMetadataViewer(ChannelModel channelModel, ChannelProcessingManager channelProcessingManager,
+ IconManager iconManager, AliasModel aliasModel, UserPreferences userPreferences)
{
mChannelDetailPanel = new ChannelDetailPanel(channelProcessingManager);
- mCallEventPanel = new CallEventPanel(iconManager);
+ mDecodeEventPanel = new DecodeEventPanel(iconManager, userPreferences, aliasModel);
mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager);
- mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager, iconManager);
+ mChannelMetadataPanel = new ChannelMetadataPanel(channelModel, channelProcessingManager, iconManager, userPreferences);
init();
}
@@ -60,7 +62,7 @@ public class ChannelMetadataViewer extends JPanel
JideTabbedPane tabbedPane = new JideTabbedPane();
tabbedPane.addTab("Details", mChannelDetailPanel);
- tabbedPane.addTab("Events", mCallEventPanel);
+ tabbedPane.addTab("Events", mDecodeEventPanel);
tabbedPane.addTab("Messages", mMessageActivityPanel);
// tabbedPane.addTab("Spectrum", mChannelSpectrumPanel);
tabbedPane.setFont(this.getFont());
@@ -73,7 +75,7 @@ public class ChannelMetadataViewer extends JPanel
add(splitPane);
mChannelMetadataPanel.addProcessingChainSelectionListener(mChannelDetailPanel);
- mChannelMetadataPanel.addProcessingChainSelectionListener(mCallEventPanel);
+ mChannelMetadataPanel.addProcessingChainSelectionListener(mDecodeEventPanel);
mChannelMetadataPanel.addProcessingChainSelectionListener(mMessageActivityPanel);
}
}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/IChannelMetadataUpdateListener.java b/src/main/java/io/github/dsheirer/channel/metadata/IChannelMetadataUpdateListener.java
new file mode 100644
index 00000000..1e0f8df1
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/channel/metadata/IChannelMetadataUpdateListener.java
@@ -0,0 +1,29 @@
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
+
+package io.github.dsheirer.channel.metadata;
+
+/**
+ * Interface to receive channel metadata update notifications
+ */
+public interface IChannelMetadataUpdateListener
+{
+ void updated(ChannelMetadata channelMetadata, ChannelMetadataField channelMetadataField);
+}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/Metadata.java b/src/main/java/io/github/dsheirer/channel/metadata/Metadata.java
deleted file mode 100644
index 80bffc1a..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/Metadata.java
+++ /dev/null
@@ -1,664 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.alias.id.priority.Priority;
-import io.github.dsheirer.channel.state.State;
-import io.github.dsheirer.module.decode.DecoderType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-import java.util.TreeSet;
-
-public class Metadata
-{
- private final static Logger mLog = LoggerFactory.getLogger(Metadata.class);
-
- // Static unique metadata identifier tracking
- private static int UNIQUE_METADATA_ID_GENERATOR = 0;
-
- private int mMetadataID;
-
- protected boolean mUpdated;
- protected DecoderType mPrimaryDecoderType;
- protected boolean mSelected;
- protected boolean mBufferOverflow;
- protected State mState = State.IDLE;
- protected String mChannelConfigurationSystem;
- protected String mChannelConfigurationSite;
- protected String mChannelConfigurationName;
- protected String mChannelFrequencyLabel;
- protected long mChannelFrequency;
- protected AliasedIdentifier mNetworkID1 = new AliasedIdentifier();
- protected AliasedIdentifier mNetworkID2 = new AliasedIdentifier();
-
- protected String mMessage;
- protected String mMessageType;
- protected AliasedIdentifier mPrimaryAddressFrom = new AliasedIdentifier();
- protected AliasedIdentifier mPrimaryAddressTo = new AliasedIdentifier();
- protected AliasedIdentifier mSecondaryAddressFrom = new AliasedIdentifier();
- protected AliasedIdentifier mSecondaryAddressTo = new AliasedIdentifier();
-
- //Lazily constructed member variables.
- private Integer mAudioPriority;
- protected Boolean mRecordable = false;
- protected Boolean mDoNotRecord;
- private Set mBroadcastChannels;
-
- private long mTimestamp = System.currentTimeMillis();
-
-
- /**
- * Channel metadata. Contains all attributes that reflect the state and current attribute values for a channel
- * that is currently decoding. This metadata is intended to support any decoding channel gui components to
- * graphically convey the current state of a decoding channel and to provide audio metadata
- */
- public Metadata()
- {
- mMetadataID = UNIQUE_METADATA_ID_GENERATOR++;
- }
-
- /**
- * Protected constructor. Primarily used by the copyOf() method to create a metadata copy with the same ID
- */
- protected Metadata(int metadataID)
- {
- mMetadataID = metadataID;
- }
-
- /**
- * Timestamp when this metadata was created
- * @return milliseconds since epoch
- */
- public long getTimestamp()
- {
- return mTimestamp;
- }
- /**
- * Unique string identifier for this metadata that is comprised of the channel ID and the primary TO address.
- *
- * This identifier can be used to uniquely identify a channel audio stream and the primary communicant.
- */
- public String getUniqueIdentifier()
- {
- return "SRC:" + mMetadataID +
- " ID:" + (mPrimaryAddressTo.hasIdentifier() ? mPrimaryAddressTo.getIdentifier() : "UNKNOWN");
- }
-
- /**
- * Indicates if any of the fields of this metadata have been updated since the last time a copy was made from this
- * metadata. This method is primarily used by downstream audio playback and audio recording to signal when changes
- * are made to the metadata that requires the downstream component to reinspect the metadata.
- *
- * This flag is reset to false immediately after a copy is made of this metadata via the copyOf() method.
- */
- public boolean isUpdated()
- {
- return mUpdated;
- }
-
- /**
- * Audio Priority as the highest audio priority value from across the primary and secondary identifier aliases.
- *
- * A default priority will be used if there are no aliased values. If there is a conflict between audio priority
- * and 'Do Not Monitor' among the aliases, the highest audio priority will be used (prefer to monitor).
- *
- * -1 Do Not Monitor
- * 0 Channel Selected for immediate monitor
- * 1 Highest Priority
- * 100 Lowest Priority (default)
- *
- * @return audio priority
- */
- public int getAudioPriority()
- {
- if(isSelected())
- {
- return Priority.SELECTED_PRIORITY;
- }
-
- if(mAudioPriority == null)
- {
- determineAudioPriority();
- }
-
- return mAudioPriority;
- }
-
- /**
- * Indicates if the audio priority is set to 'Do Not Monitor'
- */
- public boolean isDoNotMonitor()
- {
- return getAudioPriority() == Priority.DO_NOT_MONITOR;
- }
-
- /**
- * Indicates if any of the primary or secondary TO/FROM aliases are identified as recordable
- */
- public boolean isRecordable()
- {
- if(mDoNotRecord == null)
- {
- determineRecordable();
- }
-
- return mRecordable && !mDoNotRecord;
- }
-
- /**
- * Indicates that this metadata has been selected by the user and any audio produced by this channel will be set
- * to the highest playback priority (immediate monitor).
- */
- public boolean isSelected()
- {
- return mSelected;
- }
-
- /**
- * Indicates if the channel for this metadata is in a buffer overflow state.
- */
- public boolean isBufferOverflow()
- {
- return mBufferOverflow;
- }
-
- /**
- * List of de-duplicated broadcast channels aggregated from the primary and secondary TO/FROM aliases.
- */
- public Set getBroadcastChannels()
- {
- if(mBroadcastChannels == null)
- {
- determineBroadcastChannels();
- }
-
- return mBroadcastChannels;
- }
-
- /**
- * Indicates if this metadata is streamable, meaning that it contains one ore more broadcast channels
- */
- public boolean isStreamable()
- {
- return !getBroadcastChannels().isEmpty();
- }
-
- /**
- * Unique identifier for the source channel that produces this metadata
- */
- public int getMetadataID()
- {
- return mMetadataID;
- }
-
- /**
- * Decoder type (ie protocol) for the primary decoder
- */
- public DecoderType getPrimaryDecoderType()
- {
- return mPrimaryDecoderType;
- }
-
- /**
- * Indicates if this metadata has a primary decoder type defined
- */
- public boolean hasPrimaryDecoderType()
- {
- return mPrimaryDecoderType != null;
- }
-
- /**
- * Returns the alias associated with the attribute or null
- */
- public Alias getAlias(Attribute attribute)
- {
- switch(attribute)
- {
- case NETWORK_ID_1:
- return getNetworkID1().getAlias();
- case NETWORK_ID_2:
- return getNetworkID2().getAlias();
- case PRIMARY_ADDRESS_FROM:
- return getPrimaryAddressFrom().getAlias();
- case PRIMARY_ADDRESS_TO:
- return getPrimaryAddressTo().getAlias();
- case SECONDARY_ADDRESS_FROM:
- return getSecondaryAddressFrom().getAlias();
- case SECONDARY_ADDRESS_TO:
- return getSecondaryAddressTo().getAlias();
- }
-
- return null;
- }
-
- /**
- * Returns the string value for the specified attribute or null
- */
- public String getValue(Attribute attribute)
- {
- switch(attribute)
- {
- case CHANNEL_CONFIGURATION_SYSTEM:
- return mChannelConfigurationSystem;
- case CHANNEL_CONFIGURATION_SITE:
- return mChannelConfigurationSite;
- case CHANNEL_FREQUENCY_LABEL:
- return mChannelFrequencyLabel;
- case CHANNEL_STATE:
- return mState.getDisplayValue();
- case MESSAGE:
- return mMessage;
- case MESSAGE_TYPE:
- return mMessageType;
- case NETWORK_ID_1:
- return mNetworkID1.getIdentifier();
- case NETWORK_ID_2:
- return mNetworkID2.getIdentifier();
- case PRIMARY_ADDRESS_FROM:
- return mPrimaryAddressFrom.getIdentifier();
- case PRIMARY_ADDRESS_TO:
- return mPrimaryAddressTo.getIdentifier();
- case SECONDARY_ADDRESS_FROM:
- return mSecondaryAddressFrom.getIdentifier();
- case SECONDARY_ADDRESS_TO:
- return mSecondaryAddressTo.getIdentifier();
- }
-
- return null;
- }
-
- /**
- * Current channel state
- */
- public State getState()
- {
- return mState;
- }
-
- /**
- * System name from the channel configuration
- */
- public String getChannelConfigurationSystem()
- {
- return mChannelConfigurationSystem;
- }
-
- /**
- * Indicates if there is a non-null, non-empty channel configuration system value
- */
- public boolean hasChannelConfigurationSystem()
- {
- return mChannelConfigurationSystem != null && !mChannelConfigurationSystem.isEmpty();
- }
-
- /**
- * Site name from the channel configuration
- */
- public String getChannelConfigurationSite()
- {
- return mChannelConfigurationSite;
- }
-
- /**
- * Indicates if there is a non-null, non-empty channel configuration site value
- */
- public boolean hasChannelConfigurationSite()
- {
- return mChannelConfigurationSite != null && !mChannelConfigurationSite.isEmpty();
- }
-
- /**
- * Site name from the channel configuration
- */
- public String getChannelConfigurationName()
- {
- return mChannelConfigurationName;
- }
-
- /**
- * Indicates if there is a non-null, non-empty channel configuration name value
- */
- public boolean hasChannelConfigurationName()
- {
- return mChannelConfigurationSite != null && !mChannelConfigurationSite.isEmpty();
- }
-
- /**
- * Channel ID or Channel Number
- */
- public String getChannelFrequencyLabel()
- {
- return mChannelFrequencyLabel;
- }
-
- /**
- * Indicates if there is a non-null, non-empty channel identifier value
- */
- public boolean hasChannelFrequencyLabel()
- {
- return mChannelFrequencyLabel != null && !mChannelFrequencyLabel.isEmpty();
- }
-
- /**
- * Channel frequency
- */
- public long getChannelFrequency()
- {
- return mChannelFrequency;
- }
-
- /**
- * Indicates if there is a non-zero channel frequency value
- */
- public boolean hasChannelFrequency()
- {
- return mChannelFrequency > 0;
- }
-
- /**
- * Network Identifier 1
- */
- public AliasedIdentifier getNetworkID1()
- {
- return mNetworkID1;
- }
-
- /**
- * Network Identifier 2
- */
- public AliasedIdentifier getNetworkID2()
- {
- return mNetworkID2;
- }
-
- /**
- * Message
- */
- public String getMessage()
- {
- return mMessage;
- }
-
- /**
- * Indicates if there is a non-null, non-empty message value
- */
- public boolean hasMessage()
- {
- return mMessage != null && !mMessage.isEmpty();
- }
-
- /**
- * Message and Decoder type
- */
- public String getMessageType()
- {
- return mMessageType;
- }
-
- /**
- * Indicates if there is a non-null, non-empty message and decoder type value
- */
- public boolean hasMessageType()
- {
- return mMessageType != null && !mMessageType.isEmpty();
- }
-
- /**
- * Primary FROM Address
- */
- public AliasedIdentifier getPrimaryAddressFrom()
- {
- return mPrimaryAddressFrom;
- }
-
- /**
- * Primary TO Address
- */
- public AliasedIdentifier getPrimaryAddressTo()
- {
- return mPrimaryAddressTo;
- }
-
- /**
- * Secondary FROM Address
- */
- public AliasedIdentifier getSecondaryAddressFrom()
- {
- return mSecondaryAddressFrom;
- }
-
- /**
- * Secondary TO Address
- */
- public AliasedIdentifier getSecondaryAddressTo()
- {
- return mSecondaryAddressTo;
- }
-
- /**
- * Determines the audio priority from across the primary and secondary TO/FROM aliases when they exist
- */
- private void determineAudioPriority()
- {
- int priority = Priority.DEFAULT_PRIORITY;
-
- boolean doNotMonitorFound = false;
- boolean audioPriorityFound = false;
-
- if(getPrimaryAddressTo().hasAlias())
- {
- Alias primaryTo = getPrimaryAddressTo().getAlias();
-
- if(primaryTo.hasCallPriority())
- {
- if(primaryTo.getCallPriority() == Priority.DO_NOT_MONITOR)
- {
- doNotMonitorFound = true;
- }
- else
- {
- audioPriorityFound = true;
-
- if(primaryTo.getCallPriority() < priority)
- {
- priority = primaryTo.getCallPriority();
- }
- }
- }
- }
-
- if(getPrimaryAddressFrom().hasAlias())
- {
- Alias primaryFrom = getPrimaryAddressFrom().getAlias();
-
- if(primaryFrom.hasCallPriority())
- {
- if(primaryFrom.getCallPriority() == Priority.DO_NOT_MONITOR)
- {
- doNotMonitorFound = true;
- }
- else
- {
- audioPriorityFound = true;
-
- if(primaryFrom.getCallPriority() < priority)
- {
- priority = primaryFrom.getCallPriority();
- }
- }
- }
- }
-
- if(getSecondaryAddressTo().hasAlias())
- {
- Alias secondaryTo = getSecondaryAddressTo().getAlias();
-
- if(secondaryTo.hasCallPriority())
- {
- if(secondaryTo.getCallPriority() == Priority.DO_NOT_MONITOR)
- {
- doNotMonitorFound = true;
- }
- else
- {
- audioPriorityFound = true;
-
- if(secondaryTo.getCallPriority() < priority)
- {
- priority = secondaryTo.getCallPriority();
- }
- }
- }
- }
-
- if(getSecondaryAddressFrom().hasAlias())
- {
- Alias secondaryFrom = getSecondaryAddressFrom().getAlias();
-
- if(secondaryFrom.hasCallPriority())
- {
- if(secondaryFrom.getCallPriority() == Priority.DO_NOT_MONITOR)
- {
- doNotMonitorFound = true;
- }
- else
- {
- audioPriorityFound = true;
-
- if(secondaryFrom.getCallPriority() < priority)
- {
- priority = secondaryFrom.getCallPriority();
- }
- }
- }
- }
-
- //If we found a 'Do Not Monitor' and no other audio priority, then set to do not monitor
- if(doNotMonitorFound && !audioPriorityFound)
- {
- mAudioPriority = Priority.DO_NOT_MONITOR;
- }
- else
- {
- mAudioPriority = priority;
- }
- }
-
- /**
- * Determines if any of the primary or secondary to/from aliases are recordable.
- */
- private void determineRecordable()
- {
- mDoNotRecord = false;
-
- if(mPrimaryAddressTo.hasAlias() && !mPrimaryAddressTo.getAlias().isRecordable())
- {
- mDoNotRecord = true;
- return;
- }
-
- if(mPrimaryAddressFrom.hasAlias() && !mPrimaryAddressFrom.getAlias().isRecordable())
- {
- mDoNotRecord = true;
- return;
- }
-
- if(mSecondaryAddressTo.hasAlias() && !mSecondaryAddressTo.getAlias().isRecordable())
- {
- mDoNotRecord = true;
- return;
- }
-
- if(mSecondaryAddressFrom.hasAlias() && !mSecondaryAddressFrom.getAlias().isRecordable())
- {
- mDoNotRecord = true;
- return;
- }
- }
-
- /**
- * Aggregates a de-duplicated list of broadcast channels from among the primary/secondary to/from aliases
- */
- private void determineBroadcastChannels()
- {
- mBroadcastChannels = new TreeSet<>();
-
- if(mPrimaryAddressTo.hasAlias() && mPrimaryAddressTo.getAlias().isStreamable())
- {
- mBroadcastChannels.addAll(mPrimaryAddressTo.getAlias().getBroadcastChannels());
- }
-
- if(mPrimaryAddressFrom.hasAlias() && mPrimaryAddressFrom.getAlias().isStreamable())
- {
- mBroadcastChannels.addAll(mPrimaryAddressFrom.getAlias().getBroadcastChannels());
- }
-
- if(mSecondaryAddressTo.hasAlias() && mSecondaryAddressTo.getAlias().isStreamable())
- {
- mBroadcastChannels.addAll(mSecondaryAddressTo.getAlias().getBroadcastChannels());
- }
-
- if(mSecondaryAddressFrom.hasAlias() && mSecondaryAddressFrom.getAlias().isStreamable())
- {
- mBroadcastChannels.addAll(mSecondaryAddressFrom.getAlias().getBroadcastChannels());
- }
- }
-
- /**
- * Creates a deep/full snapshot copy of this metadata set.
- *
- * The streamable, recordable, audio priority and broadcast channels are not copied. These are lazily determined
- * when initially requested.
- */
- public Metadata copyOf()
- {
- Metadata copy = new Metadata(mMetadataID);
-
- copy.mDoNotRecord = mDoNotRecord;
- copy.mRecordable = mRecordable;
- copy.mState = mState;
- copy.mPrimaryDecoderType = mPrimaryDecoderType;
- copy.mChannelFrequency = mChannelFrequency;
-
- copy.mChannelConfigurationSystem = hasChannelConfigurationSystem() ? new String(mChannelConfigurationSystem) : null;
- copy.mChannelConfigurationSite = hasChannelConfigurationSite() ? new String(mChannelConfigurationSite) : null;
- copy.mChannelConfigurationName = hasChannelConfigurationName() ? new String(mChannelConfigurationName) : null;
- copy.mChannelFrequencyLabel = hasChannelFrequencyLabel() ? new String(mChannelFrequencyLabel) : null;
- copy.mMessage = hasMessage() ? new String(mMessage) : null;
- copy.mMessageType = hasMessageType() ? new String(mMessageType) : null;
-
- copy.mNetworkID1 = mNetworkID1.copyOf();
- copy.mNetworkID2 = mNetworkID2.copyOf();
- copy.mPrimaryAddressFrom = mPrimaryAddressFrom.copyOf();
- copy.mPrimaryAddressTo = mPrimaryAddressTo.copyOf();
- copy.mSecondaryAddressFrom = mSecondaryAddressFrom.copyOf();
- copy.mSecondaryAddressTo = mSecondaryAddressTo.copyOf();
-
- copy.mUpdated = mUpdated;
-
- //Reset the updated flag
- mUpdated = false;
-
- return copy;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadata.java b/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadata.java
deleted file mode 100644
index df4e297d..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadata.java
+++ /dev/null
@@ -1,294 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-import io.github.dsheirer.channel.state.State;
-import io.github.dsheirer.module.decode.DecoderType;
-import io.github.dsheirer.sample.Broadcaster;
-import io.github.dsheirer.sample.Listener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MutableMetadata extends Metadata implements Listener
-{
- private final static Logger mLog = LoggerFactory.getLogger(MutableMetadata.class);
-
- private Broadcaster mMetadataChangeEventBroadcaster = new Broadcaster<>();
-
- /**
- * Mutable channel metadata. Contains all attributes that reflect the state and current attribute values for a
- * channel that is currently decoding. This metadata is intended to support any decoding channel gui components to
- * graphically convey the current state of a decoding channel and to provide audio metadata
- */
- public MutableMetadata()
- {
- super();
- }
-
- /**
- * Sets the selected state for this metadata. Selected indicates that the user has selected this metadata for
- * immediate monitor in the audio panel. When true, this overrides the audio priority for any audio produced
- * by the channel and sets that audio to the highest priority.
- *
- * Any component that toggles the selected state for this metadata is also responsible for clearing the flag.
- */
- 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;
- }
-
- /**
- * Sets the primary decoder type
- */
- public void setPrimaryDecoderType(DecoderType decoderType)
- {
- mPrimaryDecoderType = decoderType;
- mUpdated = true;
- }
-
- /**
- * Request to change an attribute value for this metadata. This is the primary method for updating all attributes
- * in this metadata set.
- */
- @Override
- public void receive(AttributeChangeRequest request)
- {
- switch(request.getAttribute())
- {
- case BUFFER_OVERFLOW:
- mBufferOverflow = request.getBooleanValue();
- broadcast(Attribute.BUFFER_OVERFLOW);
- break;
- case CHANNEL_CONFIGURATION_SYSTEM:
- mChannelConfigurationSystem = request.getStringValue();
- broadcast(Attribute.CHANNEL_CONFIGURATION_SYSTEM);
- break;
- case CHANNEL_CONFIGURATION_SITE:
- mChannelConfigurationSite = request.getStringValue();
- broadcast(Attribute.CHANNEL_CONFIGURATION_SITE);
- break;
- case CHANNEL_CONFIGURATION_NAME:
- mChannelConfigurationName = request.getStringValue();
- broadcast(Attribute.CHANNEL_CONFIGURATION_NAME);
- break;
- case CHANNEL_FREQUENCY:
- if(request.hasValue())
- {
- mChannelFrequency = request.getLongValue();
- }
- broadcast(Attribute.CHANNEL_FREQUENCY);
- break;
- case CHANNEL_FREQUENCY_LABEL:
- mChannelFrequencyLabel = request.getStringValue();
- broadcast(Attribute.CHANNEL_FREQUENCY_LABEL);
- break;
- case MESSAGE:
- mMessage = request.getStringValue();
- broadcast(Attribute.MESSAGE);
- break;
- case MESSAGE_TYPE:
- mMessageType = request.getStringValue();
- broadcast(Attribute.MESSAGE_TYPE);
- break;
- case NETWORK_ID_1:
- mNetworkID1.setIdentifier(request.getStringValue());
- mNetworkID1.setAlias(request.getAlias());
- broadcast(Attribute.NETWORK_ID_1);
- break;
- case NETWORK_ID_2:
- mNetworkID2.setIdentifier(request.getStringValue());
- mNetworkID2.setAlias(request.getAlias());
- broadcast(Attribute.NETWORK_ID_2);
- break;
- case PRIMARY_ADDRESS_FROM:
- mPrimaryAddressFrom.setIdentifier(request.getStringValue());
- mPrimaryAddressFrom.setAlias(request.getAlias());
- broadcast(Attribute.PRIMARY_ADDRESS_FROM);
- break;
- case PRIMARY_ADDRESS_TO:
- mPrimaryAddressTo.setIdentifier(request.getStringValue());
- 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());
- broadcast(Attribute.SECONDARY_ADDRESS_FROM);
- break;
- case SECONDARY_ADDRESS_TO:
- mSecondaryAddressTo.setIdentifier(request.getStringValue());
- mSecondaryAddressTo.setAlias(request.getAlias());
- broadcast(Attribute.SECONDARY_ADDRESS_TO);
- break;
- case CHANNEL_STATE:
- mState = (State) request.getValue();
- broadcast(Attribute.CHANNEL_STATE);
- break;
- default:
- throw new IllegalArgumentException("Unrecognized Metadata Attribute: " +
- request.getAttribute().name());
- }
-
- mUpdated = true;
- }
-
- /**
- * Resets temporal attributes to null value. This only resets attributes that have a non-ull value in order to
- * limit the number of change events that are produced.
- */
- public void resetTemporalAttributes()
- {
- mDoNotRecord = null;
- mBufferOverflow = false;
-
- if(hasMessage())
- {
- mMessage = null;
- broadcast(Attribute.MESSAGE);
- }
-
- if(hasMessageType())
- {
- mMessageType = null;
- broadcast(Attribute.MESSAGE_TYPE);
- }
-
- if(mPrimaryAddressFrom.hasIdentifier())
- {
- mPrimaryAddressFrom.reset();
- broadcast(Attribute.PRIMARY_ADDRESS_FROM);
- }
-
- if(mPrimaryAddressTo.hasIdentifier())
- {
- mPrimaryAddressTo.reset();
- broadcast(Attribute.PRIMARY_ADDRESS_TO);
- }
-
- if(mSecondaryAddressFrom.hasIdentifier())
- {
- mSecondaryAddressFrom.reset();
- broadcast(Attribute.SECONDARY_ADDRESS_FROM);
- }
-
- if(mSecondaryAddressTo.hasIdentifier())
- {
- mSecondaryAddressTo.reset();
- broadcast(Attribute.SECONDARY_ADDRESS_TO);
- }
-
- mUpdated = true;
- }
-
- /**
- * Resets all attributes to empty values
- */
- public void resetAllAttributes()
- {
- resetTemporalAttributes();
-
- if(hasChannelConfigurationSystem())
- {
- mChannelConfigurationSystem = null;
- broadcast(Attribute.CHANNEL_CONFIGURATION_SYSTEM);
- }
-
- if(hasChannelConfigurationSite())
- {
- mChannelConfigurationSite = null;
- broadcast(Attribute.CHANNEL_CONFIGURATION_SITE);
- }
-
- if(hasChannelConfigurationName())
- {
- mChannelConfigurationSite = null;
- broadcast(Attribute.CHANNEL_CONFIGURATION_NAME);
- }
-
- if(hasChannelFrequencyLabel())
- {
- mChannelFrequencyLabel = null;
- broadcast(Attribute.CHANNEL_FREQUENCY_LABEL);
- }
-
- if(hasChannelFrequency())
- {
- mChannelFrequency = 0;
- broadcast(Attribute.CHANNEL_FREQUENCY);
- }
-
- if(hasPrimaryDecoderType())
- {
- mPrimaryDecoderType = null;
- broadcast(Attribute.PRIMARY_DECODER_TYPE);
- }
-
- if(mNetworkID1.hasIdentifier())
- {
- mNetworkID1.reset();
- broadcast(Attribute.NETWORK_ID_1);
- }
-
- if(mNetworkID2.hasIdentifier())
- {
- mNetworkID2.reset();
- broadcast(Attribute.NETWORK_ID_2);
- }
-
- mUpdated = true;
- }
-
-
- /**
- * Broadcasts to registered listeners that an attribute has changed for this metadata
- */
- private void broadcast(Attribute attribute)
- {
- mMetadataChangeEventBroadcaster.broadcast(new MutableMetadataChangeEvent(this, attribute));
- }
-
- /**
- * Adds the listener to receive metadata change events for this channel metadata
- */
- public void addListener(Listener listener)
- {
- mMetadataChangeEventBroadcaster.addListener(listener);
- }
-
- /**
- * Removes the listener from receiving metadata change events for this channel metadata
- */
- public void removeListener(Listener listener)
- {
- mMetadataChangeEventBroadcaster.removeListener(listener);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadataChangeEvent.java b/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadataChangeEvent.java
deleted file mode 100644
index c083140d..00000000
--- a/src/main/java/io/github/dsheirer/channel/metadata/MutableMetadataChangeEvent.java
+++ /dev/null
@@ -1,53 +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
- *
- ******************************************************************************/
-package io.github.dsheirer.channel.metadata;
-
-public class MutableMetadataChangeEvent
-{
- private MutableMetadata mMetadata;
- private Attribute mAttribute;
-
- /**
- * Channel metadata changed attribute event
- *
- * @param metadata where the change occurred
- * @param attribute that changed
- */
- public MutableMetadataChangeEvent(MutableMetadata metadata, Attribute attribute)
- {
- mMetadata = metadata;
- mAttribute = attribute;
- }
-
- /**
- * Channel metadata where the change occurred
- */
- public MutableMetadata getMetadata()
- {
- return mMetadata;
- }
-
- /**
- * Channel metadata attribute that has changed
- */
- public Attribute getAttribute()
- {
- return mAttribute;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/channel/state/AlwaysUnsquelchedDecoderState.java b/src/main/java/io/github/dsheirer/channel/state/AlwaysUnsquelchedDecoderState.java
index 1d3795e8..4d145b90 100644
--- a/src/main/java/io/github/dsheirer/channel/state/AlwaysUnsquelchedDecoderState.java
+++ b/src/main/java/io/github/dsheirer/channel/state/AlwaysUnsquelchedDecoderState.java
@@ -1,26 +1,26 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014,2015 Dennis Sheirer
+/*
+ * ******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2018 Dennis Sheirer
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * *****************************************************************************
+ */
package io.github.dsheirer.channel.state;
-import io.github.dsheirer.channel.metadata.Attribute;
-import io.github.dsheirer.channel.metadata.AttributeChangeRequest;
import io.github.dsheirer.channel.state.DecoderStateEvent.Event;
-import io.github.dsheirer.message.Message;
+import io.github.dsheirer.message.IMessage;
import io.github.dsheirer.module.decode.DecoderType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,8 +39,6 @@ public class AlwaysUnsquelchedDecoderState extends DecoderState
public AlwaysUnsquelchedDecoderState(DecoderType decoderType, String channelName)
{
- super(null);
-
mDecoderType = decoderType;
mChannelName = channelName;
}
@@ -69,9 +67,9 @@ public class AlwaysUnsquelchedDecoderState extends DecoderState
}
@Override
- public void receive(Message t)
+ public void receive(IMessage t)
{
- /* Not implemented */
+ /* Not implemented */
}
@Override
@@ -81,7 +79,7 @@ public class AlwaysUnsquelchedDecoderState extends DecoderState
{
//Each time we're reset, set the PRIMARY TO attribute back to the channel name, otherwise we won't have
//a primary ID for any audio produced by this state.
- broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, NO_SQUELCH));
+// broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, NO_SQUELCH));
}
}
@@ -94,7 +92,7 @@ public class AlwaysUnsquelchedDecoderState extends DecoderState
@Override
public void start()
{
- broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, NO_SQUELCH));
+// broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, NO_SQUELCH));
broadcast(new DecoderStateEvent(this, Event.ALWAYS_UNSQUELCH, State.IDLE));
}
diff --git a/src/main/java/io/github/dsheirer/channel/state/ChannelState.java b/src/main/java/io/github/dsheirer/channel/state/ChannelState.java
index c688035b..ee0c3fda 100644
--- a/src/main/java/io/github/dsheirer/channel/state/ChannelState.java
+++ b/src/main/java/io/github/dsheirer/channel/state/ChannelState.java
@@ -18,51 +18,64 @@
******************************************************************************/
package io.github.dsheirer.channel.state;
+import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.squelch.ISquelchStateProvider;
import io.github.dsheirer.audio.squelch.SquelchState;
-import io.github.dsheirer.channel.metadata.Attribute;
-import io.github.dsheirer.channel.metadata.AttributeChangeRequest;
-import io.github.dsheirer.channel.metadata.IAttributeChangeRequestListener;
-import io.github.dsheirer.channel.metadata.MutableMetadata;
+import io.github.dsheirer.channel.metadata.ChannelMetadata;
import io.github.dsheirer.channel.state.DecoderStateEvent.Event;
-import io.github.dsheirer.channel.traffic.TrafficChannelManager;
+import io.github.dsheirer.controller.channel.Channel;
import io.github.dsheirer.controller.channel.Channel.ChannelType;
+import io.github.dsheirer.controller.channel.ChannelEvent;
+import io.github.dsheirer.controller.channel.IChannelEventProvider;
+import io.github.dsheirer.identifier.IdentifierUpdateListener;
+import io.github.dsheirer.identifier.IdentifierUpdateNotification;
+import io.github.dsheirer.identifier.IdentifierUpdateProvider;
+import io.github.dsheirer.identifier.MutableIdentifierCollection;
+import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.ChannelNameConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.DecoderTypeConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.FrequencyConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.SiteConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.SystemConfigurationIdentifier;
+import io.github.dsheirer.identifier.decoder.DecoderStateIdentifier;
import io.github.dsheirer.module.Module;
-import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
-import io.github.dsheirer.module.decode.event.CallEvent;
-import io.github.dsheirer.module.decode.event.ICallEventProvider;
+import io.github.dsheirer.module.decode.event.IDecodeEvent;
+import io.github.dsheirer.module.decode.event.IDecodeEventProvider;
import io.github.dsheirer.sample.IOverflowListener;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.ISourceEventListener;
import io.github.dsheirer.source.ISourceEventProvider;
import io.github.dsheirer.source.SourceEvent;
+import io.github.dsheirer.source.SourceType;
+import io.github.dsheirer.source.config.SourceConfigTuner;
import io.github.dsheirer.source.heartbeat.Heartbeat;
import io.github.dsheirer.source.heartbeat.IHeartbeatListener;
+import io.github.dsheirer.source.tuner.channel.TunerChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ChannelState extends Module implements ICallEventProvider, IDecoderStateEventListener,
- IDecoderStateEventProvider, ISourceEventListener, ISourceEventProvider, IHeartbeatListener,
- ISquelchStateProvider, IAttributeChangeRequestListener, IOverflowListener
+public class ChannelState extends Module implements IChannelEventProvider, IDecodeEventProvider,
+ IDecoderStateEventListener, IDecoderStateEventProvider, ISourceEventListener, ISourceEventProvider,
+ IHeartbeatListener, ISquelchStateProvider, IOverflowListener, IdentifierUpdateListener, IdentifierUpdateProvider
{
private final static Logger mLog = LoggerFactory.getLogger(ChannelState.class);
public static final long FADE_TIMEOUT_DELAY = 1200;
public static final long RESET_TIMEOUT_DELAY = 2000;
- private MutableMetadata mMutableMetadata = new MutableMetadata();
private State mState = State.IDLE;
- private Listener mCallEventListener;
+ private MutableIdentifierCollection mIdentifierCollection = new MutableIdentifierCollection();
+ private Listener mChannelEventListener;
+ private Listener mDecodeEventListener;
private Listener mDecoderStateListener;
private Listener mSquelchStateListener;
private Listener mExternalSourceEventListener;
private DecoderStateEventReceiver mDecoderStateEventReceiver = new DecoderStateEventReceiver();
private HeartbeatReceiver mHeartbeatReceiver = new HeartbeatReceiver();
- private ChannelType mChannelType;
- private TrafficChannelManager mTrafficChannelEndListener;
- private CallEvent mTrafficChannelCallEvent;
+ private Channel mChannel;
private SourceEventListener mInternalSourceEventListener;
+ private ChannelMetadata mChannelMetadata;
private boolean mSquelchLocked = false;
private boolean mSelected = false;
@@ -87,25 +100,85 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
* IDLE: Normal state. No voice or data call activity
* CALL/DATA/ENCRYPTED/CONTROL: Decoding states.
* FADE: The phase after a voice or data call when either an explicit call end has been received, or when no new
- * signalling updates have been received, and the fade timer has expired. This phase allows for gui updates to
- * signal to the user that the call is ended, while continuing to display the call details for the user
+ * signalling updates have been received, and the fade timer has expired. This phase allows for gui updates to
+ * signal to the user that the call is ended, while continuing to display the call details for the user
* TEARDOWN: Indicates a traffic channel that will be torn down for reuse.
*/
- public ChannelState(ChannelType channelType)
+ public ChannelState(Channel channel, AliasModel aliasModel)
{
- mChannelType = channelType;
+ mChannel = channel;
+ mChannelMetadata = new ChannelMetadata(aliasModel);
+ createConfigurationIdentifiers(channel);
}
+ /**
+ * Creates configuration identifiers for the channel name, system, site and alias list name.
+ */
+ private void createConfigurationIdentifiers(Channel channel)
+ {
+ mIdentifierCollection.update(DecoderTypeConfigurationIdentifier.create(channel.getDecodeConfiguration().getDecoderType()));
+
+ if(channel.hasSystem())
+ {
+ mIdentifierCollection.update(SystemConfigurationIdentifier.create(channel.getSystem()));
+ }
+ if(channel.hasSite())
+ {
+ mIdentifierCollection.update(SiteConfigurationIdentifier.create(channel.getSite()));
+ }
+ if(channel.getName() != null && !channel.getName().isEmpty())
+ {
+ mIdentifierCollection.update(ChannelNameConfigurationIdentifier.create(channel.getName()));
+ }
+ if(channel.getAliasListName() != null && !channel.getAliasListName().isEmpty())
+ {
+ mIdentifierCollection.update(AliasListConfigurationIdentifier.create(channel.getAliasListName()));
+ }
+ if(channel.getSourceConfiguration().getSourceType() == SourceType.TUNER)
+ {
+ TunerChannel tunerChannel = ((SourceConfigTuner)channel.getSourceConfiguration()).getTunerChannel();
+ mIdentifierCollection.update(FrequencyConfigurationIdentifier.create(tunerChannel.getFrequency()));
+ }
+ }
/**
- * Metadata for this channel containing channel details, primary and secondary entities for call events and any
- * decoded messages. This metadata is primarily intended to be used by graphical components to convey the
- * details of the current channel state and to provide metadata backing any decoded audio packets produced by
- * any audio streams for this channel.
+ * Interface to receive channel identifier updates from this channel state and from any
+ * decoder states.
*/
- public MutableMetadata getMutableMetadata()
+ @Override
+ public Listener getIdentifierUpdateListener()
{
- return mMutableMetadata;
+ return mChannelMetadata;
+ }
+
+ /**
+ * Updates the channel state identifier collection using the update notification. This update will be reflected
+ * in the internal channel state and will also be broadcast to any listeners, including the channel metadata for
+ * this channel state.
+ */
+ public void updateChannelStateIdentifiers(IdentifierUpdateNotification notification)
+ {
+ mIdentifierCollection.receive(notification);
+ }
+
+ @Override
+ public void setIdentifierUpdateListener(Listener listener)
+ {
+ mIdentifierCollection.setIdentifierUpdateListener(listener);
+ }
+
+ @Override
+ public void removeIdentifierUpdateListener()
+ {
+ mIdentifierCollection.removeIdentifierUpdateListener();
+ }
+
+ /**
+ * Channel metadata for this channel.
+ */
+ public ChannelMetadata getChannelMetadata()
+ {
+ return mChannelMetadata;
}
/**
@@ -114,21 +187,18 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
@Override
public void reset()
{
- getMutableMetadata().resetTemporalAttributes();
-
- broadcast(new DecoderStateEvent(this, Event.RESET, State.IDLE));
-
mState = State.IDLE;
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
+ broadcast(new DecoderStateEvent(this, Event.RESET, State.IDLE));
+ mIdentifierCollection.update(DecoderStateIdentifier.IDLE);
mSourceOverflow = false;
}
@Override
public void start()
{
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
+ mIdentifierCollection.broadcastIdentifiers();
- if(mTrafficChannelEndListener != null)
+ if(mChannel.getChannelType() == ChannelType.TRAFFIC)
{
setState(State.CALL);
}
@@ -143,7 +213,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
public void dispose()
{
- mCallEventListener = null;
+ mDecodeEventListener = null;
mDecoderStateListener = null;
mSquelchStateListener = null;
}
@@ -159,21 +229,11 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
return mInternalSourceEventListener;
}
- private boolean isStandardChannel()
- {
- return mChannelType == ChannelType.STANDARD;
- }
-
- private boolean isTrafficChannel()
- {
- return mChannelType == ChannelType.TRAFFIC;
- }
-
public void setStandardChannelTimeout(long milliseconds)
{
mStandardChannelFadeTimeout = milliseconds;
- if(mChannelType == ChannelType.STANDARD)
+ if(mChannel.isStandardChannel())
{
mFadeTimeout = mStandardChannelFadeTimeout;
}
@@ -183,7 +243,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
{
mTrafficChannelFadeTimeout = milliseconds;
- if(mChannelType == ChannelType.TRAFFIC)
+ if(mChannel.isTrafficChannel())
{
mFadeTimeout = System.currentTimeMillis() + mTrafficChannelFadeTimeout;
}
@@ -209,7 +269,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
*/
private void updateFadeTimeout()
{
- if(isTrafficChannel())
+ if(mChannel.isTrafficChannel())
{
mFadeTimeout = System.currentTimeMillis() + mTrafficChannelFadeTimeout;
}
@@ -225,7 +285,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
*/
private void updateResetTimeout()
{
- if(isTrafficChannel())
+ if(mChannel.isTrafficChannel())
{
mEndTimeout = System.currentTimeMillis();
}
@@ -298,26 +358,35 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
broadcast(SquelchState.SQUELCH);
updateFadeTimeout();
mState = state;
+ mIdentifierCollection.update(DecoderStateIdentifier.ACTIVE);
break;
case CONTROL:
//Don't allow traffic channels to be control channels, otherwise they can't transition to teardown
- if(isStandardChannel())
+ if(mChannel.isStandardChannel())
{
broadcast(SquelchState.SQUELCH);
updateFadeTimeout();
mState = state;
+ mIdentifierCollection.update(DecoderStateIdentifier.CONTROL);
}
break;
case DATA:
+ broadcast(SquelchState.SQUELCH);
+ updateFadeTimeout();
+ mState = state;
+ mIdentifierCollection.update(DecoderStateIdentifier.DATA);
+ break;
case ENCRYPTED:
broadcast(SquelchState.SQUELCH);
updateFadeTimeout();
mState = state;
+ mIdentifierCollection.update(DecoderStateIdentifier.ENCRYPTED);
break;
case CALL:
broadcast(SquelchState.UNSQUELCH);
updateFadeTimeout();
mState = state;
+ mIdentifierCollection.update(DecoderStateIdentifier.CALL);
break;
case FADE:
processFadeState();
@@ -330,12 +399,11 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
break;
case RESET:
mState = State.IDLE;
+ mIdentifierCollection.update(DecoderStateIdentifier.IDLE);
break;
default:
break;
}
-
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
}
}
@@ -351,14 +419,13 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
/**
* This method is invoked if the source buffer provider goes into overflow state. Since this is an external state,
* we use the mSourceOverflow variable to override the internal state reported to external listeners.
+ *
* @param overflow true to indicate an overflow state
*/
@Override
public void sourceOverflow(boolean overflow)
{
mSourceOverflow = overflow;
-
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.BUFFER_OVERFLOW, mSourceOverflow));
}
/**
@@ -380,9 +447,9 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
{
updateResetTimeout();
mState = State.FADE;
+ mIdentifierCollection.update(DecoderStateIdentifier.FADE);
broadcast(SquelchState.SQUELCH);
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
}
private void processIdleState()
@@ -391,12 +458,11 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
if(mState == State.FADE)
{
- getMutableMetadata().resetTemporalAttributes();
broadcast(new DecoderStateEvent(this, Event.RESET, State.IDLE));
}
mState = State.IDLE;
- getMutableMetadata().receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
+ mIdentifierCollection.update(DecoderStateIdentifier.IDLE);
}
private void processTeardownState()
@@ -404,48 +470,58 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
broadcast(SquelchState.SQUELCH);
mState = State.TEARDOWN;
+ mIdentifierCollection.update(DecoderStateIdentifier.TEARDOWN);
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_STATE, mState));
-
- if(mTrafficChannelEndListener != null && mTrafficChannelCallEvent != null)
+ if(mChannel.isTrafficChannel())
{
- mTrafficChannelCallEvent.end();
- broadcast(mTrafficChannelCallEvent);
- mTrafficChannelEndListener.callEnd(mTrafficChannelCallEvent.getChannel());
- mTrafficChannelEndListener = null;
- mTrafficChannelCallEvent = null;
+ broadcast(new ChannelEvent(mChannel, ChannelEvent.Event.REQUEST_DISABLE));
}
}
/**
* Broadcasts the call event to the registered listener
*/
- protected void broadcast(CallEvent event)
+ protected void broadcast(IDecodeEvent event)
{
- if(mCallEventListener != null)
+ if(mDecodeEventListener != null)
{
- mCallEventListener.receive(event);
+ mDecodeEventListener.receive(event);
+ }
+ }
+
+ /**
+ * Broadcasts the channel event to a registered listener
+ */
+ private void broadcast(ChannelEvent channelEvent)
+ {
+ if(mChannelEventListener != null)
+ {
+ mChannelEventListener.receive(channelEvent);
}
}
@Override
- public void addCallEventListener(Listener listener)
+ public void setChannelEventListener(Listener listener)
{
- mCallEventListener = listener;
+ mChannelEventListener = listener;
}
@Override
- public void removeCallEventListener(Listener listener)
+ public void removeChannelEventListener()
{
- mCallEventListener = null;
+ mChannelEventListener = null;
}
-
- //NEW:
@Override
- public Listener getAttributeChangeRequestListener()
+ public void addDecodeEventListener(Listener listener)
{
- return mMutableMetadata;
+ mDecodeEventListener = listener;
+ }
+
+ @Override
+ public void removeDecodeEventListener(Listener listener)
+ {
+ mDecodeEventListener = null;
}
/**
@@ -483,57 +559,6 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
return mDecoderStateEventReceiver;
}
- /**
- * Registers a listener to be notified when a traffic channel call event is
- * completed, so that the listener can perform call tear-down
- */
- public void configureAsTrafficChannel(TrafficChannelManager manager, CallEvent callEvent)
- {
- mTrafficChannelEndListener = manager;
-
- mTrafficChannelCallEvent = callEvent;
-
- /* Broadcast the call event details as metadata for the audio manager */
- String channel = mTrafficChannelCallEvent.getChannel();
-
- if(channel != null)
- {
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_FREQUENCY_LABEL, channel));
- }
-
- long frequency = mTrafficChannelCallEvent.getFrequency();
-
- if(frequency > 0)
- {
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_FREQUENCY, frequency));
- }
-
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.PRIMARY_DECODER_TYPE,
- mTrafficChannelCallEvent.getDecoderType()));
-
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_NAME, "TRAFFIC"));
-
- String from = mTrafficChannelCallEvent.getFromID();
-
- if(from != null)
- {
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_FROM, from,
- mTrafficChannelCallEvent.getFromIDAlias()));
- }
-
- String to = mTrafficChannelCallEvent.getToID();
-
- if(to != null)
- {
- mMutableMetadata.receive(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, to,
- mTrafficChannelCallEvent.getToIDAlias()));
- }
-
- /* Rebroadcast the allocation event so that the internal decoder states
- * can self-configure with the call event details */
- broadcast(mTrafficChannelCallEvent);
- }
-
/**
* Registers the listener to receive source events from the channel state
*/
@@ -572,7 +597,8 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
//in an active (ie sync locked) state.
if(getState().isActiveState())
{
- broadcast(SourceEvent.frequencyErrorMeasurementSyncLocked(sourceEvent.getValue().longValue(), mChannelType.name()));
+ broadcast(SourceEvent.frequencyErrorMeasurementSyncLocked(sourceEvent.getValue().longValue(),
+ mChannel.getChannelType().name()));
}
break;
}
@@ -598,7 +624,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
case CHANGE_CALL_TIMEOUT:
if(event instanceof ChangeChannelTimeoutEvent)
{
- ChangeChannelTimeoutEvent timeout = (ChangeChannelTimeoutEvent) event;
+ ChangeChannelTimeoutEvent timeout = (ChangeChannelTimeoutEvent)event;
if(timeout.getChannelType() == ChannelType.STANDARD)
{
@@ -618,7 +644,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
}
break;
case END:
- if(isTrafficChannel())
+ if(mChannel.isTrafficChannel())
{
setState(State.TEARDOWN);
}
@@ -628,7 +654,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
}
break;
case RESET:
- /* Channel State does not respond to reset events */
+ /* Channel State does not respond to reset events */
break;
default:
break;
@@ -660,7 +686,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
}
else if(mState == State.FADE && mEndTimeout <= System.currentTimeMillis())
{
- if(isTrafficChannel())
+ if(mChannel.isTrafficChannel())
{
processTeardownState();
}
diff --git a/src/main/java/io/github/dsheirer/channel/state/DecoderState.java b/src/main/java/io/github/dsheirer/channel/state/DecoderState.java
index 0ce9cfc2..8eead5af 100644
--- a/src/main/java/io/github/dsheirer/channel/state/DecoderState.java
+++ b/src/main/java/io/github/dsheirer/channel/state/DecoderState.java
@@ -1,15 +1,23 @@
package io.github.dsheirer.channel.state;
-import io.github.dsheirer.alias.AliasList;
-import io.github.dsheirer.channel.metadata.AttributeChangeRequest;
-import io.github.dsheirer.channel.metadata.IAttributeChangeRequestProvider;
+import io.github.dsheirer.channel.IChannelDescriptor;
+import io.github.dsheirer.identifier.Form;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.identifier.IdentifierClass;
+import io.github.dsheirer.identifier.IdentifierUpdateListener;
+import io.github.dsheirer.identifier.IdentifierUpdateNotification;
+import io.github.dsheirer.identifier.IdentifierUpdateProvider;
+import io.github.dsheirer.identifier.MutableIdentifierCollection;
+import io.github.dsheirer.identifier.configuration.ChannelDescriptorConfigurationIdentifier;
+import io.github.dsheirer.identifier.configuration.DecoderTypeConfigurationIdentifier;
+import io.github.dsheirer.message.IMessage;
import io.github.dsheirer.message.IMessageListener;
-import io.github.dsheirer.message.Message;
import io.github.dsheirer.module.Module;
import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.event.ActivitySummaryProvider;
import io.github.dsheirer.module.decode.event.CallEvent;
-import io.github.dsheirer.module.decode.event.ICallEventProvider;
+import io.github.dsheirer.module.decode.event.IDecodeEvent;
+import io.github.dsheirer.module.decode.event.IDecodeEventProvider;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
@@ -19,47 +27,87 @@ import io.github.dsheirer.sample.Listener;
*
* Provides access to a textual activity summary of events observed.
*/
-public abstract class DecoderState extends Module implements ActivitySummaryProvider, Listener,
- IAttributeChangeRequestProvider, ICallEventProvider, IDecoderStateEventListener,
- IDecoderStateEventProvider, IMessageListener
+public abstract class DecoderState extends Module implements ActivitySummaryProvider, Listener,
+ IDecodeEventProvider, IDecoderStateEventListener, IDecoderStateEventProvider, IMessageListener,
+ IdentifierUpdateProvider, IdentifierUpdateListener
{
+// private final static Logger mLog = LoggerFactory.getLogger(DecoderState.class);
+
protected String DIVIDER1 = "======================================================\n";
protected String DIVIDER2 = "------------------------------------------------------\n";
/* This has to be a broadcaster in order for references to persist */
- private Broadcaster mCallEventBroadcaster = new Broadcaster<>();
- private Broadcaster mAttributeChangeRequestBroadcaster = new Broadcaster<>();
+ private Broadcaster mDecodeEventBroadcaster = new Broadcaster<>();
private Listener mDecoderStateListener;
-
private DecoderStateEventListener mDecoderStateEventListener = new DecoderStateEventListener();
+ private MutableIdentifierCollection mIdentifierCollection = new MutableIdentifierCollection();
+ private ConfigurationIdentifierListener mConfigurationIdentifierListener = new ConfigurationIdentifierListener();
+ private IChannelDescriptor mCurrentChannel;
protected CallEvent mCurrentCallEvent;
- private AliasList mAliasList;
-
- public DecoderState(AliasList aliasList)
+ public DecoderState()
{
- mAliasList = aliasList;
+ mIdentifierCollection.update(new DecoderTypeConfigurationIdentifier(getDecoderType()));
+ }
+
+ @Override
+ public void start()
+ {
+ //Broadcast the existing identifiers (as add events) so that they can be received by external listeners
+ mIdentifierCollection.broadcastIdentifiers();
}
public abstract DecoderType getDecoderType();
- public AliasList getAliasList()
+ /**
+ * Current collection of identifiers managed by the decoder state.
+ */
+ public MutableIdentifierCollection getIdentifierCollection()
{
- return mAliasList;
+ return mIdentifierCollection;
}
- public boolean hasAliasList()
+ /**
+ * Registers the listener to receive identifier update notifications
+ */
+ @Override
+ public void setIdentifierUpdateListener(Listener listener)
{
- return mAliasList != null;
+ getIdentifierCollection().setIdentifierUpdateListener(listener);
+ }
+
+ /**
+ * Removes the listener from receiving identifier update notifications
+ */
+ @Override
+ public void removeIdentifierUpdateListener()
+ {
+ getIdentifierCollection().removeIdentifierUpdateListener();
}
/**
* Provides subclass reference to the call event broadcaster
*/
- protected Broadcaster getCallEventBroadcaster()
+ protected Broadcaster getDecodeEventBroadcaster()
{
- return mCallEventBroadcaster;
+ return mDecodeEventBroadcaster;
+ }
+
+
+ @Override
+ public Listener getMessageListener()
+ {
+ return this;
+ }
+
+ /**
+ * Resets the current temporal state variables to end the current event and prepare for the next.
+ */
+ protected void resetState()
+ {
+ mIdentifierCollection.remove(IdentifierClass.USER);
+ mCurrentChannel = null;
}
/**
@@ -85,11 +133,9 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
*/
public void dispose()
{
- mCallEventBroadcaster.dispose();
- mCallEventBroadcaster = null;
+ mDecodeEventBroadcaster.dispose();
+ mDecodeEventBroadcaster = null;
mDecoderStateListener = null;
-
- mAliasList = null;
}
/**
@@ -98,29 +144,29 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
public abstract String getActivitySummary();
/**
- * Broadcasts a call event to any registered listeners
+ * Broadcasts a decode event to any registered listeners
*/
- protected void broadcast(CallEvent event)
+ protected void broadcast(IDecodeEvent event)
{
- mCallEventBroadcaster.broadcast(event);
+ mDecodeEventBroadcaster.broadcast(event);
}
/**
* Adds a call event listener
*/
@Override
- public void addCallEventListener(Listener listener)
+ public void addDecodeEventListener(Listener listener)
{
- mCallEventBroadcaster.addListener(listener);
+ mDecodeEventBroadcaster.addListener(listener);
}
/**
* Removes the call event listener
*/
@Override
- public void removeCallEventListener(Listener listener)
+ public void removeDecodeEventListener(Listener listener)
{
- mCallEventBroadcaster.removeListener(listener);
+ mDecodeEventBroadcaster.removeListener(listener);
}
@Override
@@ -167,43 +213,66 @@ public abstract class DecoderState extends Module implements ActivitySummaryProv
mDecoderStateListener = null;
}
- @Override
- public Listener getMessageListener()
- {
- return this;
- }
-
/**
- * Broadcasts the attribute change request to the registered listener
- */
- protected void broadcast(AttributeChangeRequest> request)
- {
- mAttributeChangeRequestBroadcaster.broadcast(request);
- }
-
- /**
- * Sets the listener to receive attribute change requests from this decoder state
+ * Listens for configuration identifiers and adds them to this decoder state's identifier collection.
+ * @return
*/
@Override
- public void setAttributeChangeRequestListener(Listener listener)
+ public Listener getIdentifierUpdateListener()
{
- mAttributeChangeRequestBroadcaster.addListener(listener);
+ return mConfigurationIdentifierListener;
}
/**
- * Removes any listener from receiving attribute change requests
+ * Configuration identifier listener.
*/
- @Override
- public void removeAttributeChangeRequestListener(Listener listener)
+ public ConfigurationIdentifierListener getConfigurationIdentifierListener()
{
- mAttributeChangeRequestBroadcaster.removeListener(listener);
+ return mConfigurationIdentifierListener;
}
/**
- * Broadaster so that Attribute monitors can broadcast attribute change requests
+ * Optional current channel descriptor
*/
- protected Listener getAttributeChangeRequestListener()
+ protected IChannelDescriptor getCurrentChannel()
{
- return mAttributeChangeRequestBroadcaster;
+ return mCurrentChannel;
+ }
+
+ /**
+ * Sets the current channel descriptor
+ */
+ protected void setCurrentChannel(IChannelDescriptor channel)
+ {
+ mCurrentChannel = channel;
+ }
+
+ /**
+ * Listener for configuration type identifier updates sent from the channel state. Adds configuration
+ * identifiers to this decoder state so that decode events will contain configuration details in the
+ * event's identifier collection.
+ */
+ public class ConfigurationIdentifierListener implements Listener
+ {
+ @Override
+ public void receive(IdentifierUpdateNotification identifierUpdateNotification)
+ {
+ if(identifierUpdateNotification.getIdentifier().getIdentifierClass() == IdentifierClass.CONFIGURATION &&
+ identifierUpdateNotification.getIdentifier().getForm() != Form.DECODER_TYPE &&
+ identifierUpdateNotification.getIdentifier().getForm() != Form.CHANNEL_DESCRIPTOR)
+ {
+ getIdentifierCollection().update(identifierUpdateNotification.getIdentifier());
+ }
+
+ if(identifierUpdateNotification.getOperation() == IdentifierUpdateNotification.Operation.ADD)
+ {
+ Identifier identifier = identifierUpdateNotification.getIdentifier();
+
+ if(identifier instanceof ChannelDescriptorConfigurationIdentifier)
+ {
+ mCurrentChannel = ((ChannelDescriptorConfigurationIdentifier)identifier).getValue();
+ }
+ }
+ }
}
}
diff --git a/src/main/java/io/github/dsheirer/channel/state/DecoderStateEvent.java b/src/main/java/io/github/dsheirer/channel/state/DecoderStateEvent.java
index ad853865..90d868a1 100644
--- a/src/main/java/io/github/dsheirer/channel/state/DecoderStateEvent.java
+++ b/src/main/java/io/github/dsheirer/channel/state/DecoderStateEvent.java
@@ -62,7 +62,6 @@ public class DecoderStateEvent
END,
RESET,
SOURCE_FREQUENCY,
- START,
- TRAFFIC_CHANNEL_ALLOCATION;
+ START;
}
}
\ No newline at end of file
diff --git a/src/main/java/io/github/dsheirer/channel/state/IDecoderStateEventProvider.java b/src/main/java/io/github/dsheirer/channel/state/IDecoderStateEventProvider.java
index 0e387e2e..e0b27fe7 100644
--- a/src/main/java/io/github/dsheirer/channel/state/IDecoderStateEventProvider.java
+++ b/src/main/java/io/github/dsheirer/channel/state/IDecoderStateEventProvider.java
@@ -4,6 +4,6 @@ import io.github.dsheirer.sample.Listener;
public interface IDecoderStateEventProvider
{
- public void setDecoderStateListener( Listener listener );
- public void removeDecoderStateListener();
+ void setDecoderStateListener( Listener