diff --git a/src/controller/ThreadPoolManager.java b/src/controller/ThreadPoolManager.java index d73bfcf8..c5527970 100644 --- a/src/controller/ThreadPoolManager.java +++ b/src/controller/ThreadPoolManager.java @@ -32,7 +32,6 @@ public class ThreadPoolManager private final static Logger mLog = LoggerFactory.getLogger( ThreadPoolManager.class ); private int THREAD_POOL_SIZE = 2; - private int MAX_TASK_COUNT = 24; private HashMap,ThreadType> mTasks = new HashMap,ThreadType>(); @@ -55,21 +54,12 @@ public class ThreadPoolManager new NamingThreadFactory( "sdrtrunk" ) ); } - if( mTasks.size() <= MAX_TASK_COUNT ) - { - ScheduledFuture task = - mExecutor.scheduleAtFixedRate( command, 0, period, unit ); - - mTasks.put( task, type ); - - return task; - } - else - { - throw new RejectedExecutionException( "Cannot schedule task - at " - + "max task count [" + mTasks.size() + "]" ); - } + ScheduledFuture task = + mExecutor.scheduleAtFixedRate( command, 0, period, unit ); + mTasks.put( task, type ); + + return task; } public void scheduleOnce( Runnable command, long delay, TimeUnit unit ) @@ -81,22 +71,14 @@ public class ThreadPoolManager new NamingThreadFactory( "sdrtrunk" ) ); } - if( mTasks.size() <= MAX_TASK_COUNT ) - { - mExecutor.schedule( command, delay, unit ); - } - else - { - throw new RejectedExecutionException( "Cannot schedule task - at " - + "max task count [" + mTasks.size() + "]" ); - } + mExecutor.schedule( command, delay, unit ); } public void cancel( ScheduledFuture task ) { task.cancel( true ); - ThreadType type = mTasks.remove( task ); + mTasks.remove( task ); } public int getTaskCount( ThreadType type ) diff --git a/src/module/decode/event/CallEventModel.java b/src/module/decode/event/CallEventModel.java index 38b5d40d..eee813cf 100644 --- a/src/module/decode/event/CallEventModel.java +++ b/src/module/decode/event/CallEventModel.java @@ -66,8 +66,6 @@ public class CallEventModel extends AbstractTableModel implements Listener 1; - } - - return true; - } - private Alias getAlias( String talkgroup ) { if( hasAliasList() ) diff --git a/src/module/decode/ltrnet/LTRNetDecoderState.java b/src/module/decode/ltrnet/LTRNetDecoderState.java index 7f66d5fc..47034de5 100644 --- a/src/module/decode/ltrnet/LTRNetDecoderState.java +++ b/src/module/decode/ltrnet/LTRNetDecoderState.java @@ -675,7 +675,7 @@ public class LTRNetDecoderState extends DecoderState } /** - * Resets the decoder state for re-use on another channel + * Performs a full reset */ public void reset() { @@ -694,7 +694,7 @@ public class LTRNetDecoderState extends DecoderState } /** - * Resets the decoder state after a call event + * Resets the decoder state after a call or other decode event */ private void resetState() { diff --git a/src/module/decode/ltrstandard/LTRStandardDecoderPanel.java b/src/module/decode/ltrstandard/LTRStandardDecoderPanel.java index 08a0983b..75106285 100644 --- a/src/module/decode/ltrstandard/LTRStandardDecoderPanel.java +++ b/src/module/decode/ltrstandard/LTRStandardDecoderPanel.java @@ -21,6 +21,7 @@ import java.awt.EventQueue; import javax.swing.JLabel; +import net.miginfocom.swing.MigLayout; import module.decode.state.ChangedAttribute; import module.decode.state.DecoderPanel; import settings.ColorSetting; @@ -53,7 +54,11 @@ public class LTRStandardDecoderPanel extends DecoderPanel public void init() { - mProtocol.setFont( mFontDecoder ); + super.init(); + + setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]0[]") ); + + mProtocol.setFont( mFontDecoder ); mProtocol.setForeground( mColorLabelDecoder ); mTalkgroup.setFont( mFontDecoder ); diff --git a/src/module/decode/ltrstandard/LTRStandardDecoderState.java b/src/module/decode/ltrstandard/LTRStandardDecoderState.java index e6e1eeb9..94cd32b9 100644 --- a/src/module/decode/ltrstandard/LTRStandardDecoderState.java +++ b/src/module/decode/ltrstandard/LTRStandardDecoderState.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014,2015 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,6 @@ ******************************************************************************/ package module.decode.ltrstandard; -import java.text.DecimalFormat; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -35,22 +34,19 @@ import module.decode.state.DecoderStateEvent.Event; import module.decode.state.State; import alias.Alias; import alias.AliasList; +import audio.metadata.Metadata; +import audio.metadata.MetadataType; public class LTRStandardDecoderState extends DecoderState { - private static final int sINT_NULL_VALUE = -1; - private DecimalFormat mDecimalFormatter = new DecimalFormat("0.00000"); - private HashMap mActiveCalls = new HashMap(); private HashSet mTalkgroupsFirstHeard = new HashSet(); private TreeSet mTalkgroups = new TreeSet(); private TreeSet mActiveLCNs = new TreeSet(); - private int mMonitoredLCN; private String mTalkgroup; private Alias mTalkgroupAlias; private int mChannelNumber; - private long mFrequency; public LTRStandardDecoderState( AliasList aliasList ) @@ -111,14 +107,13 @@ public class LTRStandardDecoderState extends DecoderState broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS ); LTRCallEvent current = getCurrentCallEvent(); - - /* If we have an ongoing call, then add this message - * to the current event - if addMessage returns - * false, then we have a different talkgroup and a - * new call event, so close out the old one. */ - if( current != null && !current.addMessage( ltr ) ) + + /* Detect when we haven't reset from the previous + * call and now have a new call coming in with + * a different talkgroup */ + if( current != null && isDifferentTalkgroup( mTalkgroup ) ) { - mCurrentCallEvent.setEnd( System.currentTimeMillis() ); + mCurrentCallEvent.end(); broadcast( mCurrentCallEvent ); mCurrentCallEvent = null; } @@ -136,30 +131,35 @@ public class LTRStandardDecoderState extends DecoderState broadcast( mCurrentCallEvent ); - broadcast( new DecoderStateEvent( this, Event.START, State.CALL ) ); + broadcast( new Metadata( MetadataType.TO, + mTalkgroup, mTalkgroupAlias, true ) ); + + broadcast( new DecoderStateEvent( this, + Event.START, State.CALL ) ); } else { - broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.CALL ) ); + broadcast( new DecoderStateEvent( this, + Event.CONTINUATION, State.CALL ) ); } } } break; case CA_ENDD: mTalkgroup = ltr.getTalkgroupID(); - broadcast( ChangedAttribute.FROM_TALKGROUP ); + broadcast( ChangedAttribute.TO_TALKGROUP ); mTalkgroupAlias = ltr.getTalkgroupIDAlias(); - broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS ); + broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS ); if( mCurrentCallEvent != null ) { - mCurrentCallEvent.setEnd( System.currentTimeMillis() ); + mCurrentCallEvent.end(); broadcast( mCurrentCallEvent ); broadcast( new DecoderStateEvent( this, Event.END, State.FADE ) ); mCurrentCallEvent = null; } - + int home = ltr.getHomeRepeater(); if( 0 < home && home <= 20 ) @@ -182,9 +182,9 @@ public class LTRStandardDecoderState extends DecoderState { if( channel == home ) { - if( mMonitoredLCN != channel ) + if( mChannelNumber != channel ) { - mMonitoredLCN = channel; + mChannelNumber = channel; broadcast( ChangedAttribute.CHANNEL_NUMBER ); } @@ -206,15 +206,16 @@ public class LTRStandardDecoderState extends DecoderState if( idleChannel == ltr.getHomeRepeater() && idleChannel == ltr.getFree() ) { - if( mMonitoredLCN != idleChannel ) + if( mChannelNumber != idleChannel ) { - mMonitoredLCN = idleChannel; + mChannelNumber = idleChannel; broadcast( ChangedAttribute.CHANNEL_NUMBER ); } mActiveLCNs.add( idleChannel ); } - broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.IDLE ) ); + broadcast( new DecoderStateEvent( this, + Event.CONTINUATION, State.IDLE ) ); break; case UN_KNWN: default: @@ -224,60 +225,49 @@ public class LTRStandardDecoderState extends DecoderState } } -// /** -// * Intercept the fade event so that we can generate a call end event -// */ -// @Override -// public void fade( final CallEventType type ) -// { -// /* We can receive multiple call tear-down messages -- only respond to -// * the message that can change the state to fade */ -// if( getState().canChangeTo( State.FADE ) ) -// { -// mActiveCalls.clear(); -// -// LTRCallEvent current = getCurrentLTRCallEvent(); -// -// if( current != null ) -// { -// /* Close out the call event. If we only received 1 call -// * message, then flag it as noise and remove the call event */ -// if( current.isValid() ) -// { -// mCallEventModel.setEnd( current ); -// } -// else -// { -// mCallEventModel.remove( current ); -// } -// } -// -// setCurrentCallEvent( null ); -// } -// -// super.fade( type ); -// } - + /** + * Indicates if the talkgroup is different than the talkgroup specified in + * the current call event + */ + private boolean isDifferentTalkgroup( String talkgroup ) + { + return talkgroup != null && + mCurrentCallEvent != null && + mCurrentCallEvent.getToID() != null && + !mCurrentCallEvent.getToID().contentEquals( talkgroup ); + } + + /** + * Performs a full reset + */ public void reset() { + mActiveCalls.clear(); + mTalkgroupsFirstHeard.clear(); + mTalkgroups.clear(); + mActiveLCNs.clear(); + mChannelNumber = 0; + resetState(); - + } + + /** + * Performs a temporal reset following a call or other decode event + */ + private void resetState() + { if( mCurrentCallEvent != null ) { mCurrentCallEvent.setEnd( System.currentTimeMillis() ); broadcast( mCurrentCallEvent ); mCurrentCallEvent = null; } - - } - - private void resetState() - { + mTalkgroup = null; - broadcast( ChangedAttribute.FROM_TALKGROUP ); + broadcast( ChangedAttribute.TO_TALKGROUP ); mTalkgroupAlias = null; - broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS ); + broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS ); } public String getTalkgroup() @@ -303,7 +293,6 @@ public class LTRStandardDecoderState extends DecoderState @Override public void init() { - } @Override @@ -333,9 +322,9 @@ public class LTRStandardDecoderState extends DecoderState sb.append( "Monitored LCN: " ); - if( mMonitoredLCN > 0 ) + if( mChannelNumber > 0 ) { - sb.append( mMonitoredLCN ); + sb.append( mChannelNumber ); } else { diff --git a/src/module/decode/state/ChannelState.java b/src/module/decode/state/ChannelState.java index 96bd25db..1510d490 100644 --- a/src/module/decode/state/ChannelState.java +++ b/src/module/decode/state/ChannelState.java @@ -568,7 +568,6 @@ public class ChannelState extends Module implements ICallEventProvider, mSquelchLocked = true; break; case CONTINUATION: - case DECODE: if( isEndingState() ) { setState( event.getState() ); @@ -578,6 +577,12 @@ public class ChannelState extends Module implements ICallEventProvider, updateFadeTimeout(); } break; + case DECODE: + if( getState() == State.IDLE ) + { + setState( event.getState() ); + } + break; case END: setState( State.FADE ); break; diff --git a/src/record/wave/RealBufferWaveRecorder.java b/src/record/wave/RealBufferWaveRecorder.java index 880ca83c..5de38587 100644 --- a/src/record/wave/RealBufferWaveRecorder.java +++ b/src/record/wave/RealBufferWaveRecorder.java @@ -104,7 +104,7 @@ public class RealBufferWaveRecorder extends Module StringBuilder sb = new StringBuilder(); sb.append( mFilePrefix ); sb.append( "_" ); - sb.append( TimeStamp.getTimeStamp( "_" ) ); + sb.append( TimeStamp.getLongTimeStamp( "_" ) ); sb.append( ".wav" ); mFile = Paths.get( sb.toString() ); diff --git a/src/util/TimeStamp.java b/src/util/TimeStamp.java index c4777c10..0985f6cd 100644 --- a/src/util/TimeStamp.java +++ b/src/util/TimeStamp.java @@ -24,6 +24,7 @@ public class TimeStamp { private static SimpleDateFormat mSDFDate = new SimpleDateFormat( "yyyyMMdd" ); private static SimpleDateFormat mSDFTime = new SimpleDateFormat( "HHmmss" ); + private static SimpleDateFormat mSDFTimeWithMilliseconds = new SimpleDateFormat( "HHmmss.SSS" ); /** * Returns the current system date formatted as yyyy-MM-dd @@ -57,6 +58,14 @@ public class TimeStamp return mSDFTime.format( new Date( timestamp ) ); } + /** + * Returns the timestamp formatted as a time of HH:mm:ss + */ + public static String getFormattedTimeWithMilliseconds( long timestamp ) + { + return mSDFTime.format( new Date( timestamp ) ); + } + /** * Returns current system time formatted as yyyy-MM-dd*HH:mm:ss * with the * representing the separator attribute @@ -80,5 +89,30 @@ public class TimeStamp return sb.toString(); } + + /** + * Returns current system time formatted as yyyy-MM-dd*HH:mm:ss.SSS + * with the * representing the separator attribute + */ + public static String getLongTimeStamp( String separator ) + { + return getLongTimeStamp( System.currentTimeMillis(), separator ); + } + + /** + * Returns timestamp formatted as yyyy-MM-dd*HH:mm:ss.SSS + * with the * representing the separator attribute + */ + public static String getLongTimeStamp( long timestamp, String separator ) + { + StringBuilder sb = new StringBuilder(); + + sb.append( getFormattedDate( timestamp ) ); + sb.append( separator ); + sb.append( getFormattedTimeWithMilliseconds( timestamp ) ); + + return sb.toString(); + } + }