mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Merges #34 Major redesign of Tuner, Channel and Alias management.
Changes to model, view and controller components and updates all gui editors. Removes the configuration panel and tree and replaces with 3 new panels. Updates playlist.xml to a new playlist_v2.xml format.
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
|
||||
package module;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public abstract class Module
|
||||
{
|
||||
/**
|
||||
@@ -57,9 +59,9 @@ public abstract class Module
|
||||
public abstract void reset();
|
||||
|
||||
/**
|
||||
* Start processing.
|
||||
* Start processing. Provides an executor to use for scheduling tasks
|
||||
*/
|
||||
public abstract void start();
|
||||
public abstract void start( ScheduledExecutorService executor );
|
||||
|
||||
/**
|
||||
* Stop processing
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
* Copyright (C) 2015-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
|
||||
@@ -27,8 +27,11 @@ import message.IMessageListener;
|
||||
import message.IMessageProvider;
|
||||
import message.Message;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.CallEventModel;
|
||||
import module.decode.event.ICallEventListener;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.event.MessageActivityModel;
|
||||
import module.decode.state.ChannelState;
|
||||
import module.decode.state.DecoderState;
|
||||
import module.decode.state.DecoderStateEvent;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
@@ -43,16 +46,19 @@ import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.IComplexBufferListener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IRealBufferProvider;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferProvider;
|
||||
import sample.real.IUnFilteredRealBufferListener;
|
||||
import sample.real.IUnFilteredRealBufferProvider;
|
||||
import sample.real.RealBuffer;
|
||||
import source.ComplexSource;
|
||||
import source.RealSource;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import source.tuner.frequency.IFrequencyCorrectionController;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.IFrequencyChangeListener;
|
||||
import source.tuner.frequency.IFrequencyChangeProvider;
|
||||
import audio.AudioPacket;
|
||||
import audio.IAudioPacketListener;
|
||||
import audio.IAudioPacketProvider;
|
||||
@@ -63,6 +69,7 @@ import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.ISquelchStateProvider;
|
||||
import audio.squelch.SquelchState;
|
||||
import controller.NamingThreadFactory;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.IChannelEventListener;
|
||||
import controller.channel.IChannelEventProvider;
|
||||
@@ -87,8 +94,7 @@ import controller.channel.IChannelEventProvider;
|
||||
*/
|
||||
public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ProcessingChain.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ProcessingChain.class );
|
||||
|
||||
private Broadcaster<AudioPacket> mAudioPacketBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<Metadata> mMetadataBroadcaster = new Broadcaster<>();
|
||||
@@ -96,23 +102,61 @@ public class ProcessingChain implements IChannelEventListener
|
||||
private Broadcaster<ChannelEvent> mChannelEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<ComplexBuffer> mComplexBufferBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<DecoderStateEvent> mDecoderStateEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<FrequencyChangeEvent> mFrequencyChangeEventBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<Message> mMessageBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<RealBuffer> mRealBufferBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<RealBuffer> mFilteredRealBufferBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<RealBuffer> mUnFilteredRealBufferBroadcaster = new Broadcaster<>();
|
||||
private Broadcaster<SquelchState> mSquelchStateBroadcaster = new Broadcaster<>();
|
||||
|
||||
private ScheduledExecutorService mScheduledExecutorService;
|
||||
private String mName;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
|
||||
protected Source mSource;
|
||||
private List<Module> mModules = new ArrayList<>();
|
||||
private IFrequencyCorrectionController mFrequencyCorrectionController;
|
||||
|
||||
public ProcessingChain( String name )
|
||||
{
|
||||
mScheduledExecutorService = Executors.newScheduledThreadPool( 1,
|
||||
new NamingThreadFactory( "channel " + name ) );
|
||||
}
|
||||
private CallEventModel mCallEventModel;
|
||||
private ChannelState mChannelState;
|
||||
private MessageActivityModel mMessageActivityModel;
|
||||
|
||||
/**
|
||||
* Creates a processing chain for managing a set of modules
|
||||
*
|
||||
* @param name for thread pool naming each thread
|
||||
* @param channelType
|
||||
*/
|
||||
public ProcessingChain( String name, ChannelType channelType )
|
||||
{
|
||||
mName = name;
|
||||
|
||||
mChannelState = new ChannelState( channelType );
|
||||
addModule( mChannelState );
|
||||
|
||||
mCallEventModel = new CallEventModel();
|
||||
addCallEventListener( mCallEventModel );
|
||||
}
|
||||
|
||||
public CallEventModel getCallEventModel()
|
||||
{
|
||||
return mCallEventModel;
|
||||
}
|
||||
|
||||
public ChannelState getChannelState()
|
||||
{
|
||||
return mChannelState;
|
||||
}
|
||||
|
||||
public MessageActivityModel getMessageActivityModel()
|
||||
{
|
||||
return mMessageActivityModel;
|
||||
}
|
||||
|
||||
public void setMessageActivityModel( MessageActivityModel model )
|
||||
{
|
||||
mMessageActivityModel = model;
|
||||
|
||||
addMessageListener( mMessageActivityModel );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
stop();
|
||||
@@ -127,15 +171,18 @@ public class ProcessingChain implements IChannelEventListener
|
||||
mScheduledExecutorService.shutdownNow();
|
||||
mScheduledExecutorService = null;
|
||||
|
||||
mFrequencyCorrectionController = null;
|
||||
|
||||
mAudioPacketBroadcaster.dispose();
|
||||
mCallEventBroadcaster.dispose();
|
||||
mChannelEventBroadcaster.dispose();
|
||||
mComplexBufferBroadcaster.dispose();
|
||||
mMessageBroadcaster.dispose();
|
||||
mRealBufferBroadcaster.dispose();
|
||||
mFilteredRealBufferBroadcaster.dispose();
|
||||
mSquelchStateBroadcaster.dispose();
|
||||
|
||||
if( mScheduledExecutorService != null )
|
||||
{
|
||||
mScheduledExecutorService.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +200,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
* Indicates if this processing chain is currently receiving samples from
|
||||
* a source and sending those samples to the decoders.
|
||||
*/
|
||||
public boolean processing()
|
||||
public boolean isProcessing()
|
||||
{
|
||||
return mRunning.get();
|
||||
}
|
||||
@@ -166,28 +213,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
return mSource != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if one of the modules provides frequency error control.
|
||||
*/
|
||||
public boolean hasFrequencyCorrectionControl()
|
||||
{
|
||||
return mFrequencyCorrectionController != null &&
|
||||
mFrequencyCorrectionController.hasFrequencyCorrectionControl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency correction controller. Can be null.
|
||||
*/
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl()
|
||||
{
|
||||
if( mFrequencyCorrectionController != null )
|
||||
{
|
||||
return mFrequencyCorrectionController.getFrequencyCorrectionControl();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a sample source to this processing chain. Processing won't
|
||||
* start until the start() method is invoked.
|
||||
@@ -200,7 +225,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
*/
|
||||
public void setSource( Source source ) throws IllegalStateException
|
||||
{
|
||||
if( processing() )
|
||||
if( isProcessing() )
|
||||
{
|
||||
throw new IllegalStateException( "Processing chain is currently "
|
||||
+ "processing. Invoke stop() on the processing chain before "
|
||||
@@ -208,23 +233,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
}
|
||||
|
||||
mSource = source;
|
||||
|
||||
/* Establish two-way communication between the tuner channel source and
|
||||
* the decoder for fine tuning frequency error correction feedback from
|
||||
* the decoder. The tuner channel source will also notify the frequency
|
||||
* controller during frequency changes to allow the controller to reset
|
||||
* frequency error tracking */
|
||||
if( mSource != null &&
|
||||
mSource instanceof TunerChannelSource &&
|
||||
hasFrequencyCorrectionControl() )
|
||||
{
|
||||
TunerChannelSource channel = (TunerChannelSource)mSource;
|
||||
|
||||
FrequencyCorrectionControl control = getFrequencyCorrectionControl();
|
||||
|
||||
channel.setFrequencyChangeListener( control );
|
||||
control.setFrequencyChangeListener( channel );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,24 +261,45 @@ public class ProcessingChain implements IChannelEventListener
|
||||
return decoderStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the list of modules to this processing chain
|
||||
*/
|
||||
public void addModules( List<Module> modules )
|
||||
{
|
||||
for( Module module: modules )
|
||||
{
|
||||
addModule( module );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a module to the processing chain. Each module is tested for the
|
||||
* interfaces that it supports and is registered or receives a listener
|
||||
* to consume or produce the supported interface data type. All elements
|
||||
* that are produced by any component are automatically routed to all other
|
||||
* components that support the corresponding listener interface.
|
||||
* and events that are produced by any module are automatically routed to
|
||||
* all other components that support the corresponding listener interface.
|
||||
*
|
||||
* At least one module should consume complex samples and either produce
|
||||
* decoded messages and/or audio, or produce decoded real sample buffers
|
||||
* for all other modules to consume.
|
||||
*
|
||||
* @param module - processing module, demodulator or decoder
|
||||
* @param module - processing module, demodulator, decoder, source, state
|
||||
* machine, etc.
|
||||
*/
|
||||
public void addModule( Module module )
|
||||
{
|
||||
mModules.add( module );
|
||||
|
||||
registerListeners( module );
|
||||
registerProviders( module );
|
||||
}
|
||||
|
||||
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Listeners <<<<<<<<<<<<<<<<<<<<<<<<<<< */
|
||||
/**
|
||||
* Registers the module as a listener to each of the broadcasters that
|
||||
* provide the data interface(s) supported by the module.
|
||||
*/
|
||||
private void registerListeners( Module module )
|
||||
{
|
||||
if( module instanceof IAudioPacketListener )
|
||||
{
|
||||
mAudioPacketBroadcaster.addListener(
|
||||
@@ -301,6 +330,12 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((IDecoderStateEventListener)module).getDecoderStateListener() );
|
||||
}
|
||||
|
||||
if( module instanceof IFrequencyChangeListener )
|
||||
{
|
||||
mFrequencyChangeEventBroadcaster.addListener(
|
||||
((IFrequencyChangeListener)module).getFrequencyChangeListener());
|
||||
}
|
||||
|
||||
if( module instanceof IMessageListener )
|
||||
{
|
||||
mMessageBroadcaster.addListener(
|
||||
@@ -313,10 +348,10 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((IMetadataListener)module).getMetadataListener() );
|
||||
}
|
||||
|
||||
if( module instanceof IRealBufferListener )
|
||||
if( module instanceof IFilteredRealBufferListener )
|
||||
{
|
||||
mRealBufferBroadcaster.addListener(
|
||||
((IRealBufferListener)module).getRealBufferListener() );
|
||||
mFilteredRealBufferBroadcaster.addListener(
|
||||
((IFilteredRealBufferListener)module).getFilteredRealBufferListener() );
|
||||
}
|
||||
|
||||
if( module instanceof ISquelchStateListener )
|
||||
@@ -324,8 +359,20 @@ public class ProcessingChain implements IChannelEventListener
|
||||
mSquelchStateBroadcaster.addListener(
|
||||
((ISquelchStateListener)module).getSquelchStateListener() );
|
||||
}
|
||||
|
||||
/* >>>>>>>>>>>>>>>>>>> Providers <<<<<<<<<<<<<<<<<<<<<<<<< */
|
||||
|
||||
if( module instanceof IUnFilteredRealBufferListener )
|
||||
{
|
||||
mUnFilteredRealBufferBroadcaster.addListener(
|
||||
((IUnFilteredRealBufferListener)module).getUnFilteredRealBufferListener() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the broadcaster(s) as listeners to the module for each
|
||||
* provider interface that is supported by the module.
|
||||
*/
|
||||
private void registerProviders( Module module )
|
||||
{
|
||||
if( module instanceof IAudioPacketProvider )
|
||||
{
|
||||
((IAudioPacketProvider)module).setAudioPacketListener(
|
||||
@@ -348,15 +395,16 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((IDecoderStateEventProvider)module).setDecoderStateListener(
|
||||
mDecoderStateEventBroadcaster );
|
||||
}
|
||||
|
||||
if( module instanceof IFrequencyCorrectionController )
|
||||
{
|
||||
mFrequencyCorrectionController = (IFrequencyCorrectionController)module;
|
||||
}
|
||||
|
||||
if( module instanceof IFrequencyChangeProvider )
|
||||
{
|
||||
((IFrequencyChangeProvider)module).setFrequencyChangeListener(
|
||||
mFrequencyChangeEventBroadcaster );
|
||||
}
|
||||
|
||||
if( module instanceof IMessageProvider )
|
||||
{
|
||||
((IMessageProvider)module).addMessageListener( mMessageBroadcaster );
|
||||
((IMessageProvider)module).setMessageListener( mMessageBroadcaster );
|
||||
}
|
||||
|
||||
if( module instanceof IMetadataProvider )
|
||||
@@ -365,9 +413,10 @@ public class ProcessingChain implements IChannelEventListener
|
||||
mMetadataBroadcaster );
|
||||
}
|
||||
|
||||
if( module instanceof IRealBufferProvider )
|
||||
if( module instanceof IFilteredRealBufferProvider )
|
||||
{
|
||||
((IRealBufferProvider)module).setRealBufferListener( mRealBufferBroadcaster );
|
||||
((IFilteredRealBufferProvider)module)
|
||||
.setFilteredRealBufferListener( mFilteredRealBufferBroadcaster );
|
||||
}
|
||||
|
||||
if( module instanceof ISquelchStateProvider )
|
||||
@@ -375,19 +424,13 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((ISquelchStateProvider)module).setSquelchStateListener(
|
||||
mSquelchStateBroadcaster );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the list of modules to this processing chain
|
||||
*/
|
||||
public void addModules( List<Module> modules )
|
||||
{
|
||||
for( Module module: modules )
|
||||
|
||||
if( module instanceof IUnFilteredRealBufferProvider )
|
||||
{
|
||||
addModule( module );
|
||||
((IUnFilteredRealBufferProvider)module)
|
||||
.setUnFilteredRealBufferListener( mUnFilteredRealBufferBroadcaster );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts processing if the chain has a valid source. Invocations on an
|
||||
@@ -405,19 +448,6 @@ public class ProcessingChain implements IChannelEventListener
|
||||
module.reset();
|
||||
}
|
||||
|
||||
/* Start each of the modules */
|
||||
for( Module module: mModules )
|
||||
{
|
||||
try
|
||||
{
|
||||
module.start();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Error starting module", e );
|
||||
}
|
||||
}
|
||||
|
||||
/* Register with the source to receive sample data. Setup a
|
||||
* timer task to process the buffer queues 50 times a second
|
||||
* (every 20 ms) */
|
||||
@@ -427,7 +457,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
((ComplexSource)mSource).setListener( mComplexBufferBroadcaster );
|
||||
break;
|
||||
case REAL:
|
||||
((RealSource)mSource).setListener( mRealBufferBroadcaster );
|
||||
((RealSource)mSource).setListener( mFilteredRealBufferBroadcaster );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized source "
|
||||
@@ -435,15 +465,15 @@ public class ProcessingChain implements IChannelEventListener
|
||||
}
|
||||
|
||||
/* If this is a tuner source, broadcast the frequency to all
|
||||
* of the decoder state's */
|
||||
* of the decoder state's and start the samples flowing */
|
||||
if( mSource instanceof TunerChannelSource )
|
||||
{
|
||||
TunerChannelSource tunerChannelSource = (TunerChannelSource)mSource;
|
||||
|
||||
TunerChannelSource tcs = (TunerChannelSource)mSource;
|
||||
|
||||
try
|
||||
{
|
||||
long frequency = tunerChannelSource.getFrequency();
|
||||
|
||||
long frequency = tcs.getFrequency();
|
||||
|
||||
mDecoderStateEventBroadcaster.broadcast(
|
||||
new DecoderStateEvent( this, Event.SOURCE_FREQUENCY,
|
||||
State.IDLE, frequency ) );
|
||||
@@ -452,13 +482,32 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
mLog.error( "Error getting frequency from tuner channel source", e );
|
||||
}
|
||||
|
||||
tunerChannelSource.start( mScheduledExecutorService );
|
||||
}
|
||||
|
||||
if( mScheduledExecutorService == null )
|
||||
{
|
||||
mScheduledExecutorService = Executors.newScheduledThreadPool(
|
||||
1, new NamingThreadFactory( "channel " + mName ) );
|
||||
}
|
||||
|
||||
/* Start each of the modules */
|
||||
for( Module module: mModules )
|
||||
{
|
||||
try
|
||||
{
|
||||
module.start( mScheduledExecutorService );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Error starting module", e );
|
||||
}
|
||||
}
|
||||
|
||||
mSource.start( mScheduledExecutorService );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.debug( "Source is null on start()" );
|
||||
mLog.error( "Source is null on start()" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -473,13 +522,15 @@ public class ProcessingChain implements IChannelEventListener
|
||||
{
|
||||
if( mSource != null )
|
||||
{
|
||||
mSource.stop();
|
||||
|
||||
switch( mSource.getSampleType() )
|
||||
{
|
||||
case COMPLEX:
|
||||
((ComplexSource)mSource).removeListener( mComplexBufferBroadcaster );
|
||||
break;
|
||||
case REAL:
|
||||
((RealSource)mSource).removeListener( mRealBufferBroadcaster );
|
||||
((RealSource)mSource).removeListener( mFilteredRealBufferBroadcaster );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized source "
|
||||
@@ -595,12 +646,12 @@ public class ProcessingChain implements IChannelEventListener
|
||||
|
||||
public void addRealBufferListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mRealBufferBroadcaster.addListener( listener );
|
||||
mFilteredRealBufferBroadcaster.addListener( listener );
|
||||
}
|
||||
|
||||
public void removeRealBufferListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mRealBufferBroadcaster.removeListener( listener );
|
||||
mFilteredRealBufferBroadcaster.removeListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import module.decode.config.AuxDecodeConfiguration;
|
||||
import controller.channel.AbstractChannelEditor;
|
||||
import controller.channel.ChannelNode;
|
||||
|
||||
public class AuxDecodeComponentEditor extends AbstractChannelEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HashMap<DecoderType,AuxDecoderCheckBox> mControls =
|
||||
new HashMap<DecoderType,AuxDecoderCheckBox>();
|
||||
|
||||
public AuxDecodeComponentEditor( ChannelNode channelNode )
|
||||
{
|
||||
super( channelNode );
|
||||
|
||||
List<DecoderType> decoders = DecoderType.getAuxDecoders();
|
||||
|
||||
Collections.sort( decoders );
|
||||
|
||||
for( DecoderType decoder: decoders )
|
||||
{
|
||||
AuxDecoderCheckBox control = new AuxDecoderCheckBox( decoder );
|
||||
|
||||
if( getConfig().getAuxDecoders().contains( decoder ) )
|
||||
{
|
||||
control.setSelected( true );
|
||||
}
|
||||
|
||||
add( control, "wrap" );
|
||||
|
||||
mControls.put( decoder, control );
|
||||
}
|
||||
}
|
||||
|
||||
public AuxDecodeConfiguration getConfig()
|
||||
{
|
||||
return getChannelNode().getChannel().getAuxDecodeConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
getConfig().clearAuxDecoders();
|
||||
|
||||
for( DecoderType decoder: mControls.keySet() )
|
||||
{
|
||||
if( mControls.get( decoder ) .isSelected() )
|
||||
{
|
||||
getConfig().addAuxDecoder( decoder );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
for( DecoderType decoder: mControls.keySet() )
|
||||
{
|
||||
mControls.get( decoder ).setSelected(
|
||||
getConfig().getAuxDecoders().contains( decoder ) );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class AuxDecoderCheckBox extends JCheckBox
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private DecoderType mDecoderType;
|
||||
|
||||
public AuxDecoderCheckBox( DecoderType decoder )
|
||||
{
|
||||
super( decoder.getDisplayString() );
|
||||
|
||||
mDecoderType = decoder;
|
||||
}
|
||||
}
|
||||
}
|
||||
153
src/module/decode/AuxDecodeConfigurationEditor.java
Normal file
153
src/module/decode/AuxDecodeConfigurationEditor.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode;
|
||||
|
||||
import gui.editor.Editor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import module.decode.config.AuxDecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class AuxDecodeConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private List<AuxDecoderCheckBox> mControls = new ArrayList<>();
|
||||
|
||||
public AuxDecodeConfigurationEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
public AuxDecodeConfiguration getConfiguration()
|
||||
{
|
||||
return hasItem() ? getItem().getAuxDecodeConfiguration() : null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "", "[][grow]" ) );
|
||||
|
||||
List<DecoderType> decoders = DecoderType.getAuxDecoders();
|
||||
|
||||
Collections.sort( decoders );
|
||||
|
||||
for( DecoderType decoder: decoders )
|
||||
{
|
||||
AuxDecoderCheckBox control = new AuxDecoderCheckBox( decoder );
|
||||
control.setEnabled( false );
|
||||
control.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( control );
|
||||
mControls.add( control );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
AuxDecodeConfiguration config = getItem().getAuxDecodeConfiguration();
|
||||
|
||||
config.clearAuxDecoders();
|
||||
|
||||
for( AuxDecoderCheckBox checkBox: mControls )
|
||||
{
|
||||
if( checkBox.isSelected() )
|
||||
{
|
||||
config.addAuxDecoder( checkBox.getDecoderType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
for( AuxDecoderCheckBox box: mControls )
|
||||
{
|
||||
if( box.isEnabled() != enabled )
|
||||
{
|
||||
box.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AuxDecoderCheckBox extends JCheckBox
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private DecoderType mDecoderType;
|
||||
|
||||
public AuxDecoderCheckBox( DecoderType decoder )
|
||||
{
|
||||
super( decoder.getDisplayString() );
|
||||
|
||||
mDecoderType = decoder;
|
||||
}
|
||||
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return mDecoderType;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel channel )
|
||||
{
|
||||
super.setItem( channel );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
for( AuxDecoderCheckBox cb: mControls )
|
||||
{
|
||||
if( getItem().getAuxDecodeConfiguration().getAuxDecoders().contains( cb.getDecoderType() ) )
|
||||
{
|
||||
cb.setSelected( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
cb.setSelected( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode;
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import module.decode.config.DecodeConfigFactory;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import playlist.PlaylistManager;
|
||||
import controller.Editor;
|
||||
import controller.channel.AbstractChannelEditor;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelNode;
|
||||
import controller.channel.ChannelValidationException;
|
||||
|
||||
public class DecodeComponentEditor extends AbstractChannelEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<DecoderType> mComboDecoders;
|
||||
|
||||
private DecodeEditor mEditor;
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
|
||||
public DecodeComponentEditor( PlaylistManager playlistManager )
|
||||
{
|
||||
this( new ChannelNode( new Channel() ), playlistManager );
|
||||
}
|
||||
|
||||
public DecodeComponentEditor( ChannelNode channelNode,
|
||||
PlaylistManager playlistMangager )
|
||||
{
|
||||
super( channelNode );
|
||||
|
||||
mPlaylistManager = playlistMangager;
|
||||
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][grow]" ) );
|
||||
|
||||
/**
|
||||
* ComboBox: Decoders
|
||||
*/
|
||||
mComboDecoders = new JComboBox<DecoderType>();
|
||||
|
||||
DefaultComboBoxModel<DecoderType> model =
|
||||
new DefaultComboBoxModel<DecoderType>();
|
||||
|
||||
for( DecoderType type: DecoderType.getPrimaryDecoders() )
|
||||
{
|
||||
model.addElement( type );
|
||||
}
|
||||
|
||||
mComboDecoders.setModel( model );
|
||||
|
||||
mComboDecoders.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
DecoderType selected = mComboDecoders
|
||||
.getItemAt( mComboDecoders.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
DecodeConfiguration config;
|
||||
|
||||
if( mChannelNode.getChannel()
|
||||
.getDecodeConfiguration().getDecoderType() ==
|
||||
selected )
|
||||
{
|
||||
config = mChannelNode.getChannel()
|
||||
.getDecodeConfiguration();
|
||||
}
|
||||
else
|
||||
{
|
||||
config = DecodeConfigFactory
|
||||
.getDecodeConfiguration( selected );
|
||||
}
|
||||
|
||||
//Remove the existing one
|
||||
if( mEditor != null )
|
||||
{
|
||||
remove( mEditor );
|
||||
}
|
||||
|
||||
//Change to the new one
|
||||
mEditor = DecoderFactory.getEditorPanel( config,
|
||||
mChannelNode, mPlaylistManager );
|
||||
|
||||
add( mEditor, "span 2,center" );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
add( new JLabel( "Decoder:" ) );
|
||||
add( mComboDecoders, "wrap" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
final DecoderType decoder = mChannelNode.getChannel()
|
||||
.getDecodeConfiguration().getDecoderType();
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
mComboDecoders.setSelectedItem( decoder );
|
||||
|
||||
mComboDecoders.requestFocus();
|
||||
|
||||
mComboDecoders.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DecodeConfiguration getDecodeConfig()
|
||||
{
|
||||
return mEditor.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( mEditor != null )
|
||||
{
|
||||
mEditor.save();
|
||||
}
|
||||
|
||||
//The component that calls save will invoke the change broadcast
|
||||
mChannelNode.getChannel()
|
||||
.setDecodeConfiguration( mEditor.getConfig(), false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the editor against the current decode editor
|
||||
*/
|
||||
@Override
|
||||
public void validate( Editor editor ) throws ChannelValidationException
|
||||
{
|
||||
super.validate( editor );
|
||||
|
||||
mEditor.validate( editor );
|
||||
}
|
||||
}
|
||||
137
src/module/decode/DecodeConfigurationEditor.java
Normal file
137
src/module/decode/DecodeConfigurationEditor.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.EmptyValidatingEditor;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
|
||||
public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<DecoderType> mComboDecoders;
|
||||
private ValidatingEditor<Channel> mCurrentEditor = new EmptyValidatingEditor<>( "a decoder" );
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
|
||||
public DecodeConfigurationEditor( final ChannelMapModel channelMapModel )
|
||||
{
|
||||
mChannelMapModel = channelMapModel;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow,fill]" ) );
|
||||
|
||||
mComboDecoders = new JComboBox<DecoderType>();
|
||||
mComboDecoders.setEnabled( false );
|
||||
|
||||
DefaultComboBoxModel<DecoderType> model = new DefaultComboBoxModel<DecoderType>();
|
||||
|
||||
for( DecoderType type: DecoderType.getPrimaryDecoders() )
|
||||
{
|
||||
model.addElement( type );
|
||||
}
|
||||
|
||||
mComboDecoders.setModel( model );
|
||||
mComboDecoders.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
DecoderType selected = mComboDecoders.getItemAt( mComboDecoders.getSelectedIndex() );
|
||||
ValidatingEditor<Channel> editor = DecoderFactory.getEditor( selected, mChannelMapModel );
|
||||
setEditor( editor );
|
||||
}
|
||||
});
|
||||
|
||||
add( mComboDecoders );
|
||||
add( mCurrentEditor );
|
||||
}
|
||||
|
||||
private void setEditor( ValidatingEditor<Channel> editor )
|
||||
{
|
||||
if( mCurrentEditor != editor )
|
||||
{
|
||||
//Set channel to null in current editor to force a save prompt as required
|
||||
if( mCurrentEditor.isModified() )
|
||||
{
|
||||
mCurrentEditor.setItem( null );
|
||||
}
|
||||
|
||||
remove( mCurrentEditor );
|
||||
|
||||
mCurrentEditor = editor;
|
||||
mCurrentEditor.setSaveRequestListener( this );
|
||||
mCurrentEditor.setItem( getItem() );
|
||||
|
||||
add( mCurrentEditor );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
mCurrentEditor.save();
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel channel )
|
||||
{
|
||||
super.setItem( channel );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mComboDecoders.setEnabled( true );
|
||||
mComboDecoders.setSelectedItem( channel.getDecodeConfiguration().getDecoderType() );
|
||||
mCurrentEditor.setItem( channel );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboDecoders.setEnabled( false );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
mCurrentEditor.validate( editor );
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.Editor;
|
||||
|
||||
public class DecodeEditor extends Editor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected DecodeConfiguration mConfig;
|
||||
|
||||
protected JCheckBox mAFC;
|
||||
protected JSpinner mAFCMaximumCorrection;
|
||||
|
||||
public DecodeEditor( DecodeConfiguration config )
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][grow]" ) );
|
||||
|
||||
mConfig = config;
|
||||
|
||||
if( config.supportsAFC() )
|
||||
{
|
||||
mAFC = new JCheckBox( "Automatic Frequency Control" );
|
||||
mAFC.setSelected( mConfig.isAFCEnabled() );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
mConfig.setAFC( mAFC.isSelected() );
|
||||
}
|
||||
} );
|
||||
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center "
|
||||
+ "frequency of the channel to correct/compensate for "
|
||||
+ "inaccuracies and frequency drift in the tuner" );
|
||||
|
||||
add( mAFC, "span" );
|
||||
|
||||
int initial = mConfig.getAFCMaximumCorrection();
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( initial, 0, 15000, 1 );
|
||||
|
||||
mAFCMaximumCorrection = new JSpinner( model );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mAFCMaximumCorrection.getEditor();
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mAFCMaximumCorrection.setToolTipText( "Sets the maximum frequency "
|
||||
+ "correction value in hertz, 0 - 15kHz" );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
int value = ((SpinnerNumberModel)mAFCMaximumCorrection
|
||||
.getModel()).getNumber().intValue();
|
||||
|
||||
mConfig.setAFCMaximumCorrection( value );
|
||||
|
||||
save();
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Correction Limit Hz:" ) );
|
||||
add( mAFCMaximumCorrection, "wrap" );
|
||||
}
|
||||
}
|
||||
|
||||
public DecodeConfiguration getConfig()
|
||||
{
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* 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
|
||||
@@ -20,13 +20,13 @@ package module.decode;
|
||||
import message.IMessageProvider;
|
||||
import message.Message;
|
||||
import module.Module;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
|
||||
public abstract class Decoder extends Module implements IMessageProvider
|
||||
public abstract class Decoder extends Module
|
||||
implements IMessageProvider, Listener<Message>
|
||||
{
|
||||
/* This has to be a broadcaster in order for references to persist */
|
||||
protected Broadcaster<Message> mMessageBroadcaster = new Broadcaster<>();
|
||||
protected Listener<Message> mMessageListener;
|
||||
|
||||
/**
|
||||
* Decoder - parent class for all decoders, demodulators and components.
|
||||
@@ -38,8 +38,7 @@ public abstract class Decoder extends Module implements IMessageProvider
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
mMessageBroadcaster.dispose();
|
||||
mMessageBroadcaster = null;
|
||||
mMessageListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,9 +51,9 @@ public abstract class Decoder extends Module implements IMessageProvider
|
||||
* Adds a listener for receiving decoded messages from this decoder
|
||||
*/
|
||||
@Override
|
||||
public void addMessageListener( Listener<Message> listener )
|
||||
public void setMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mMessageBroadcaster.addListener( listener );
|
||||
mMessageListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,8 +61,25 @@ public abstract class Decoder extends Module implements IMessageProvider
|
||||
* decoders
|
||||
*/
|
||||
@Override
|
||||
public void removeMessageListener( Listener<Message> listener )
|
||||
public void removeMessageListener()
|
||||
{
|
||||
mMessageBroadcaster.removeListener( listener );
|
||||
mMessageListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the message to the registered message listener
|
||||
*/
|
||||
public void broadcast( Message message )
|
||||
{
|
||||
if( mMessageListener != null )
|
||||
{
|
||||
mMessageListener.receive( message );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
broadcast( message );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* 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
|
||||
@@ -25,7 +25,9 @@ import message.Message;
|
||||
import message.MessageDirection;
|
||||
import module.Module;
|
||||
import module.decode.am.AMDecoder;
|
||||
import module.decode.am.AMDecoderEditor;
|
||||
import module.decode.am.AMDecoderPanel;
|
||||
import module.decode.am.DecodeConfigAM;
|
||||
import module.decode.config.AuxDecodeConfiguration;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.fleetsync2.Fleetsync2Decoder;
|
||||
@@ -38,43 +40,45 @@ import module.decode.lj1200.LJ1200DecoderState;
|
||||
import module.decode.lj1200.LJ1200MessageFilter;
|
||||
import module.decode.ltrnet.DecodeConfigLTRNet;
|
||||
import module.decode.ltrnet.LTRNetDecoder;
|
||||
import module.decode.ltrnet.LTRNetDecoderEditor;
|
||||
import module.decode.ltrnet.LTRNetDecoderPanel;
|
||||
import module.decode.ltrnet.LTRNetDecoderState;
|
||||
import module.decode.ltrnet.LTRNetEditor;
|
||||
import module.decode.ltrnet.LTRNetMessageFilter;
|
||||
import module.decode.ltrstandard.DecodeConfigLTRStandard;
|
||||
import module.decode.ltrstandard.LTRStandardDecoder;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderEditor;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderPanel;
|
||||
import module.decode.ltrstandard.LTRStandardDecoderState;
|
||||
import module.decode.ltrstandard.LTRStandardEditor;
|
||||
import module.decode.ltrstandard.LTRStandardMessageFilter;
|
||||
import module.decode.mdc1200.MDCDecoder;
|
||||
import module.decode.mdc1200.MDCDecoderPanel;
|
||||
import module.decode.mdc1200.MDCDecoderState;
|
||||
import module.decode.mdc1200.MDCMessageFilter;
|
||||
import module.decode.mpt1327.DecodeConfigMPT1327;
|
||||
import module.decode.mpt1327.MPT1327ConfigEditor;
|
||||
import module.decode.mpt1327.MPT1327Decoder;
|
||||
import module.decode.mpt1327.MPT1327Decoder.Sync;
|
||||
import module.decode.mpt1327.MPT1327DecoderEditor;
|
||||
import module.decode.mpt1327.MPT1327DecoderPanel;
|
||||
import module.decode.mpt1327.MPT1327DecoderState;
|
||||
import module.decode.mpt1327.MPT1327MessageFilter;
|
||||
import module.decode.nbfm.DecodeConfigNBFM;
|
||||
import module.decode.nbfm.NBFMDecoder;
|
||||
import module.decode.nbfm.NBFMDecoderEditor;
|
||||
import module.decode.nbfm.NBFMDecoderPanel;
|
||||
import module.decode.nbfm.NBFMEditor;
|
||||
import module.decode.p25.DecodeConfigP25Phase1;
|
||||
import module.decode.p25.P25Decoder.Modulation;
|
||||
import module.decode.p25.P25DecoderEditor;
|
||||
import module.decode.p25.P25DecoderPanel;
|
||||
import module.decode.p25.P25DecoderState;
|
||||
import module.decode.p25.P25DecodeEditor;
|
||||
import module.decode.p25.P25_C4FMDecoder;
|
||||
import module.decode.p25.P25_LSMDecoder;
|
||||
import module.decode.p25.audio.P25AudioModule;
|
||||
import module.decode.p25.message.filter.P25MessageFilterSet;
|
||||
import module.decode.passport.DecodeConfigPassport;
|
||||
import module.decode.passport.PassportDecoder;
|
||||
import module.decode.passport.PassportDecoderEditor;
|
||||
import module.decode.passport.PassportDecoderPanel;
|
||||
import module.decode.passport.PassportDecoderState;
|
||||
import module.decode.passport.PassportEditor;
|
||||
import module.decode.passport.PassportMessageFilter;
|
||||
import module.decode.state.AlwaysUnsquelchedDecoderState;
|
||||
import module.decode.state.DecoderPanel;
|
||||
@@ -84,33 +88,30 @@ import module.decode.tait.Tait1200Decoder;
|
||||
import module.decode.tait.Tait1200DecoderPanel;
|
||||
import module.decode.tait.Tait1200DecoderState;
|
||||
import module.demodulate.am.AMDemodulatorModule;
|
||||
import module.demodulate.audio.DemodulatedAudioFilterModule;
|
||||
import module.demodulate.fm.FMDemodulatorModule;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import playlist.PlaylistManager;
|
||||
import properties.SystemProperties;
|
||||
import record.RecorderType;
|
||||
import record.config.RecordConfiguration;
|
||||
import settings.SettingsManager;
|
||||
import util.TimeStamp;
|
||||
import alias.AliasList;
|
||||
import alias.AliasModel;
|
||||
import audio.AudioModule;
|
||||
import controller.ResourceManager;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ChannelNode;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.map.ChannelMap;
|
||||
import controller.site.Site;
|
||||
import controller.system.System;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
import filter.AllPassFilter;
|
||||
import filter.FilterSet;
|
||||
import filter.IFilter;
|
||||
import gui.editor.EmptyValidatingEditor;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
public class DecoderFactory
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( DecoderFactory.class );
|
||||
|
||||
public static final boolean NO_REMOVE_DC = false;
|
||||
public static final boolean REMOVE_DC = true;
|
||||
|
||||
@@ -120,72 +121,46 @@ public class DecoderFactory
|
||||
* Returns a list of one primary decoder and any auxiliary decoders, as
|
||||
* specified in the configurations.
|
||||
*
|
||||
* @param channelType - standard or traffic channel type
|
||||
* @param resourceManager
|
||||
* @param decodeConfig - primary decoder configuration
|
||||
* @param recordConfig - recording configuration used by traffic channel manager
|
||||
* @param auxConfig - auxiliary decoder(s) configuration
|
||||
* @param optional alias list - (null is ok)
|
||||
*
|
||||
* @return list of configured decoders
|
||||
*/
|
||||
public static List<Module> getModules( ChannelType channelType,
|
||||
ResourceManager resourceManager,
|
||||
DecodeConfiguration decodeConfig,
|
||||
RecordConfiguration recordConfig,
|
||||
AuxDecodeConfiguration auxConfig,
|
||||
AliasList aliasList,
|
||||
System system,
|
||||
Site site,
|
||||
String channelName )
|
||||
public static List<Module> getModules( ChannelModel channelModel,
|
||||
ChannelMapModel channelMapModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
AliasModel aliasModel,
|
||||
Channel channel )
|
||||
{
|
||||
List<Module> modules = getPrimaryModules( channelType, decodeConfig,
|
||||
recordConfig, aliasList, system, site, channelName, resourceManager );
|
||||
|
||||
modules.addAll( getAuxiliaryDecoders( auxConfig, aliasList ) );
|
||||
/* Get the optional alias list for the decode modules to use */
|
||||
AliasList aliasList = aliasModel.getAliasList( channel.getAliasListName() );
|
||||
|
||||
List<Module> modules = getPrimaryModules( channelModel, channelMapModel,
|
||||
channelProcessingManager, aliasList, channel );
|
||||
|
||||
modules.addAll( getAuxiliaryDecoders( channel.getAuxDecodeConfiguration(), aliasList ) );
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
public static FMDemodulatorModule getFMDemodulator(
|
||||
DecodeConfiguration config, int pass, int stop, boolean removeDC )
|
||||
{
|
||||
if( config.isAFCEnabled() )
|
||||
{
|
||||
return new FMDemodulatorModule( pass, stop,
|
||||
config.getAFCMaximumCorrection(), removeDC );
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FMDemodulatorModule( pass, stop,
|
||||
NO_FREQUENCY_CORRECTION, removeDC );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a primary decoder as specified in the decode configuration
|
||||
*
|
||||
* @param channelType - traffic or standard decode channel
|
||||
* @param decodeConfig - primary decoder configuration
|
||||
* @param recordConfig - recording options
|
||||
* @param aliasList - optional alias list
|
||||
* @param resourceManager - shared resource manager
|
||||
* @return configured decoder or null
|
||||
*/
|
||||
public static List<Module> getPrimaryModules( ChannelType channelType,
|
||||
DecodeConfiguration decodeConfig,
|
||||
RecordConfiguration recordConfig,
|
||||
public static List<Module> getPrimaryModules( ChannelModel channelModel,
|
||||
ChannelMapModel channelMapModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
AliasList aliasList,
|
||||
System system,
|
||||
Site site,
|
||||
String channelName,
|
||||
ResourceManager resourceManager )
|
||||
Channel channel )
|
||||
{
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
|
||||
ChannelType channelType = channel.getChannelType();
|
||||
|
||||
/* Baseband low-pass filter pass and stop frequencies */
|
||||
int pass = decodeConfig.getDecoderType().getChannelBandwidth() / 2;
|
||||
int stop = pass + 1250;
|
||||
DecodeConfiguration decodeConfig = channel.getDecodeConfiguration();
|
||||
|
||||
int iqPass = decodeConfig.getDecoderType().getChannelBandwidth() / 2;
|
||||
int iqStop = iqPass + 1250;
|
||||
|
||||
RecordConfiguration recordConfig = channel.getRecordConfiguration();
|
||||
|
||||
boolean recordAudio = recordConfig == null ? false :
|
||||
recordConfig.getRecorders().contains( RecorderType.AUDIO );
|
||||
@@ -193,41 +168,45 @@ public class DecoderFactory
|
||||
switch( decodeConfig.getDecoderType() )
|
||||
{
|
||||
case AM:
|
||||
modules.add( new AMDemodulatorModule() );
|
||||
modules.add( new AMDecoder( decodeConfig ) );
|
||||
modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.AM, channelName ) );
|
||||
modules.add( new AudioModule( recordAudio, REMOVE_DC ) );
|
||||
modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.AM, channel.getName() ) );
|
||||
modules.add( new AMDemodulatorModule() );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case NBFM:
|
||||
modules.add( new AudioModule( recordAudio, NO_REMOVE_DC ) );
|
||||
modules.add( new NBFMDecoder( decodeConfig ) );
|
||||
modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.NBFM, channelName ) );
|
||||
modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) );
|
||||
modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.NBFM, channel.getName() ) );
|
||||
modules.add( new FMDemodulatorModule( iqPass, iqStop ) );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case LTR_STANDARD:
|
||||
modules.add( new AudioModule( recordAudio, REMOVE_DC ) );
|
||||
MessageDirection direction = ((DecodeConfigLTRStandard)decodeConfig).getMessageDirection();
|
||||
modules.add( new LTRStandardDecoder( aliasList, direction ) );
|
||||
modules.add( new LTRStandardDecoderState( aliasList ) );
|
||||
modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) );
|
||||
modules.add( new FMDemodulatorModule( iqPass, iqStop ) );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case LTR_NET:
|
||||
modules.add( new AudioModule( recordAudio, REMOVE_DC ) );
|
||||
modules.add( new LTRNetDecoder( (DecodeConfigLTRNet)decodeConfig, aliasList ) );
|
||||
modules.add( new LTRNetDecoderState( aliasList ) );
|
||||
modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) );
|
||||
modules.add( new FMDemodulatorModule( iqPass, iqStop ) );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case MPT1327:
|
||||
DecodeConfigMPT1327 mptConfig = (DecodeConfigMPT1327)decodeConfig;
|
||||
|
||||
modules.add( new AudioModule( recordAudio, NO_REMOVE_DC ) );
|
||||
|
||||
ChannelMap channelMap = resourceManager.getPlaylistManager().getPlayist()
|
||||
.getChannelMapList().getChannelMap( mptConfig.getChannelMapName() );
|
||||
ChannelMap channelMap = channelMapModel
|
||||
.getChannelMap( mptConfig.getChannelMapName() );
|
||||
|
||||
Sync sync = mptConfig.getSync();
|
||||
|
||||
modules.add( new MPT1327Decoder( aliasList, sync ) );
|
||||
|
||||
|
||||
modules.add( new MPT1327DecoderState( aliasList, channelMap,
|
||||
channelType, mptConfig.getCallTimeout() * 1000 ) );
|
||||
|
||||
@@ -235,30 +214,34 @@ public class DecoderFactory
|
||||
{
|
||||
long timeout = mptConfig.getCallTimeout() * 1000; //convert to milliseconds
|
||||
|
||||
modules.add( new TrafficChannelManager( resourceManager,
|
||||
decodeConfig, recordConfig, system, site,
|
||||
( aliasList != null ? aliasList.getName() : null ), timeout,
|
||||
mptConfig.getTrafficChannelPoolSize() ) );
|
||||
modules.add( new TrafficChannelManager( channelModel, channelProcessingManager,
|
||||
decodeConfig, recordConfig, channel.getSystem(),
|
||||
channel.getSite(), ( aliasList != null ? aliasList.getName() : null ), timeout,
|
||||
mptConfig.getTrafficChannelPoolSize() ) );
|
||||
}
|
||||
|
||||
modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) );
|
||||
modules.add( new FMDemodulatorModule( iqPass, iqStop ) );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case PASSPORT:
|
||||
modules.add( new AudioModule( recordAudio, REMOVE_DC ) );
|
||||
modules.add( new PassportDecoder( decodeConfig, aliasList ) );
|
||||
modules.add( new PassportDecoderState( aliasList ) );
|
||||
modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) );
|
||||
modules.add( new FMDemodulatorModule( iqPass, iqStop ) );
|
||||
modules.add( new DemodulatedAudioFilterModule( 4000, 6000 ));
|
||||
modules.add( new AudioModule( recordAudio ) );
|
||||
break;
|
||||
case P25_PHASE1:
|
||||
DecodeConfigP25Phase1 p25Config = (DecodeConfigP25Phase1)decodeConfig;
|
||||
|
||||
Modulation modulation = p25Config.getModulation();
|
||||
|
||||
|
||||
switch( modulation )
|
||||
{
|
||||
case C4FM:
|
||||
modules.add( getFMDemodulator( decodeConfig, 6750, 7500, NO_REMOVE_DC ) );
|
||||
modules.add( new P25_C4FMDecoder( aliasList ) );
|
||||
modules.add( new FMDemodulatorModule( 6750, 7500 ) );
|
||||
modules.add( new P25_C4FMDecoder( aliasList, decodeConfig.getAFCMaximumCorrection() ) );
|
||||
modules.add( new P25DecoderState( aliasList, channelType,
|
||||
Modulation.C4FM, p25Config.getIgnoreDataCalls() ) );
|
||||
break;
|
||||
@@ -277,8 +260,9 @@ public class DecoderFactory
|
||||
//Set call timeout to 3 seconds for P25 traffic channels
|
||||
long timeout = 3000;
|
||||
|
||||
modules.add( new TrafficChannelManager( resourceManager,
|
||||
decodeConfig, recordConfig, system, site,
|
||||
modules.add( new TrafficChannelManager( channelModel,
|
||||
channelProcessingManager, decodeConfig,
|
||||
recordConfig, channel.getSystem(), channel.getSite(),
|
||||
( aliasList != null ? aliasList.getName() : null ), timeout,
|
||||
p25Config.getTrafficChannelPoolSize() ) );
|
||||
}
|
||||
@@ -447,41 +431,132 @@ public class DecoderFactory
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
public static DecodeEditor getEditorPanel( DecodeConfiguration config,
|
||||
ChannelNode channelNode, PlaylistManager playlistManager )
|
||||
|
||||
public static DecodeConfiguration getDefaultDecodeConfiguration()
|
||||
{
|
||||
DecodeEditor configuredPanel;
|
||||
|
||||
switch( config.getDecoderType() )
|
||||
return getDecodeConfiguration( DecoderType.NBFM );
|
||||
}
|
||||
|
||||
public static DecodeConfiguration getDecodeConfiguration( DecoderType decoder )
|
||||
{
|
||||
DecodeConfiguration retVal;
|
||||
|
||||
switch( decoder )
|
||||
{
|
||||
case NBFM:
|
||||
configuredPanel = new NBFMEditor( config );
|
||||
break;
|
||||
case LTR_STANDARD:
|
||||
configuredPanel = new LTRStandardEditor( config );
|
||||
break;
|
||||
case AM:
|
||||
return new DecodeConfigAM();
|
||||
case LTR_NET:
|
||||
configuredPanel = new LTRNetEditor( config );
|
||||
break;
|
||||
return new DecodeConfigLTRNet();
|
||||
case LTR_STANDARD:
|
||||
return new DecodeConfigLTRStandard();
|
||||
case MPT1327:
|
||||
configuredPanel = new MPT1327ConfigEditor( config,
|
||||
channelNode, playlistManager );
|
||||
break;
|
||||
return new DecodeConfigMPT1327();
|
||||
case NBFM:
|
||||
return new DecodeConfigNBFM();
|
||||
case PASSPORT:
|
||||
configuredPanel = new PassportEditor( config );
|
||||
break;
|
||||
return new DecodeConfigPassport();
|
||||
case P25_PHASE1:
|
||||
configuredPanel = new P25DecodeEditor( config );
|
||||
break;
|
||||
return new DecodeConfigP25Phase1();
|
||||
default:
|
||||
throw new IllegalArgumentException( "DecodeConfigFactory - unknown decoder type ["
|
||||
+ decoder.toString() + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
public static ValidatingEditor<Channel> getEditor( DecoderType type, ChannelMapModel model )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case AM:
|
||||
return new AMDecoderEditor();
|
||||
case LTR_NET:
|
||||
return new LTRNetDecoderEditor();
|
||||
case LTR_STANDARD:
|
||||
return new LTRStandardDecoderEditor();
|
||||
case MPT1327:
|
||||
return new MPT1327DecoderEditor( model );
|
||||
case NBFM:
|
||||
return new NBFMDecoderEditor();
|
||||
case P25_PHASE1:
|
||||
return new P25DecoderEditor();
|
||||
case PASSPORT:
|
||||
return new PassportDecoderEditor();
|
||||
default:
|
||||
configuredPanel = new DecodeEditor( config );
|
||||
break;
|
||||
}
|
||||
|
||||
return configuredPanel;
|
||||
return new EmptyValidatingEditor<Channel>( "a decoder" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a copy of the configuration
|
||||
*/
|
||||
public static DecodeConfiguration copy( DecodeConfiguration config )
|
||||
{
|
||||
if( config != null )
|
||||
{
|
||||
switch( config.getDecoderType() )
|
||||
{
|
||||
case AM:
|
||||
DecodeConfigAM originalAM = (DecodeConfigAM)config;
|
||||
DecodeConfigAM copyAM = new DecodeConfigAM();
|
||||
copyAM.setAFC( originalAM.getAFC() );
|
||||
copyAM.setAFCMaximumCorrection( originalAM.getAFCMaximumCorrection() );
|
||||
return copyAM;
|
||||
case LTR_NET:
|
||||
DecodeConfigLTRNet originalLTRNet = (DecodeConfigLTRNet)config;
|
||||
DecodeConfigLTRNet copyLTRNet = new DecodeConfigLTRNet();
|
||||
copyLTRNet.setAFC( originalLTRNet.getAFC() );
|
||||
copyLTRNet.setAFCMaximumCorrection( originalLTRNet.getAFCMaximumCorrection() );
|
||||
copyLTRNet.setMessageDirection( originalLTRNet.getMessageDirection() );
|
||||
return copyLTRNet;
|
||||
case LTR_STANDARD:
|
||||
DecodeConfigLTRStandard originalLTRStandard = (DecodeConfigLTRStandard)config;
|
||||
DecodeConfigLTRStandard copyLTRStandard = new DecodeConfigLTRStandard();
|
||||
copyLTRStandard.setAFC( originalLTRStandard.getAFC() );
|
||||
copyLTRStandard.setAFCMaximumCorrection( originalLTRStandard.getAFCMaximumCorrection() );
|
||||
copyLTRStandard.setMessageDirection( originalLTRStandard.getMessageDirection() );
|
||||
return copyLTRStandard;
|
||||
case MPT1327:
|
||||
DecodeConfigMPT1327 originalMPT = (DecodeConfigMPT1327)config;
|
||||
DecodeConfigMPT1327 copyMPT = new DecodeConfigMPT1327();
|
||||
copyMPT.setAFC( originalMPT.getAFC() );
|
||||
copyMPT.setAFCMaximumCorrection( originalMPT.getAFCMaximumCorrection() );
|
||||
copyMPT.setCallTimeout( originalMPT.getCallTimeout() );
|
||||
copyMPT.setChannelMapName( originalMPT.getChannelMapName() );
|
||||
copyMPT.setSync( originalMPT.getSync() );
|
||||
copyMPT.setTrafficChannelPoolSize( originalMPT.getTrafficChannelPoolSize() );
|
||||
return copyMPT;
|
||||
case NBFM:
|
||||
DecodeConfigNBFM originalNBFM = (DecodeConfigNBFM)config;
|
||||
DecodeConfigNBFM copyNBFM = new DecodeConfigNBFM();
|
||||
copyNBFM.setAFC( originalNBFM.getAFC() );
|
||||
copyNBFM.setAFCMaximumCorrection( originalNBFM.getAFCMaximumCorrection() );
|
||||
return copyNBFM;
|
||||
case P25_PHASE1:
|
||||
DecodeConfigP25Phase1 originalP25 = (DecodeConfigP25Phase1)config;
|
||||
DecodeConfigP25Phase1 copyP25 = new DecodeConfigP25Phase1();
|
||||
copyP25.setAFC( originalP25.getAFC() );
|
||||
copyP25.setAFCMaximumCorrection( originalP25.getAFCMaximumCorrection() );
|
||||
copyP25.setIgnoreDataCalls( originalP25.getIgnoreDataCalls() );
|
||||
copyP25.setModulation( originalP25.getModulation() );
|
||||
copyP25.setTrafficChannelPoolSize( originalP25.getTrafficChannelPoolSize() );
|
||||
return copyP25;
|
||||
case PASSPORT:
|
||||
DecodeConfigPassport originalPass = (DecodeConfigPassport)config;
|
||||
DecodeConfigPassport copyPass = new DecodeConfigPassport();
|
||||
copyPass.setAFC( originalPass.getAFC() );
|
||||
copyPass.setAFCMaximumCorrection( originalPass.getAFCMaximumCorrection() );
|
||||
return copyPass;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized decoder "
|
||||
+ "configuration type:" + config.getDecoderType() );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getRecordingFilename( String token )
|
||||
{
|
||||
//Get the base recording filename
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
package module.decode.am;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.PrimaryDecoder;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
@@ -41,7 +43,7 @@ public class AMDecoder extends PrimaryDecoder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
76
src/module/decode/am/AMDecoderEditor.java
Normal file
76
src/module/decode/am/AMDecoderEditor.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.am;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class AMDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AMDecoderEditor()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) );
|
||||
add( new JLabel( "AM Decoder" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
if( getItem().getDecodeConfiguration() instanceof DecodeConfigAM )
|
||||
{
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
getItem().setDecodeConfiguration( new DecodeConfigAM() );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.am;
|
||||
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class AMEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AMEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.config;
|
||||
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.am.DecodeConfigAM;
|
||||
import module.decode.ltrnet.DecodeConfigLTRNet;
|
||||
import module.decode.ltrstandard.DecodeConfigLTRStandard;
|
||||
import module.decode.mpt1327.DecodeConfigMPT1327;
|
||||
import module.decode.nbfm.DecodeConfigNBFM;
|
||||
import module.decode.p25.DecodeConfigP25Phase1;
|
||||
import module.decode.passport.DecodeConfigPassport;
|
||||
|
||||
public class DecodeConfigFactory
|
||||
{
|
||||
public static DecodeConfiguration getDefaultDecodeConfiguration()
|
||||
{
|
||||
return getDecodeConfiguration( DecoderType.NBFM );
|
||||
}
|
||||
|
||||
public static DecodeConfiguration
|
||||
getDecodeConfiguration( DecoderType decoder )
|
||||
{
|
||||
DecodeConfiguration retVal;
|
||||
|
||||
switch( decoder )
|
||||
{
|
||||
case AM:
|
||||
retVal = new DecodeConfigAM();
|
||||
break;
|
||||
case NBFM:
|
||||
retVal = new DecodeConfigNBFM();
|
||||
break;
|
||||
case LTR_STANDARD:
|
||||
retVal = new DecodeConfigLTRStandard();
|
||||
break;
|
||||
case LTR_NET:
|
||||
retVal = new DecodeConfigLTRNet();
|
||||
break;
|
||||
case MPT1327:
|
||||
retVal = new DecodeConfigMPT1327();
|
||||
break;
|
||||
case PASSPORT:
|
||||
retVal = new DecodeConfigPassport();
|
||||
break;
|
||||
case P25_PHASE1:
|
||||
retVal = new DecodeConfigP25Phase1();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "DecodeConfigFactory - "
|
||||
+ "unknown decoder type [" + decoder.toString() + "]" );
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
******************************************************************************/
|
||||
package module.decode.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlSeeAlso;
|
||||
|
||||
@@ -48,10 +48,12 @@ public abstract class DecodeConfiguration extends Configuration
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_DEFAULT = 3;
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_MINIMUM = 0;
|
||||
public static final int TRAFFIC_CHANNEL_LIMIT_MAXIMUM = 30;
|
||||
|
||||
public static final int DEFAULT_AFC_MAX_CORRECTION = 1000;
|
||||
|
||||
private DecoderType mDecoderType = DecoderType.NBFM;
|
||||
private boolean mAFCEnabled = true;
|
||||
private int mAFCMaxCorrection = 3000;
|
||||
private int mAFCMaxCorrection = DEFAULT_AFC_MAX_CORRECTION;
|
||||
|
||||
public DecodeConfiguration()
|
||||
{
|
||||
@@ -68,7 +70,7 @@ public abstract class DecodeConfiguration extends Configuration
|
||||
return mDecoderType;
|
||||
}
|
||||
|
||||
@XmlElement( name = "afc" )
|
||||
@XmlAttribute( name = "afc" )
|
||||
public boolean getAFC()
|
||||
{
|
||||
return mAFCEnabled;
|
||||
@@ -84,6 +86,7 @@ public abstract class DecodeConfiguration extends Configuration
|
||||
mAFCEnabled = enabled;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "AFCMaximumCorrection" )
|
||||
public int getAFCMaximumCorrection()
|
||||
{
|
||||
return mAFCMaxCorrection;
|
||||
|
||||
@@ -20,9 +20,6 @@ package module.decode.event;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import settings.SettingsManager;
|
||||
import alias.Alias;
|
||||
|
||||
@@ -35,9 +32,6 @@ public class CallEventAliasCellRenderer extends DefaultTableCellRenderer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory
|
||||
.getLogger( CallEventAliasCellRenderer.class );
|
||||
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
public CallEventAliasCellRenderer( SettingsManager settingsManager )
|
||||
|
||||
@@ -25,20 +25,13 @@ import java.util.List;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
public class CallEventModel extends AbstractTableModel implements Listener<CallEvent>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CallEventModel.class );
|
||||
|
||||
private static DecimalFormat mFrequencyFormatter =
|
||||
new DecimalFormat( "0.000000" );
|
||||
private static DecimalFormat mFrequencyFormatter = new DecimalFormat( "0.000000" );
|
||||
|
||||
public static final int TIME = 0;
|
||||
public static final int EVENT = 1;
|
||||
|
||||
@@ -23,12 +23,14 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import module.ProcessingChain;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import settings.SettingsManager;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
|
||||
public class CallEventPanel extends JPanel implements ChannelEventListener
|
||||
{
|
||||
@@ -37,9 +39,13 @@ public class CallEventPanel extends JPanel implements ChannelEventListener
|
||||
private JScrollPane mEmptyScroller;
|
||||
private Channel mDisplayedChannel;
|
||||
private CallEventAliasCellRenderer mRenderer;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
public CallEventPanel( SettingsManager settingsManager )
|
||||
public CallEventPanel( SettingsManager settingsManager,
|
||||
ChannelProcessingManager channelProcessingManager )
|
||||
{
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
|
||||
setLayout( new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]") );
|
||||
|
||||
JTable table = new JTable( new CallEventModel() );
|
||||
@@ -62,45 +68,54 @@ public class CallEventPanel extends JPanel implements ChannelEventListener
|
||||
@Override
|
||||
public void channelChanged( final ChannelEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.CHANGE_SELECTED &&
|
||||
if( event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel().isSelected() )
|
||||
{
|
||||
if( mDisplayedChannel == null ||
|
||||
( mDisplayedChannel != null &&
|
||||
mDisplayedChannel != event.getChannel() ) )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
removeAll();
|
||||
|
||||
JTable table = new JTable(
|
||||
event.getChannel().getCallEventModel() );
|
||||
|
||||
table.setAutoCreateRowSorter( true );
|
||||
table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
|
||||
|
||||
table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS )
|
||||
.setCellRenderer( mRenderer );
|
||||
|
||||
table.getColumnModel().getColumn( CallEventModel.TO_ALIAS )
|
||||
.setCellRenderer( mRenderer );
|
||||
|
||||
add( new JScrollPane( table ) );
|
||||
|
||||
mDisplayedChannel = event.getChannel();
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
ProcessingChain chain = mChannelProcessingManager
|
||||
.getProcessingChain( event.getChannel() );
|
||||
|
||||
if( chain != null )
|
||||
{
|
||||
final CallEventModel model = chain.getCallEventModel();
|
||||
|
||||
if( model != null )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
removeAll();
|
||||
|
||||
JTable table = new JTable( model );
|
||||
|
||||
table.setAutoCreateRowSorter( true );
|
||||
table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
|
||||
|
||||
table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS )
|
||||
.setCellRenderer( mRenderer );
|
||||
|
||||
table.getColumnModel().getColumn( CallEventModel.TO_ALIAS )
|
||||
.setCellRenderer( mRenderer );
|
||||
|
||||
add( new JScrollPane( table ) );
|
||||
|
||||
mDisplayedChannel = event.getChannel();
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( event.getEvent() == Event.CHANNEL_PROCESSING_STOPPED ||
|
||||
event.getEvent() == Event.CHANNEL_DISABLED )
|
||||
else if( event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP ||
|
||||
event.getEvent() == Event.REQUEST_DISABLE )
|
||||
{
|
||||
if( mDisplayedChannel != null &&
|
||||
mDisplayedChannel == event.getChannel() )
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* 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
|
||||
@@ -32,11 +32,11 @@ public class MessageActivityModel extends AbstractTableModel
|
||||
implements Listener<Message>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final int sTIME = 0;
|
||||
private static final int sPROTOCOL = 1;
|
||||
private static final int sERROR_STATUS = 2;
|
||||
private static final int sMESSAGE = 3;
|
||||
private static final int sMESSAGE_BITS = 4;
|
||||
private static final int TIME = 0;
|
||||
private static final int PROTOCOL = 1;
|
||||
private static final int ERROR_STATUS = 2;
|
||||
private static final int MESSAGE = 3;
|
||||
private static final int MESSAGE_BITS = 4;
|
||||
|
||||
protected int mMaxMessages = 500;
|
||||
protected LinkedList<Message> mMessages = new LinkedList<Message>();
|
||||
@@ -174,18 +174,18 @@ public class MessageActivityModel extends AbstractTableModel
|
||||
|
||||
switch( columnIndex )
|
||||
{
|
||||
case sTIME:
|
||||
case TIME:
|
||||
return mSDFTime.format( new Date( message.getTimeReceived() ) );
|
||||
case sPROTOCOL:
|
||||
case PROTOCOL:
|
||||
return message.getProtocol();
|
||||
case sERROR_STATUS:
|
||||
case ERROR_STATUS:
|
||||
return message.getErrorStatus();
|
||||
case sMESSAGE:
|
||||
case MESSAGE:
|
||||
return message.getMessage();
|
||||
case sMESSAGE_BITS:
|
||||
case MESSAGE_BITS:
|
||||
return message.getBinaryMessage();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* 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
|
||||
@@ -36,6 +36,7 @@ import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import message.Message;
|
||||
import module.ProcessingChain;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -48,6 +49,7 @@ import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import filter.FilterEditorPanel;
|
||||
import filter.FilterSet;
|
||||
|
||||
@@ -63,16 +65,21 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
private JTable mMessageTable;
|
||||
|
||||
private Channel mDisplayedChannel;
|
||||
private MessageActivityModel mDisplayedModel = EMPTY_MODEL;
|
||||
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
public MessageActivityPanel()
|
||||
public MessageActivityPanel( ChannelProcessingManager channelProcessingManager )
|
||||
{
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
|
||||
setLayout( new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]") );
|
||||
|
||||
add( mManagementPanel, "span,growx" );
|
||||
|
||||
mMessageTable = new JTable( EMPTY_MODEL );
|
||||
mMessageTable = new JTable( mDisplayedModel );
|
||||
|
||||
add( new JScrollPane( mMessageTable ), "span,grow" );
|
||||
}
|
||||
@@ -82,7 +89,7 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
if( event.getEvent() == Event.CHANGE_SELECTED &&
|
||||
if( event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel().isSelected() )
|
||||
{
|
||||
if( mDisplayedChannel == null ||
|
||||
@@ -91,7 +98,19 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
{
|
||||
mDisplayedChannel = event.getChannel();
|
||||
|
||||
mMessageTable.setModel( event.getChannel().getMessageActivityModel() );
|
||||
ProcessingChain chain = mChannelProcessingManager
|
||||
.getProcessingChain( mDisplayedChannel );
|
||||
|
||||
if( chain != null )
|
||||
{
|
||||
mDisplayedModel = chain.getMessageActivityModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDisplayedModel = EMPTY_MODEL;
|
||||
}
|
||||
|
||||
mMessageTable.setModel( mDisplayedModel );
|
||||
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
@@ -105,8 +124,8 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if( event.getEvent() == Event.CHANNEL_PROCESSING_STOPPED ||
|
||||
event.getEvent() == Event.CHANNEL_DISABLED )
|
||||
else if( event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP ||
|
||||
event.getEvent() == Event.REQUEST_DISABLE )
|
||||
{
|
||||
if( mDisplayedChannel != null &&
|
||||
mDisplayedChannel == event.getChannel() )
|
||||
@@ -195,10 +214,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
public void mouseReleased( MouseEvent arg0 ) {}
|
||||
} );
|
||||
|
||||
if( mDisplayedChannel != null )
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
slider.setValue( mDisplayedChannel.getMessageActivityModel()
|
||||
.getMaxMessageCount() );
|
||||
slider.setValue( mDisplayedModel.getMaxMessageCount() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -210,10 +228,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent arg0 )
|
||||
{
|
||||
if( mDisplayedChannel != null )
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
mDisplayedChannel.getMessageActivityModel()
|
||||
.setMaxMessageCount( slider.getValue() );
|
||||
mDisplayedModel.setMaxMessageCount( slider.getValue() );
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -228,9 +245,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
if( mDisplayedChannel != null )
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
mDisplayedChannel.getMessageActivityModel().clear();
|
||||
mDisplayedModel.clear();
|
||||
}
|
||||
}
|
||||
} );
|
||||
@@ -258,50 +275,52 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
}
|
||||
else
|
||||
{
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
editor.setTitle( "Message Filter Editor" );
|
||||
editor.setSize( 600, 400 );
|
||||
editor.setLocationRelativeTo( MessageFilterButton.this );
|
||||
editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
editor.setLayout( new MigLayout( "", "[grow,fill]",
|
||||
"[grow,fill][][]" ) );
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
FilterSet<Message> filter = (FilterSet<Message>)
|
||||
mDisplayedChannel.getMessageActivityModel()
|
||||
.getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel =
|
||||
new FilterEditorPanel<Message>( filter );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( panel );
|
||||
scroller.setViewportView( panel );
|
||||
|
||||
editor.add( scroller, "wrap" );
|
||||
|
||||
editor.add( new JLabel( "Right-click to select/deselect "
|
||||
+ "all nodes" ), "wrap" );
|
||||
|
||||
JButton close = new JButton( "Close" );
|
||||
close.addActionListener( new ActionListener()
|
||||
if( mDisplayedModel != null )
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
} );
|
||||
|
||||
editor.add( close );
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
editor.setTitle( "Message Filter Editor" );
|
||||
editor.setSize( 600, 400 );
|
||||
editor.setLocationRelativeTo( MessageFilterButton.this );
|
||||
editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
editor.setLayout( new MigLayout( "", "[grow,fill]",
|
||||
"[grow,fill][][]" ) );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible( true );
|
||||
}
|
||||
} );
|
||||
@SuppressWarnings( "unchecked" )
|
||||
FilterSet<Message> filter = (FilterSet<Message>)
|
||||
mDisplayedModel.getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel =
|
||||
new FilterEditorPanel<Message>( filter );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( panel );
|
||||
scroller.setViewportView( panel );
|
||||
|
||||
editor.add( scroller, "wrap" );
|
||||
|
||||
editor.add( new JLabel( "Right-click to select/deselect "
|
||||
+ "all nodes" ), "wrap" );
|
||||
|
||||
JButton close = new JButton( "Close" );
|
||||
close.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
} );
|
||||
|
||||
editor.add( close );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
@@ -25,11 +25,12 @@ import instrument.tap.stream.FloatBufferTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
@@ -44,7 +45,7 @@ import dsp.fsk.FSK2Decoder.Output;
|
||||
* Fleetsync II Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
|
||||
* floating point samples and output fully framed Fleetsync II messages
|
||||
*/
|
||||
public class Fleetsync2Decoder extends Decoder implements IRealBufferListener,
|
||||
public class Fleetsync2Decoder extends Decoder implements IFilteredRealBufferListener,
|
||||
Instrumentable
|
||||
{
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
@@ -90,7 +91,7 @@ public class Fleetsync2Decoder extends Decoder implements IRealBufferListener,
|
||||
mMessageProcessor = new Fleetsync2MessageProcessor( aliasList );
|
||||
mMessageFramer.addMessageListener( mMessageProcessor );
|
||||
|
||||
mMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -169,7 +170,7 @@ public class Fleetsync2Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
@@ -180,7 +181,7 @@ public class Fleetsync2Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package module.decode.fleetsync2;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -58,7 +59,7 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,13 @@ import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import sample.real.RealSampleListener;
|
||||
import alias.AliasList;
|
||||
@@ -46,7 +47,7 @@ import dsp.fsk.FSK2Decoder.Output;
|
||||
/**
|
||||
* LJ1200 - 1200 baud 2FSK decoder
|
||||
*/
|
||||
public class LJ1200Decoder extends Decoder implements IRealBufferListener,
|
||||
public class LJ1200Decoder extends Decoder implements IFilteredRealBufferListener,
|
||||
Instrumentable
|
||||
{
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
@@ -100,7 +101,7 @@ public class LJ1200Decoder extends Decoder implements IRealBufferListener,
|
||||
mMessageProcessor = new LJ1200MessageProcessor( aliasList );
|
||||
mTowerMessageFramer.addMessageListener( mMessageProcessor );
|
||||
mTransponderMessageFramer.addMessageListener( mMessageProcessor );
|
||||
mMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,7 +188,7 @@ public class LJ1200Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
@@ -198,7 +199,7 @@ public class LJ1200Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -22,18 +22,19 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.p25.P25DecoderState;
|
||||
import module.decode.state.ChangedAttribute;
|
||||
import module.decode.state.DecoderState;
|
||||
import module.decode.state.DecoderStateEvent;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
import module.decode.state.State;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
|
||||
@@ -58,7 +59,7 @@ public class LJ1200DecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -51,16 +51,22 @@ public class LTRCallEvent extends CallEvent
|
||||
*/
|
||||
public boolean isMatchingTalkgroup( LTRNetMessage message )
|
||||
{
|
||||
String talkgroup = message.getTalkgroupID();
|
||||
|
||||
if( talkgroup != null && getToID() != null &&
|
||||
talkgroup.contentEquals( getToID() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return isMatchingTalkgroup( message.getTalkgroupID() );
|
||||
}
|
||||
|
||||
public boolean isMatchingTalkgroup( String talkgroup )
|
||||
{
|
||||
return talkgroup != null &&
|
||||
getToID() != null &&
|
||||
talkgroup.contentEquals( getToID() );
|
||||
return talkgroup != null && getToID() != null && talkgroup.contentEquals( getToID() );
|
||||
}
|
||||
|
||||
|
||||
private Alias getAlias( String talkgroup )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
|
||||
@@ -23,19 +23,21 @@ import instrument.tap.TapGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IUnFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
import bits.SyncPattern;
|
||||
import dsp.fsk.LTRFSKDecoder;
|
||||
|
||||
public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instrumentable
|
||||
public class LTRNetDecoder extends Decoder
|
||||
implements IUnFilteredRealBufferListener, Instrumentable
|
||||
{
|
||||
public static final int LTR_STANDARD_MESSAGE_LENGTH = 40;
|
||||
private LTRFSKDecoder mLTRFSKDecoder;
|
||||
@@ -44,6 +46,10 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr
|
||||
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
|
||||
/**
|
||||
* LTR-Net Decoder. Decodes unfiltered (e.g. demodulated but with no DC or
|
||||
* audio filtering) samples and produces LTR-Net messages.
|
||||
*/
|
||||
public LTRNetDecoder( DecodeConfigLTRNet config, AliasList aliasList )
|
||||
{
|
||||
mLTRFSKDecoder = new LTRFSKDecoder();
|
||||
@@ -69,7 +75,7 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr
|
||||
|
||||
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );
|
||||
|
||||
mLTRMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mLTRMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,7 +85,7 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getUnFilteredRealBufferListener()
|
||||
{
|
||||
return mLTRFSKDecoder;
|
||||
}
|
||||
@@ -116,7 +122,7 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
179
src/module/decode/ltrnet/LTRNetDecoderEditor.java
Normal file
179
src/module/decode/ltrnet/LTRNetDecoderEditor.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrnet;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRNetDecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
mComboDirection.setModel( new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mComboDirection.setEnabled( false );
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
//No validation
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mAFC.setEnabled( true );
|
||||
mComboDirection.setEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigLTRNet )
|
||||
{
|
||||
DecodeConfigLTRNet ltr = (DecodeConfigLTRNet)config;
|
||||
mComboDirection.setSelectedItem( ltr.getMessageDirection() );
|
||||
mAFC.setSelected( ltr.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() );
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setEnabled( false );
|
||||
mComboDirection.setEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigLTRNet ltr = new DecodeConfigLTRNet();
|
||||
|
||||
ltr.setAFC( mAFC.isSelected() );
|
||||
ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() );
|
||||
|
||||
getItem().setDecodeConfiguration( ltr );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -777,7 +778,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrnet;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class LTRNetEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRNetEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
|
||||
mComboDirection.setModel(
|
||||
new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
|
||||
mComboDirection.setSelectedItem( ((DecodeConfigLTRNet)mConfig).getMessageDirection() );
|
||||
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
MessageDirection selected = mComboDirection
|
||||
.getItemAt( mComboDirection.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
((DecodeConfigLTRNet)mConfig).setMessageDirection( selected );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection, "wrap" );
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,20 @@
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IUnFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
import bits.SyncPattern;
|
||||
import dsp.fsk.LTRFSKDecoder;
|
||||
|
||||
public class LTRStandardDecoder extends Decoder implements IRealBufferListener
|
||||
public class LTRStandardDecoder extends Decoder implements IUnFilteredRealBufferListener
|
||||
{
|
||||
public static final int LTR_STANDARD_MESSAGE_LENGTH = 40;
|
||||
|
||||
@@ -36,6 +38,10 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener
|
||||
private MessageFramer mLTRMessageFramer;
|
||||
private LTRStandardMessageProcessor mLTRMessageProcessor;
|
||||
|
||||
/**
|
||||
* LTR Decoder. Decodes unfiltered (e.g. demodulated but with no DC or
|
||||
* audio filtering) samples and produces LTR Standard messages.
|
||||
*/
|
||||
public LTRStandardDecoder( AliasList aliasList,
|
||||
MessageDirection direction )
|
||||
{
|
||||
@@ -58,7 +64,7 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener
|
||||
|
||||
mLTRMessageProcessor = new LTRStandardMessageProcessor( direction, aliasList );
|
||||
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );
|
||||
mLTRMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mLTRMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +74,7 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getUnFilteredRealBufferListener()
|
||||
{
|
||||
return mLTRFSKDecoder;
|
||||
}
|
||||
@@ -80,7 +86,7 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
176
src/module/decode/ltrstandard/LTRStandardDecoderEditor.java
Normal file
176
src/module/decode/ltrstandard/LTRStandardDecoderEditor.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class LTRStandardDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRStandardDecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
mComboDirection.setModel( new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mComboDirection.setEnabled( false );
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mAFC.setEnabled( true );
|
||||
mComboDirection.setEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigLTRStandard )
|
||||
{
|
||||
DecodeConfigLTRStandard ltr = (DecodeConfigLTRStandard)config;
|
||||
mComboDirection.setSelectedItem( ltr.getMessageDirection() );
|
||||
mAFC.setSelected( ltr.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() );
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboDirection.setSelectedItem( MessageDirection.OSW );
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setEnabled( false );
|
||||
mComboDirection.setEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigLTRStandard ltr = new DecodeConfigLTRStandard();
|
||||
|
||||
ltr.setAFC( mAFC.isSelected() );
|
||||
ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() );
|
||||
|
||||
getItem().setDecodeConfiguration( ltr );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -73,8 +74,10 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -490,4 +493,4 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
return active;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import message.MessageDirection;
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class LTRStandardEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<MessageDirection> mComboDirection;
|
||||
|
||||
public LTRStandardEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
mComboDirection = new JComboBox<MessageDirection>();
|
||||
|
||||
mComboDirection.setModel(
|
||||
new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
|
||||
|
||||
mComboDirection.setSelectedItem( ((DecodeConfigLTRStandard)mConfig).getMessageDirection() );
|
||||
|
||||
mComboDirection.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
MessageDirection selected = mComboDirection
|
||||
.getItemAt( mComboDirection.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
((DecodeConfigLTRStandard)mConfig).setMessageDirection( selected );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Format:" ) );
|
||||
add( mComboDirection, "wrap" );
|
||||
}
|
||||
}
|
||||
@@ -118,4 +118,4 @@ public class LTRStandardMessageProcessor implements Listener<BinaryMessage>
|
||||
{
|
||||
mMessageListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard.message;
|
||||
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class CallEndMessage extends LTRStandardMessage
|
||||
{
|
||||
public CallEndMessage( BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.CA_ENDD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "END* AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " TG [" );
|
||||
sb.append( getToID() );
|
||||
sb.append( "/" );
|
||||
Alias endAlias = getToIDAlias();
|
||||
if( endAlias != null )
|
||||
{
|
||||
sb.append( getToIDAlias().getName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "UNKNOWN" );
|
||||
}
|
||||
sb.append( "] FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard.message;
|
||||
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class CallMessage extends LTRStandardMessage
|
||||
{
|
||||
public CallMessage( BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.CA_STRT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "CALL LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " TG [ " );
|
||||
sb.append( getToID() );
|
||||
sb.append( "/" );
|
||||
|
||||
Alias alias = getToIDAlias();
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
sb.append( getToIDAlias().getName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "UNKNOWN" );
|
||||
}
|
||||
|
||||
sb.append( " ] FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard.message;
|
||||
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class IdleMessage extends LTRStandardMessage
|
||||
{
|
||||
public IdleMessage( BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.SY_IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "IDLE AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " HOME:" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( " GRP:" );
|
||||
sb.append( getGroupFormatted() );
|
||||
sb.append( " FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard.message;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import module.decode.DecoderType;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public abstract class LTRStandardMessage extends Message
|
||||
{
|
||||
protected SimpleDateFormat mDatestampFormatter =
|
||||
new SimpleDateFormat( "yyyyMMdd HHmmss" );
|
||||
|
||||
public static final int[] SYNC = { 0,1,2,3,4,5,6,7,8 };
|
||||
public static final int[] AREA = { 9 };
|
||||
public static final int[] CHANNEL = { 10,11,12,13,14 };
|
||||
public static final int[] HOME_REPEATER = { 15,16,17,18,19 };
|
||||
public static final int[] GROUP = { 20,21,22,23,24,25,26,27 };
|
||||
public static final int[] FREE = { 28,29,30,31,32 };
|
||||
public static final int[] CHECKSUM = { 33,34,35,36,37,38,39 };
|
||||
|
||||
protected BinaryMessage mMessage;
|
||||
protected MessageDirection mMessageDirection;
|
||||
protected AliasList mAliasList;
|
||||
protected CRC mCRC;
|
||||
|
||||
public LTRStandardMessage( BinaryMessage message,
|
||||
MessageDirection direction,
|
||||
AliasList list,
|
||||
CRC crc )
|
||||
{
|
||||
mMessage = message;
|
||||
mMessageDirection = direction;
|
||||
mAliasList = list;
|
||||
mCRC = crc;
|
||||
}
|
||||
|
||||
public abstract MessageType getMessageType();
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mCRC != CRC.FAILED_CRC && mCRC != CRC.FAILED_PARITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( mDatestampFormatter.format(
|
||||
new Date( System.currentTimeMillis() ) ) );
|
||||
sb.append( " LTR " );
|
||||
sb.append( mMessageDirection.name() );
|
||||
sb.append( " [" );
|
||||
sb.append( mCRC.getAbbreviation() );
|
||||
sb.append( "] " );
|
||||
sb.append( getMessage() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryMessage()
|
||||
{
|
||||
return mMessage.toString();
|
||||
}
|
||||
|
||||
public CRC getCRC()
|
||||
{
|
||||
return mCRC;
|
||||
}
|
||||
|
||||
public int getArea()
|
||||
{
|
||||
return mMessage.getInt( AREA );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public String getChannelFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getChannel() ), 2, "0" );
|
||||
}
|
||||
|
||||
public int getHomeRepeater()
|
||||
{
|
||||
return mMessage.getInt( HOME_REPEATER );
|
||||
}
|
||||
|
||||
public String getHomeRepeaterFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getHomeRepeater() ), 2, "0" );
|
||||
}
|
||||
|
||||
public int getGroup()
|
||||
{
|
||||
return mMessage.getInt( GROUP );
|
||||
}
|
||||
|
||||
public String getGroupFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getGroup() ), 3, "0" );
|
||||
}
|
||||
|
||||
public int getFree()
|
||||
{
|
||||
return mMessage.getInt( FREE );
|
||||
}
|
||||
|
||||
public String getFreeFormatted()
|
||||
{
|
||||
return StringUtils.leftPad( String.valueOf( getFree() ), 2, "0" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getArea() );
|
||||
sb.append( "-" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( "-" );
|
||||
sb.append( getGroupFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getToID() );
|
||||
}
|
||||
|
||||
public List<Alias> getAliases()
|
||||
{
|
||||
List<Alias> aliases = new ArrayList<>();
|
||||
|
||||
Alias talkgroupAlias = getToIDAlias();
|
||||
|
||||
if( talkgroupAlias != null )
|
||||
{
|
||||
aliases.add( talkgroupAlias );
|
||||
}
|
||||
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public int getCRCChecksum()
|
||||
{
|
||||
return mMessage.getInt( CHECKSUM );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return DecoderType.LTR_STANDARD.getDisplayString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return getMessageType().getDisplayText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorStatus()
|
||||
{
|
||||
return mCRC.getDisplayText();
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard.message;
|
||||
|
||||
import message.MessageDirection;
|
||||
import message.MessageType;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class UnknownMessage extends LTRStandardMessage
|
||||
{
|
||||
public UnknownMessage( BinaryMessage message, MessageDirection direction,
|
||||
AliasList list, CRC crc )
|
||||
{
|
||||
super( message, direction, list, crc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageType getMessageType()
|
||||
{
|
||||
return MessageType.UN_KNWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "UNKNOWN AREA:" );
|
||||
sb.append( getArea() );
|
||||
sb.append( " LCN:" );
|
||||
sb.append( getChannelFormatted() );
|
||||
sb.append( " HOME:" );
|
||||
sb.append( getHomeRepeaterFormatted() );
|
||||
sb.append( " GRP:" );
|
||||
sb.append( getGroupFormatted() );
|
||||
sb.append( " FREE:" );
|
||||
sb.append( getFreeFormatted() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,12 @@ import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
@@ -46,7 +47,7 @@ import dsp.fsk.FSK2Decoder.Output;
|
||||
* MDC1200 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
|
||||
* complex or floating point samples and output fully framed MDC1200 messages
|
||||
*/
|
||||
public class MDCDecoder extends Decoder implements IRealBufferListener,
|
||||
public class MDCDecoder extends Decoder implements IFilteredRealBufferListener,
|
||||
Instrumentable
|
||||
{
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
@@ -102,7 +103,7 @@ public class MDCDecoder extends Decoder implements IRealBufferListener,
|
||||
/* Message Processor */
|
||||
mMessageProcessor = new MDCMessageProcessor( aliasList );
|
||||
mMessageFramer.addMessageListener( mMessageProcessor );
|
||||
mMessageProcessor.addMessageListener( mMessageBroadcaster );
|
||||
mMessageProcessor.addMessageListener( this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -197,7 +198,7 @@ public class MDCDecoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
@@ -210,7 +211,7 @@ public class MDCDecoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package module.decode.mdc1200;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -54,7 +55,7 @@ public class MDCDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.mpt1327;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.mpt1327.MPT1327Decoder.Sync;
|
||||
import playlist.PlaylistManager;
|
||||
import controller.channel.ChannelNode;
|
||||
import controller.channel.map.ChannelMap;
|
||||
|
||||
public class MPT1327ConfigEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<ChannelMap> mComboChannelMaps;
|
||||
private JComboBox<Sync> mComboSync;
|
||||
private JLabel mCallTimeoutLabel;
|
||||
private JSlider mCallTimeout;
|
||||
private JLabel mTrafficChannelPoolSizeLabel;
|
||||
private JSlider mTrafficChannelPoolSize;
|
||||
private ChannelNode mChannelNode;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
|
||||
public MPT1327ConfigEditor( DecodeConfiguration config,
|
||||
ChannelNode channelNode,
|
||||
PlaylistManager playlistManager )
|
||||
{
|
||||
super( config );
|
||||
|
||||
mChannelNode = channelNode;
|
||||
mPlaylistManager = playlistManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private DecodeConfigMPT1327 getMPTConfig()
|
||||
{
|
||||
return (DecodeConfigMPT1327)mConfig;
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
/**
|
||||
* ComboBox: Alias Lists
|
||||
*/
|
||||
List<ChannelMap> maps = ( mPlaylistManager == null ?
|
||||
new ArrayList<ChannelMap>() : mPlaylistManager.getPlayist()
|
||||
.getChannelMapList().getChannelMap() );
|
||||
|
||||
ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] );
|
||||
|
||||
mComboChannelMaps = new JComboBox<ChannelMap>();
|
||||
mComboChannelMaps.setModel(
|
||||
new DefaultComboBoxModel<ChannelMap>( mapArray ) );
|
||||
|
||||
add( new JLabel( "Channel Map:" ) );
|
||||
add( mComboChannelMaps, "wrap" );
|
||||
|
||||
mComboSync = new JComboBox<Sync>();
|
||||
mComboSync.setModel( new DefaultComboBoxModel<Sync>( Sync.values() ) );
|
||||
|
||||
add( new JLabel( "Sync:" ) );
|
||||
add( mComboSync, "wrap" );
|
||||
|
||||
mCallTimeout = new JSlider( JSlider.HORIZONTAL,
|
||||
DecodeConfiguration.CALL_TIMEOUT_MINIMUM,
|
||||
DecodeConfiguration.CALL_TIMEOUT_MAXIMUM,
|
||||
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
|
||||
|
||||
mCallTimeout.setMajorTickSpacing( 90 );
|
||||
mCallTimeout.setMinorTickSpacing( 10 );
|
||||
mCallTimeout.setPaintTicks( true );
|
||||
|
||||
mCallTimeout.setLabelTable( mCallTimeout.createStandardLabels( 100, 100 ) );
|
||||
mCallTimeout.setPaintLabels( true );
|
||||
|
||||
mCallTimeoutLabel = new JLabel( "Call Timeout: " + mCallTimeout.getValue() + " " );
|
||||
|
||||
mCallTimeout.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mCallTimeoutLabel.setText( "Call Timeout: " + mCallTimeout.getValue() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mCallTimeoutLabel );
|
||||
add( mCallTimeout, "wrap,grow" );
|
||||
|
||||
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
|
||||
|
||||
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
|
||||
mTrafficChannelPoolSize.setMinorTickSpacing( 1 );
|
||||
mTrafficChannelPoolSize.setPaintTicks( true );
|
||||
|
||||
mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) );
|
||||
mTrafficChannelPoolSize.setPaintLabels( true );
|
||||
|
||||
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " );
|
||||
|
||||
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mTrafficChannelPoolSizeLabel );
|
||||
add( mTrafficChannelPoolSize, "wrap,grow" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
DecodeConfigMPT1327 config = getMPTConfig();
|
||||
|
||||
ChannelMap selected = (ChannelMap)mComboChannelMaps.getSelectedItem();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
config.setChannelMapName( selected.getName() );
|
||||
}
|
||||
|
||||
Sync selectedSync = (Sync)mComboSync.getSelectedItem();
|
||||
|
||||
if( selectedSync != null )
|
||||
{
|
||||
config.setSync( selectedSync );
|
||||
}
|
||||
|
||||
config.setCallTimeout( mCallTimeout.getValue() );
|
||||
|
||||
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
DecodeConfigMPT1327 config = (DecodeConfigMPT1327)mConfig;
|
||||
|
||||
String name = config.getChannelMapName();
|
||||
|
||||
ChannelMap selected = null;
|
||||
|
||||
if( name != null )
|
||||
{
|
||||
for( ChannelMap map: mChannelNode.getModel().getResourceManager()
|
||||
.getPlaylistManager().getPlayist().getChannelMapList()
|
||||
.getChannelMap() )
|
||||
{
|
||||
if( map.getName().equalsIgnoreCase( name ) )
|
||||
{
|
||||
selected = map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mComboChannelMaps.setSelectedItem( selected );
|
||||
mComboChannelMaps.requestFocus();
|
||||
mComboChannelMaps.requestFocusInWindow();
|
||||
|
||||
mComboSync.setSelectedItem( config.getSync() );
|
||||
|
||||
mCallTimeout.setValue( config.getCallTimeout() );
|
||||
|
||||
mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
@@ -35,7 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
@@ -55,7 +56,7 @@ import dsp.fsk.FSK2Decoder.Output;
|
||||
* traffic messages.
|
||||
*/
|
||||
public class MPT1327Decoder extends Decoder
|
||||
implements IRealBufferListener, Instrumentable
|
||||
implements IFilteredRealBufferListener, Instrumentable
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( MPT1327Decoder.class );
|
||||
|
||||
@@ -140,13 +141,13 @@ public class MPT1327Decoder extends Decoder
|
||||
|
||||
/* Fully decoded and framed messages processor */
|
||||
mMessageProcessor = new MPT1327MessageProcessor( aliasList );
|
||||
mMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageProcessor.setMessageListener( this );
|
||||
mControlMessageFramer.addMessageListener( mMessageProcessor );
|
||||
mTrafficMessageFramer.addMessageListener( mMessageProcessor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
@@ -306,7 +307,7 @@ public class MPT1327Decoder extends Decoder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
285
src/module/decode/mpt1327/MPT1327DecoderEditor.java
Normal file
285
src/module/decode/mpt1327/MPT1327DecoderEditor.java
Normal file
@@ -0,0 +1,285 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.mpt1327;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.map.ChannelMap;
|
||||
import controller.channel.map.ChannelMapManagerFrame;
|
||||
import controller.channel.map.ChannelMapModel;
|
||||
|
||||
public class MPT1327DecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
private JComboBox<ChannelMap> mComboChannelMaps;
|
||||
private JLabel mCallTimeoutLabel;
|
||||
private JSlider mCallTimeout;
|
||||
private JLabel mTrafficChannelPoolSizeLabel;
|
||||
private JSlider mTrafficChannelPoolSize;
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
|
||||
public MPT1327DecoderEditor( ChannelMapModel channelMapModel )
|
||||
{
|
||||
mChannelMapModel = channelMapModel;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
|
||||
JButton channelMaps = new JButton( "Channel Maps" );
|
||||
channelMaps.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
final ChannelMapManagerFrame manager =
|
||||
new ChannelMapManagerFrame( mChannelMapModel );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
manager.setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
add( channelMaps, "span 2" );
|
||||
|
||||
List<ChannelMap> maps = mChannelMapModel.getChannelMaps();
|
||||
ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] );
|
||||
|
||||
mComboChannelMaps = new JComboBox<ChannelMap>();
|
||||
mComboChannelMaps.setModel( new DefaultComboBoxModel<ChannelMap>( mapArray ) );
|
||||
mComboChannelMaps.setEnabled( false );
|
||||
add( new JLabel( "Channel Map:" ) );
|
||||
add( mComboChannelMaps, "span 3,grow" );
|
||||
|
||||
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
|
||||
mTrafficChannelPoolSize.setEnabled( false );
|
||||
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
|
||||
mTrafficChannelPoolSize.setMinorTickSpacing( 5 );
|
||||
mTrafficChannelPoolSize.setPaintTicks( true );
|
||||
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " +
|
||||
mTrafficChannelPoolSize.getValue() + " " );
|
||||
|
||||
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " +
|
||||
mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mTrafficChannelPoolSizeLabel );
|
||||
add( mTrafficChannelPoolSize );
|
||||
|
||||
mCallTimeout = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.CALL_TIMEOUT_MINIMUM,
|
||||
DecodeConfiguration.CALL_TIMEOUT_MAXIMUM, DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
|
||||
mCallTimeout.setEnabled( false );
|
||||
mCallTimeout.setMajorTickSpacing( 100 );
|
||||
mCallTimeout.setMinorTickSpacing( 50 );
|
||||
mCallTimeout.setPaintTicks( true );
|
||||
|
||||
mCallTimeoutLabel = new JLabel( "Timeout: " + mCallTimeout.getValue() + " " );
|
||||
|
||||
mCallTimeout.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mCallTimeoutLabel.setText( "Timeout: " + mCallTimeout.getValue() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mCallTimeoutLabel );
|
||||
add( mCallTimeout );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigMPT1327 mpt = new DecodeConfigMPT1327();
|
||||
mpt.setAFC( mAFC.isSelected() );
|
||||
mpt.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
mpt.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
|
||||
mpt.setCallTimeout( mCallTimeout.getValue() );
|
||||
|
||||
if( mComboChannelMaps.getSelectedItem() != null )
|
||||
{
|
||||
ChannelMap map = (ChannelMap)mComboChannelMaps.getSelectedItem();
|
||||
|
||||
mpt.setChannelMapName( map.getName() );
|
||||
}
|
||||
|
||||
getItem().setDecodeConfiguration( mpt );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
//No validation required
|
||||
}
|
||||
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mAFC.isEnabled() != enabled )
|
||||
{
|
||||
mAFC.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboChannelMaps.isEnabled() != enabled )
|
||||
{
|
||||
mComboChannelMaps.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTrafficChannelPoolSize.isEnabled() != enabled )
|
||||
{
|
||||
mTrafficChannelPoolSize.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mCallTimeout.isEnabled() != enabled )
|
||||
{
|
||||
mCallTimeout.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigMPT1327 )
|
||||
{
|
||||
DecodeConfigMPT1327 mpt = (DecodeConfigMPT1327)config;
|
||||
mAFC.setSelected( mpt.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( mpt.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( mpt.isAFCEnabled() );
|
||||
|
||||
ChannelMap map = mChannelMapModel.getChannelMap( mpt.getChannelMapName() );
|
||||
|
||||
if( map != null )
|
||||
{
|
||||
mComboChannelMaps.setSelectedItem( map );
|
||||
}
|
||||
|
||||
mTrafficChannelPoolSize.setValue( mpt.getTrafficChannelPoolSize() );
|
||||
mCallTimeout.setValue( mpt.getCallTimeout() );
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
|
||||
mCallTimeout.setValue( DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* 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
|
||||
@@ -23,6 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -85,7 +86,7 @@ public class MPT1327DecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -612,4 +613,4 @@ public class MPT1327DecoderState extends DecoderState
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
******************************************************************************/
|
||||
package module.decode.nbfm;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.PrimaryDecoder;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
@@ -40,7 +42,7 @@ public class NBFMDecoder extends PrimaryDecoder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
161
src/module/decode/nbfm/NBFMDecoderEditor.java
Normal file
161
src/module/decode/nbfm/NBFMDecoderEditor.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.nbfm;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class NBFMDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
|
||||
public NBFMDecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
//No validation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigNBFM nbfm = new DecodeConfigNBFM();
|
||||
|
||||
nbfm.setAFC( mAFC.isSelected() );
|
||||
nbfm.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
|
||||
getItem().setDecodeConfiguration( nbfm );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mAFC.isEnabled() != enabled )
|
||||
{
|
||||
mAFC.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigNBFM )
|
||||
{
|
||||
DecodeConfigNBFM nbfm = (DecodeConfigNBFM)config;
|
||||
|
||||
mAFC.setSelected( nbfm.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( nbfm.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( nbfm.isAFCEnabled() );
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.nbfm;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class NBFMEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
|
||||
public NBFMEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
}
|
||||
}
|
||||
@@ -9,25 +9,20 @@ import instrument.tap.stream.FloatTap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
import sample.real.RealSampleListener;
|
||||
import sample.real.RealSampleProvider;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl.FrequencyCorrectionResetListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.IFrequencyChangeListener;
|
||||
import dsp.gain.DirectGainControl;
|
||||
|
||||
public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
Listener<RealBuffer>,
|
||||
public class C4FMSymbolFilter implements Listener<RealBuffer>,
|
||||
IFrequencyChangeListener,
|
||||
RealSampleProvider,
|
||||
Instrumentable
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( C4FMSymbolFilter.class );
|
||||
|
||||
private static final float TAPS[][] =
|
||||
{
|
||||
{ 0.00000e+00f, 0.00000e+00f, 0.00000e+00f, 0.00000e+00f, 1.00000e+00f, 0.00000e+00f, 0.00000e+00f, 0.00000e+00f }, // 0/128
|
||||
@@ -201,15 +196,17 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
private float mHistory[] = new float[ NUMBER_FILTER_TAPS ];
|
||||
private int mHistoryLast = 0;
|
||||
|
||||
private boolean mResetFrequencyTracker = false;
|
||||
|
||||
private RealSampleListener mListener;
|
||||
|
||||
private DirectGainControl mGainController =
|
||||
new DirectGainControl( 15.0f, 0.1f, 35.0f, 0.3f );
|
||||
|
||||
private FrequencyCorrectionControl mFrequencyCorrectionControl;
|
||||
private int mFrequencyAdjustmentRequested = 0;
|
||||
private int mFrequencyCorrection = 0;
|
||||
private int mFrequencyCorrectionMaximum = 3000;
|
||||
private boolean mResetFrequencyTracker = false;
|
||||
private FrequencyCorrectionProcessor mFrequencyCorrectionProcessor;
|
||||
private Listener<FrequencyChangeEvent> mFrequencyChangeListener;
|
||||
|
||||
/**
|
||||
* C4FM Symbol Filter
|
||||
@@ -224,18 +221,15 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
* setting for this filter is 15.4 and that yields a symbol spread that
|
||||
* is centered on 2.0, ranging 1.92 to 2.08.
|
||||
*/
|
||||
public C4FMSymbolFilter( FrequencyCorrectionControl frequencyControl )
|
||||
public C4FMSymbolFilter( int frequencyCorrectionMaximum )
|
||||
{
|
||||
mFrequencyCorrectionControl = frequencyControl;
|
||||
|
||||
/* Register for reset events, so we can reset internal frequency tracking */
|
||||
mFrequencyCorrectionControl.setListener( this );
|
||||
mFrequencyCorrectionMaximum = frequencyCorrectionMaximum;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mGainController = null;
|
||||
mFrequencyCorrectionControl = null;
|
||||
// mFrequencyCorrectionControl = null;
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
@@ -253,13 +247,21 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
* the internal frequency correction tracker */
|
||||
if( mFrequencyAdjustmentRequested != 0 )
|
||||
{
|
||||
mFrequencyCorrectionControl.adjust( mFrequencyAdjustmentRequested );
|
||||
int correction = mFrequencyCorrection + mFrequencyAdjustmentRequested;
|
||||
|
||||
if( correction > mFrequencyCorrectionMaximum )
|
||||
{
|
||||
correction = mFrequencyCorrectionMaximum;
|
||||
}
|
||||
else if( correction < -mFrequencyCorrectionMaximum )
|
||||
{
|
||||
correction = -mFrequencyCorrectionMaximum;
|
||||
}
|
||||
|
||||
broadcast( new FrequencyChangeEvent(
|
||||
Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, correction ) );
|
||||
|
||||
mFrequencyAdjustmentRequested = 0;
|
||||
|
||||
//Reset internal frequency tracking
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +274,8 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
|
||||
mFrequencyCorrectionControl.setFrequencyCorrection( 0 );
|
||||
broadcast( new FrequencyChangeEvent(
|
||||
Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, 0 ));
|
||||
|
||||
mResetFrequencyTracker = false;
|
||||
}
|
||||
@@ -397,17 +400,6 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface for frequency correction reset events. We reset the
|
||||
* coarse and fine frequency control values when the tuner channel source
|
||||
* has changed frequency (PPM) or sample rate
|
||||
*/
|
||||
@Override
|
||||
public void resetFrequencyCorrection()
|
||||
{
|
||||
mResetFrequencyTracker = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener( RealSampleListener listener )
|
||||
{
|
||||
@@ -459,4 +451,56 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
mSymbolSpreadTap = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcast( FrequencyChangeEvent event )
|
||||
{
|
||||
if( mFrequencyChangeListener != null )
|
||||
{
|
||||
mFrequencyChangeListener.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener()
|
||||
{
|
||||
if( mFrequencyCorrectionProcessor == null )
|
||||
{
|
||||
mFrequencyCorrectionProcessor = new FrequencyCorrectionProcessor();
|
||||
}
|
||||
|
||||
return mFrequencyCorrectionProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives notifications that the channel frequency correction has been
|
||||
* applied and updates internal tracking value.
|
||||
*/
|
||||
public class FrequencyCorrectionProcessor implements Listener<FrequencyChangeEvent>
|
||||
{
|
||||
@Override
|
||||
public void receive( FrequencyChangeEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
mFrequencyCorrection = event.getValue().intValue();
|
||||
|
||||
//Reset internal frequency tracking
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
break;
|
||||
case NOTIFICATION_FREQUENCY_CORRECTION_CHANGE:
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
mResetFrequencyTracker = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.p25;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.p25.P25Decoder.Modulation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceEditor;
|
||||
import source.tuner.TunerEditor;
|
||||
import controller.Editor;
|
||||
import controller.channel.ChannelValidationException;
|
||||
|
||||
public class P25DecodeEditor extends DecodeEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( P25DecodeEditor.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<P25_LSMDecoder.Modulation> mComboModulation;
|
||||
private JCheckBox mIgnoreDataCalls;
|
||||
private JLabel mTrafficChannelPoolSizeLabel;
|
||||
private JSlider mTrafficChannelPoolSize;
|
||||
|
||||
public P25DecodeEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
final DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
|
||||
|
||||
mComboModulation = new JComboBox<P25_LSMDecoder.Modulation>();
|
||||
|
||||
mComboModulation.setModel( new DefaultComboBoxModel<P25_LSMDecoder.Modulation>(
|
||||
P25_LSMDecoder.Modulation.values() ) );
|
||||
|
||||
mComboModulation.setSelectedItem( config.getModulation() );
|
||||
|
||||
add( new JLabel( "Modulation:" ) );
|
||||
add( mComboModulation, "wrap" );
|
||||
|
||||
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM,
|
||||
config.getTrafficChannelPoolSize() );
|
||||
|
||||
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
|
||||
mTrafficChannelPoolSize.setMinorTickSpacing( 1 );
|
||||
mTrafficChannelPoolSize.setPaintTicks( true );
|
||||
|
||||
mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) );
|
||||
mTrafficChannelPoolSize.setPaintLabels( true );
|
||||
|
||||
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " );
|
||||
|
||||
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mTrafficChannelPoolSizeLabel );
|
||||
add( mTrafficChannelPoolSize, "wrap,grow" );
|
||||
|
||||
mIgnoreDataCalls = new JCheckBox();
|
||||
mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
|
||||
|
||||
add( new JLabel( "Ignore Data Calls" ) );
|
||||
add( mIgnoreDataCalls, "wrap,grow" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce source=tuner for CQPSK modulation
|
||||
*/
|
||||
@Override
|
||||
public void validate( Editor editor ) throws ChannelValidationException
|
||||
{
|
||||
if( editor instanceof SourceEditor &&
|
||||
((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK )
|
||||
{
|
||||
if( !( editor instanceof TunerEditor ) )
|
||||
{
|
||||
throw new ChannelValidationException(
|
||||
"<html><body width='175'><h1>LSM Simulcast</h1>"
|
||||
+ "<p>P25 LSM Simulcast decoder can only be used with "
|
||||
+ "a tuner source. Please change the Source to use a tuner"
|
||||
+ " or change the P25 Decoder to C4FM modulation" );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
|
||||
|
||||
config.setModulation( (Modulation)mComboModulation.getSelectedItem() );
|
||||
config.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() );
|
||||
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
|
||||
|
||||
mComboModulation.setSelectedItem( config.getModulation() );
|
||||
mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
|
||||
mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
package module.decode.p25;
|
||||
|
||||
import alias.AliasList;
|
||||
import instrument.Instrumentable;
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import source.tuner.frequency.IFrequencyCorrectionController;
|
||||
import alias.AliasList;
|
||||
|
||||
public abstract class P25Decoder extends Decoder
|
||||
implements IFrequencyCorrectionController, Instrumentable
|
||||
public abstract class P25Decoder extends Decoder implements Instrumentable
|
||||
{
|
||||
private P25MessageProcessor mMessageProcessor;
|
||||
|
||||
public P25Decoder( AliasList aliasList )
|
||||
{
|
||||
mMessageProcessor = new P25MessageProcessor( aliasList );
|
||||
mMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
|
||||
226
src/module/decode/p25/P25DecoderEditor.java
Normal file
226
src/module/decode/p25/P25DecoderEditor.java
Normal file
@@ -0,0 +1,226 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.p25;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.AuxDecodeConfigurationEditor;
|
||||
import module.decode.config.AuxDecodeConfiguration;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.p25.P25Decoder.Modulation;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceConfigurationEditor;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class P25DecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( P25DecoderEditor.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<P25_LSMDecoder.Modulation> mComboModulation;
|
||||
private JCheckBox mIgnoreDataCalls;
|
||||
private JLabel mTrafficChannelPoolSizeLabel;
|
||||
private JSlider mTrafficChannelPoolSize;
|
||||
|
||||
public P25DecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 3", "[right][grow,fill][]", "" ) );
|
||||
|
||||
mComboModulation = new JComboBox<P25_LSMDecoder.Modulation>();
|
||||
mComboModulation.setModel( new DefaultComboBoxModel<P25_LSMDecoder.Modulation>(
|
||||
P25_LSMDecoder.Modulation.values() ) );
|
||||
mComboModulation.setEnabled( false );
|
||||
mComboModulation.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Modulation:" ) );
|
||||
add( mComboModulation );
|
||||
|
||||
mIgnoreDataCalls = new JCheckBox( "Ignore Data Calls" );
|
||||
mIgnoreDataCalls.setEnabled( false );
|
||||
mIgnoreDataCalls.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mIgnoreDataCalls );
|
||||
|
||||
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
|
||||
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
|
||||
mTrafficChannelPoolSize.setEnabled( false );
|
||||
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
|
||||
mTrafficChannelPoolSize.setMinorTickSpacing( 5 );
|
||||
mTrafficChannelPoolSize.setPaintTicks( true );
|
||||
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() + " " );
|
||||
|
||||
add( mTrafficChannelPoolSizeLabel );
|
||||
add( mTrafficChannelPoolSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigP25Phase1 p25 = new DecodeConfigP25Phase1();
|
||||
|
||||
p25.setModulation( (Modulation)mComboModulation.getSelectedItem() );
|
||||
p25.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() );
|
||||
p25.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
|
||||
|
||||
getItem().setDecodeConfiguration( p25 );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
mLog.debug( "Validating editor:" + editor.getClass() );
|
||||
/**
|
||||
* Enforce CQPSK modulation uses a Tuner Source for I/Q sample data
|
||||
*/
|
||||
if( editor instanceof SourceConfigurationEditor &&
|
||||
((Modulation)mComboModulation.getSelectedItem()) == Modulation.CQPSK )
|
||||
{
|
||||
SourceConfiguration config = ((SourceConfigurationEditor)editor).getSourceConfiguration();
|
||||
|
||||
if( config != null && !( config instanceof SourceConfigTuner ) )
|
||||
{
|
||||
throw new EditorValidationException( editor,
|
||||
"<html><body width='175'><h3>LSM Simulcast</h3>"
|
||||
+ "<p>P25 LSM Simulcast decoder can only be used with "
|
||||
+ "a tuner source. Please change the Source to use a tuner"
|
||||
+ " or change the P25 Decoder to C4FM modulation</p>" );
|
||||
}
|
||||
}
|
||||
|
||||
if( editor instanceof AuxDecodeConfigurationEditor )
|
||||
{
|
||||
AuxDecodeConfiguration config = ((AuxDecodeConfigurationEditor)editor).getConfiguration();
|
||||
|
||||
if( config != null && !config.getAuxDecoders().isEmpty() )
|
||||
{
|
||||
throw new EditorValidationException( editor,
|
||||
"<html><body width='175'><h3>Auxilary Decoders</h3>"
|
||||
+ "<p>The auxiliary decoders work with analog audio and are not "
|
||||
+ "compatible with the P25 Decoder. Please uncheck any auxiliary "
|
||||
+ "decoders that you have selected for this channel</p>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mComboModulation.isEnabled() != enabled )
|
||||
{
|
||||
mComboModulation.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTrafficChannelPoolSize.isEnabled() != enabled )
|
||||
{
|
||||
mTrafficChannelPoolSize.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mIgnoreDataCalls.isEnabled() != enabled )
|
||||
{
|
||||
mIgnoreDataCalls.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigP25Phase1 )
|
||||
{
|
||||
DecodeConfigP25Phase1 p25 = (DecodeConfigP25Phase1)config;
|
||||
|
||||
mComboModulation.setSelectedItem( p25.getModulation() );
|
||||
mIgnoreDataCalls.setSelected( p25.getIgnoreDataCalls() );
|
||||
mTrafficChannelPoolSize.setValue( p25.getTrafficChannelPoolSize() );
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboModulation.setSelectedItem( Modulation.C4FM );
|
||||
mIgnoreDataCalls.setSelected( false );
|
||||
mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.CallEvent.CallEventType;
|
||||
import module.decode.p25.P25Decoder.Modulation;
|
||||
import module.decode.p25.message.IAdjacentSite;
|
||||
@@ -121,6 +121,7 @@ import module.decode.p25.reference.IPProtocol;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Response;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import module.decode.state.ChangeChannelTimeoutEvent;
|
||||
import module.decode.state.ChangedAttribute;
|
||||
import module.decode.state.DecoderState;
|
||||
import module.decode.state.DecoderStateEvent;
|
||||
@@ -204,11 +205,6 @@ public class P25DecoderState extends DecoderState
|
||||
return DecoderType.P25_PHASE1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
@@ -1668,7 +1664,7 @@ public class P25DecoderState extends DecoderState
|
||||
.to( satcr.getLogicalLinkID() )
|
||||
.build() );
|
||||
break;
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
case SNDCP_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
SNDCPActivateTDSContextRequest satcreq =
|
||||
(SNDCPActivateTDSContextRequest)pduc;
|
||||
|
||||
@@ -2292,6 +2288,8 @@ public class P25DecoderState extends DecoderState
|
||||
logAlternateVendorMessage( pdu );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2437,8 +2435,6 @@ public class P25DecoderState extends DecoderState
|
||||
|
||||
private void processTSBKResponse( TSBKMessage message )
|
||||
{
|
||||
CallEvent event = null;
|
||||
|
||||
switch( message.getOpcode() )
|
||||
{
|
||||
case ACKNOWLEDGE_RESPONSE:
|
||||
@@ -3560,4 +3556,14 @@ public class P25DecoderState extends DecoderState
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
//Change the default (45-second) traffic channel timeout to 1 second
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
{
|
||||
broadcast( new ChangeChannelTimeoutEvent( this, ChannelType.TRAFFIC, 1000 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import module.decode.p25.message.tdu.lc.TDULCMessageFactory;
|
||||
import module.decode.p25.message.tdu.lc.TDULinkControlMessage;
|
||||
import module.decode.p25.message.tsbk.TSBKMessage;
|
||||
import module.decode.p25.message.tsbk.TSBKMessageFactory;
|
||||
import module.decode.p25.message.vselp.VSELP1Message;
|
||||
import module.decode.p25.message.vselp.VSELP2Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -129,7 +131,7 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
if( demodulator != null )
|
||||
{
|
||||
/* For CQPSK, we include 3 additional sync detectors to watch for and
|
||||
* correction +/-90 and 180 degree costas loop phase lock errors */
|
||||
* correct +/-90 and 180 degree costas loop phase lock errors */
|
||||
mMatcher.add( new CostasPhaseErrorDetector( FrameSync.P25_PHASE1_ERROR_90_CCW,
|
||||
demodulator, PHASE_CORRECTION_90_DEGREES ) );
|
||||
|
||||
@@ -289,7 +291,7 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
else
|
||||
{
|
||||
mComplete = true;
|
||||
dispatch( new P25Message( mMessage.copy(), duid, mAliasList ) );
|
||||
dispatch( new P25Message( mMessage.copy(), mDUID, mAliasList ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -631,6 +633,14 @@ public class P25MessageFramer implements Listener<Dibit>
|
||||
|
||||
mComplete = true;
|
||||
break;
|
||||
case VSELP1:
|
||||
mComplete = true;
|
||||
dispatch( new VSELP1Message( mMessage.copy(), mDUID, mAliasList ) );
|
||||
break;
|
||||
case VSELP2:
|
||||
mComplete = true;
|
||||
dispatch( new VSELP2Message( mMessage.copy(), mDUID, mAliasList ) );
|
||||
break;
|
||||
case UNKN:
|
||||
mComplete = true;
|
||||
dispatch( new P25Message( mMessage.copy(), mDUID, mAliasList ) );
|
||||
|
||||
@@ -10,8 +10,8 @@ import module.decode.p25.message.ldu.LDUMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
import sample.Listener;
|
||||
|
||||
public class P25MessageProcessor implements Listener<Message>
|
||||
{
|
||||
|
||||
@@ -24,22 +24,25 @@ import instrument.tap.stream.FloatBufferTap;
|
||||
import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import alias.AliasList;
|
||||
import sample.Listener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.IFrequencyChangeListener;
|
||||
import source.tuner.frequency.IFrequencyChangeProvider;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.fir.real.RealFIRFilter_RB_RB;
|
||||
|
||||
public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
public class P25_C4FMDecoder extends P25Decoder
|
||||
implements IFrequencyChangeListener, IFrequencyChangeProvider,IFilteredRealBufferListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class );
|
||||
|
||||
@@ -48,11 +51,8 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output";
|
||||
private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output";
|
||||
|
||||
private final static int MAXIMUM_FREQUENCY_CORRECTION = 3000; //Hertz, +/-
|
||||
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
private RealFIRFilter_RB_RB mC4FMPreFilter;
|
||||
private FrequencyCorrectionControl mFrequencyCorrectionControl;
|
||||
private C4FMSymbolFilter mSymbolFilter;
|
||||
private C4FMSlicer mC4FMSlicer;
|
||||
private P25MessageFramer mMessageFramer;
|
||||
@@ -70,7 +70,7 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
* infrastructure and subscriber identities that will be included in each
|
||||
* decoded message
|
||||
*/
|
||||
public P25_C4FMDecoder( AliasList aliasList )
|
||||
public P25_C4FMDecoder( AliasList aliasList, int frequencyCorrectionMaximum )
|
||||
{
|
||||
super( aliasList );
|
||||
|
||||
@@ -79,13 +79,8 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
|
||||
mC4FMPreFilter = new RealFIRFilter_RB_RB( filter, 1.0f );
|
||||
|
||||
/* Issue tuned frequency correction commands, remotely controlled by the
|
||||
* downstream symbol filter */
|
||||
mFrequencyCorrectionControl = new FrequencyCorrectionControl(
|
||||
MAXIMUM_FREQUENCY_CORRECTION );
|
||||
|
||||
/* Shape gain and frequency offsets to optimize sample stream */
|
||||
mSymbolFilter = new C4FMSymbolFilter( mFrequencyCorrectionControl );
|
||||
mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum );
|
||||
mC4FMPreFilter.setListener( mSymbolFilter );
|
||||
|
||||
/* Convert samples to symbols */
|
||||
@@ -108,9 +103,6 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
mC4FMPreFilter.dispose();
|
||||
mC4FMPreFilter = null;
|
||||
|
||||
mFrequencyCorrectionControl.dispose();
|
||||
mFrequencyCorrectionControl = null;
|
||||
|
||||
mSymbolFilter.dispose();
|
||||
mSymbolFilter = null;
|
||||
|
||||
@@ -127,19 +119,7 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFrequencyCorrectionControl()
|
||||
{
|
||||
return mFrequencyCorrectionControl != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl()
|
||||
{
|
||||
return mFrequencyCorrectionControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mC4FMPreFilter;
|
||||
}
|
||||
@@ -249,7 +229,7 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
@@ -261,4 +241,33 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener )
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
mSymbolFilter.setFrequencyChangeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFrequencyChangeListener()
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
mSymbolFilter.setFrequencyChangeListener( null );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener()
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
return mSymbolFilter.getFrequencyChangeListener();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,16 +26,16 @@ import instrument.tap.stream.QPSKTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.ComplexBufferToStreamConverter;
|
||||
import sample.complex.IComplexBufferListener;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import alias.AliasList;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.fir.complex.ComplexFIRFilter_CB_CB;
|
||||
@@ -50,8 +50,8 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
/* Instrumentation Taps */
|
||||
private static final String INSTRUMENT_BASEBAND_FILTER_OUTPUT = "Tap Point: Baseband Filter Output";
|
||||
private static final String INSTRUMENT_AGC_OUTPUT = "Tap Point: AGC Output";
|
||||
private static final String INSTRUMENT_QPSK_DEMODULATOR_OUTPUT = "Tap Point: CQPSK Demodulator Output";
|
||||
private static final String INSTRUMENT_CQPSK_SLICER_OUTPUT = "Tap Point: CQPSK Slicer Output";
|
||||
private static final String INSTRUMENT_LSM_DEMODULATOR_OUTPUT = "Tap Point: LSM Demodulator Output";
|
||||
private static final String INSTRUMENT_QPSK_SLICER_OUTPUT = "Tap Point: QPSK Slicer Output";
|
||||
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
|
||||
@@ -60,8 +60,8 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
new ComplexBufferToStreamConverter();
|
||||
private ComplexFeedForwardGainControl mAGC =
|
||||
new ComplexFeedForwardGainControl( 32 );
|
||||
private LSMDemodulator mCQPSKDemodulator = new LSMDemodulator();
|
||||
private QPSKPolarSlicer mCQPSKSlicer = new QPSKPolarSlicer();
|
||||
private LSMDemodulator mLSMDemodulator = new LSMDemodulator();
|
||||
private QPSKPolarSlicer mQPSKSlicer = new QPSKPolarSlicer();
|
||||
private P25MessageFramer mMessageFramer;
|
||||
|
||||
public P25_LSMDecoder( AliasList aliasList )
|
||||
@@ -75,12 +75,12 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
|
||||
mStreamConverter.setListener( mAGC );
|
||||
|
||||
mAGC.setListener( mCQPSKDemodulator );
|
||||
mAGC.setListener( mLSMDemodulator );
|
||||
|
||||
mCQPSKDemodulator.setSymbolListener( mCQPSKSlicer );
|
||||
mLSMDemodulator.setSymbolListener( mQPSKSlicer );
|
||||
|
||||
mMessageFramer = new P25MessageFramer( aliasList, mCQPSKDemodulator );
|
||||
mCQPSKSlicer.addListener( mMessageFramer );
|
||||
mMessageFramer = new P25MessageFramer( aliasList, mLSMDemodulator );
|
||||
mQPSKSlicer.addListener( mMessageFramer );
|
||||
|
||||
mMessageFramer.setListener( getMessageProcessor() );
|
||||
}
|
||||
@@ -98,11 +98,11 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
mAGC.dispose();
|
||||
mAGC = null;
|
||||
|
||||
mCQPSKDemodulator.dispose();
|
||||
mCQPSKDemodulator = null;
|
||||
mLSMDemodulator.dispose();
|
||||
mLSMDemodulator = null;
|
||||
|
||||
mCQPSKSlicer.dispose();
|
||||
mCQPSKSlicer = null;
|
||||
mQPSKSlicer.dispose();
|
||||
mQPSKSlicer = null;
|
||||
|
||||
mMessageFramer.dispose();
|
||||
mMessageFramer = null;
|
||||
@@ -119,18 +119,6 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
return Modulation.CQPSK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFrequencyCorrectionControl()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of instrumentation taps for monitoring internal processing
|
||||
*/
|
||||
@@ -145,14 +133,14 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
|
||||
group.add( new ComplexTap( INSTRUMENT_BASEBAND_FILTER_OUTPUT, 0, 1.0f ) );
|
||||
group.add( new ComplexTap( INSTRUMENT_AGC_OUTPUT, 0, 1.0f ) );
|
||||
group.add( new QPSKTap( INSTRUMENT_QPSK_DEMODULATOR_OUTPUT, 0, 1.0f ) );
|
||||
group.add( new DibitTap( INSTRUMENT_CQPSK_SLICER_OUTPUT, 0, 0.1f ) );
|
||||
group.add( new QPSKTap( INSTRUMENT_LSM_DEMODULATOR_OUTPUT, 0, 1.0f ) );
|
||||
group.add( new DibitTap( INSTRUMENT_QPSK_SLICER_OUTPUT, 0, 0.1f ) );
|
||||
|
||||
mAvailableTaps.add( group );
|
||||
|
||||
if( mCQPSKDemodulator != null )
|
||||
if( mLSMDemodulator != null )
|
||||
{
|
||||
mAvailableTaps.addAll( mCQPSKDemodulator.getTapGroups() );
|
||||
mAvailableTaps.addAll( mLSMDemodulator.getTapGroups() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,9 +153,9 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
@Override
|
||||
public void registerTap( Tap tap )
|
||||
{
|
||||
if( mCQPSKDemodulator != null )
|
||||
if( mLSMDemodulator != null )
|
||||
{
|
||||
mCQPSKDemodulator.registerTap( tap );
|
||||
mLSMDemodulator.registerTap( tap );
|
||||
}
|
||||
|
||||
switch( tap.getName() )
|
||||
@@ -180,15 +168,15 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
case INSTRUMENT_AGC_OUTPUT:
|
||||
ComplexSampleTap agcSymbol = (ComplexSampleTap)tap;
|
||||
mAGC.setListener( agcSymbol );
|
||||
agcSymbol.setListener( mCQPSKDemodulator );
|
||||
agcSymbol.setListener( mLSMDemodulator );
|
||||
break;
|
||||
case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT:
|
||||
case INSTRUMENT_LSM_DEMODULATOR_OUTPUT:
|
||||
QPSKTap qpsk = (QPSKTap)tap;
|
||||
mCQPSKDemodulator.setSymbolListener( qpsk );
|
||||
qpsk.setListener( mCQPSKSlicer );
|
||||
mLSMDemodulator.setSymbolListener( qpsk );
|
||||
qpsk.setListener( mQPSKSlicer );
|
||||
break;
|
||||
case INSTRUMENT_CQPSK_SLICER_OUTPUT:
|
||||
mCQPSKSlicer.addListener( (DibitTap)tap );
|
||||
case INSTRUMENT_QPSK_SLICER_OUTPUT:
|
||||
mQPSKSlicer.addListener( (DibitTap)tap );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized tap: " +
|
||||
@@ -202,9 +190,9 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
@Override
|
||||
public void unregisterTap( Tap tap )
|
||||
{
|
||||
if( mCQPSKDemodulator != null )
|
||||
if( mLSMDemodulator != null )
|
||||
{
|
||||
mCQPSKDemodulator.unregisterTap( tap );
|
||||
mLSMDemodulator.unregisterTap( tap );
|
||||
}
|
||||
|
||||
switch( tap.getName() )
|
||||
@@ -213,13 +201,13 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
mStreamConverter.setListener( mAGC );
|
||||
break;
|
||||
case INSTRUMENT_AGC_OUTPUT:
|
||||
mAGC.setListener( mCQPSKDemodulator );
|
||||
mAGC.setListener( mLSMDemodulator );
|
||||
break;
|
||||
case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT:
|
||||
mCQPSKDemodulator.setSymbolListener( mCQPSKSlicer );
|
||||
case INSTRUMENT_LSM_DEMODULATOR_OUTPUT:
|
||||
mLSMDemodulator.setSymbolListener( mQPSKSlicer );
|
||||
break;
|
||||
case INSTRUMENT_CQPSK_SLICER_OUTPUT:
|
||||
mCQPSKSlicer.removeListener( (DibitTap)tap );
|
||||
case INSTRUMENT_QPSK_SLICER_OUTPUT:
|
||||
mQPSKSlicer.removeListener( (DibitTap)tap );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized tap: " +
|
||||
@@ -235,7 +223,7 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package module.decode.p25.audio;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import jmbe.iface.AudioConversionLibrary;
|
||||
import jmbe.iface.AudioConverter;
|
||||
import message.IMessageListener;
|
||||
@@ -21,7 +23,6 @@ import audio.squelch.ISquelchStateListener;
|
||||
import audio.squelch.SquelchState;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.IChannelEventListener;
|
||||
import dsp.filter.iir.DeemphasisFilter;
|
||||
import dsp.gain.NonClippingGain;
|
||||
|
||||
public class P25AudioModule extends Module implements Listener<Message>,
|
||||
@@ -78,7 +79,7 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
|
||||
}
|
||||
@@ -232,10 +233,10 @@ public class P25AudioModule extends Module implements Listener<Message>,
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case CHANNEL_STATE_RESET:
|
||||
case NOTIFICATION_STATE_RESET:
|
||||
mAudioMetadata.reset();
|
||||
break;
|
||||
case CHANGE_SELECTED:
|
||||
case NOTIFICATION_SELECTION_CHANGE:
|
||||
mAudioMetadata.setSelected( event.getChannel().isSelected() );
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -86,7 +86,6 @@ public class P25Message extends Message
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
sb.append( " DATA UNIT ID:" + mMessage.getInt( DUID ) );
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -7,15 +7,9 @@ import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcast extends LDU1Message
|
||||
implements IdentifierReceiver, IAdjacentSite
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540,
|
||||
541,546,547 };
|
||||
|
||||
@@ -6,15 +6,9 @@ import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
|
||||
implements IdentifierReceiver, IAdjacentSite
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 376,377,382,383 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 384,385,386,387,536,537,538,
|
||||
|
||||
@@ -3,13 +3,8 @@ package module.decode.p25.message.ldu.lc;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallAlert extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( CallAlert.class );
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
|
||||
@@ -3,13 +3,8 @@ package module.decode.p25.message.ldu.lc;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallTermination extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
|
||||
@@ -4,15 +4,9 @@ import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdate extends LDU1Message
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 364,365,366,367 };
|
||||
public static final int[] BANDWIDTH = { 372,373,374,375,376,377,382,383,384 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 385,386,387,536,537,538,539,
|
||||
|
||||
@@ -4,15 +4,9 @@ import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdateExplicit extends LDU1Message
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdateExplicit.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 364,365,366,367 };
|
||||
public static final int[] BANDWIDTH = { 372,373,374,375 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 376,377,382,383,384,385,386,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package module.decode.p25.message.pdu;
|
||||
|
||||
import module.decode.p25.message.pdu.confirmed.PacketData;
|
||||
import module.decode.p25.message.pdu.osp.control.AdjacentStatusBroadcastExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.CallAlertExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.GroupAffiliationQueryExtended;
|
||||
@@ -122,8 +121,7 @@ public class PDUMessageFactory
|
||||
}
|
||||
|
||||
return new PDUMessage( message, duid, aliasList );
|
||||
case PACKET_DATA:
|
||||
return new PacketData( message, aliasList );
|
||||
|
||||
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
|
||||
return new PDUMessage( message, duid, aliasList );
|
||||
default:
|
||||
|
||||
@@ -3,7 +3,6 @@ package module.decode.p25.message.pdu.confirmed;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class PDUConfirmedMessageFactory
|
||||
{
|
||||
public final static Logger mLog =
|
||||
@@ -52,7 +51,7 @@ public class PDUConfirmedMessageFactory
|
||||
return new SNDCPActivateTDSContextAccept( message );
|
||||
case SNDCP_ACTIVATE_TDS_CONTEXT_REJECT:
|
||||
return new SNDCPActivateTDSContextReject( message );
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
case SNDCP_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
return new SNDCPActivateTDSContextRequest( message );
|
||||
case SNDCP_DEACTIVATE_TDS_CONTEXT_ACCEPT:
|
||||
case SNDCP_DEACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
@@ -61,14 +60,6 @@ public class PDUConfirmedMessageFactory
|
||||
return new SNDCPUserData( message );
|
||||
case SNDCP_RF_UNCONFIRMED_DATA:
|
||||
break;
|
||||
case PDU_TYPE_6:
|
||||
case PDU_TYPE_7:
|
||||
case PDU_TYPE_8:
|
||||
case PDU_TYPE_9:
|
||||
case PDU_TYPE_10:
|
||||
case PDU_TYPE_11:
|
||||
return new PDUTypeUnknown( message );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package module.decode.p25.message.tdu;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
@@ -18,7 +36,7 @@ public class TDUMessage extends P25Message
|
||||
mCRC = new CRC[ 1 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
|
||||
@@ -5,17 +5,10 @@ import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
|
||||
implements IdentifierReceiver, IAdjacentSite
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,
|
||||
116,117,118,119 };
|
||||
|
||||
@@ -5,15 +5,9 @@ import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
|
||||
implements IdentifierReceiver, IAdjacentSite
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 92,93,94,95 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 96,97,98,99,112,113,114,115,
|
||||
|
||||
@@ -2,13 +2,8 @@ package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallAlert extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( CallAlert.class );
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
|
||||
@@ -2,13 +2,8 @@ package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallTermination extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
|
||||
@@ -3,15 +3,9 @@ package module.decode.p25.message.tdu.lc;
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdate extends TDULinkControlMessage
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 72,73,74,75 };
|
||||
public static final int[] BANDWIDTH = { 88,89,90,91,92,93,94,95,96 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 97,98,99,112,113,114,115,116,
|
||||
|
||||
@@ -3,15 +3,9 @@ package module.decode.p25.message.tdu.lc;
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdateExplicit extends TDULinkControlMessage
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdateExplicit.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 72,73,74,75 };
|
||||
public static final int[] BANDWIDTH = { 88,89,90,91 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 92,93,94,95,96,97,98,99,112,
|
||||
|
||||
@@ -78,93 +78,67 @@ public class TSBKMessageFactory
|
||||
switch( opcode )
|
||||
{
|
||||
case ACKNOWLEDGE_RESPONSE:
|
||||
return new AcknowledgeResponse( message, duid,
|
||||
aliasList );
|
||||
return new AcknowledgeResponse( message, duid, aliasList );
|
||||
case ADJACENT_STATUS_BROADCAST:
|
||||
return new AdjacentStatusBroadcast( message, duid,
|
||||
aliasList );
|
||||
return new AdjacentStatusBroadcast( message, duid, aliasList );
|
||||
case AUTHENTICATION_COMMAND:
|
||||
return new AuthenticationCommand( message, duid,
|
||||
aliasList );
|
||||
return new AuthenticationCommand( message, duid, aliasList );
|
||||
case CALL_ALERT:
|
||||
return new CallAlert( message, duid, aliasList );
|
||||
case DENY_RESPONSE:
|
||||
return new DenyResponse( message, duid, aliasList );
|
||||
case EXTENDED_FUNCTION_COMMAND:
|
||||
return new ExtendedFunctionCommand( message, duid,
|
||||
aliasList );
|
||||
return new ExtendedFunctionCommand( message, duid, aliasList );
|
||||
case GROUP_AFFILIATION_QUERY:
|
||||
return new GroupAffiliationQuery( message, duid,
|
||||
aliasList );
|
||||
return new GroupAffiliationQuery( message, duid, aliasList );
|
||||
case GROUP_AFFILIATION_RESPONSE:
|
||||
return new GroupAffiliationResponse( message, duid,
|
||||
aliasList );
|
||||
return new GroupAffiliationResponse( message, duid, aliasList );
|
||||
case GROUP_DATA_CHANNEL_ANNOUNCEMENT:
|
||||
return new GroupDataChannelAnnouncement( message, duid,
|
||||
aliasList );
|
||||
return new GroupDataChannelAnnouncement( message, duid, aliasList );
|
||||
case GROUP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
|
||||
return new GroupDataChannelAnnouncementExplicit(
|
||||
message, duid, aliasList );
|
||||
return new GroupDataChannelAnnouncementExplicit( message, duid, aliasList );
|
||||
case GROUP_DATA_CHANNEL_GRANT:
|
||||
return new GroupDataChannelGrant( message, duid,
|
||||
aliasList );
|
||||
return new GroupDataChannelGrant( message, duid, aliasList );
|
||||
case GROUP_VOICE_CHANNEL_GRANT:
|
||||
return new GroupVoiceChannelGrant( message, duid,
|
||||
aliasList );
|
||||
return new GroupVoiceChannelGrant( message, duid, aliasList );
|
||||
case GROUP_VOICE_CHANNEL_GRANT_UPDATE:
|
||||
return new GroupVoiceChannelGrantUpdate( message, duid,
|
||||
aliasList );
|
||||
return new GroupVoiceChannelGrantUpdate( message, duid, aliasList );
|
||||
case GROUP_VOICE_CHANNEL_GRANT_UPDATE_EXPLICIT:
|
||||
return new GroupVoiceChannelGrantUpdateExplicit( message,
|
||||
duid, aliasList );
|
||||
return new GroupVoiceChannelGrantUpdateExplicit( message, duid, aliasList );
|
||||
case IDENTIFIER_UPDATE_NON_VUHF:
|
||||
return new IdentifierUpdateNonVUHF( message, duid,
|
||||
aliasList );
|
||||
return new IdentifierUpdateNonVUHF( message, duid, aliasList );
|
||||
case IDENTIFIER_UPDATE_TDMA:
|
||||
return new IdentifierUpdateTDMA( message, duid, aliasList );
|
||||
case IDENTIFIER_UPDATE_VHF_UHF_BANDS:
|
||||
return new IdentifierUpdateVUHF( message, duid,
|
||||
aliasList );
|
||||
return new IdentifierUpdateVUHF( message, duid, aliasList );
|
||||
case INDIVIDUAL_DATA_CHANNEL_GRANT:
|
||||
return new IndividualDataChannelGrant( message, duid,
|
||||
aliasList );
|
||||
return new IndividualDataChannelGrant( message, duid, aliasList );
|
||||
case LOCATION_REGISTRATION_RESPONSE:
|
||||
return new LocationRegistrationResponse( message, duid,
|
||||
aliasList );
|
||||
return new LocationRegistrationResponse( message, duid, aliasList );
|
||||
case MESSAGE_UPDATE:
|
||||
return new MessageUpdate( message, duid, aliasList );
|
||||
case NETWORK_STATUS_BROADCAST:
|
||||
return new NetworkStatusBroadcast( message, duid,
|
||||
aliasList );
|
||||
return new NetworkStatusBroadcast( message, duid, aliasList );
|
||||
case QUEUED_RESPONSE:
|
||||
return new QueuedResponse( message, duid, aliasList );
|
||||
case PROTECTION_PARAMETER_UPDATE:
|
||||
return new ProtectionParameterUpdate( message, duid,
|
||||
aliasList );
|
||||
return new ProtectionParameterUpdate( message, duid, aliasList );
|
||||
case RADIO_UNIT_MONITOR_COMMAND:
|
||||
return new RadioUnitMonitorCommand( message, duid,
|
||||
aliasList );
|
||||
return new RadioUnitMonitorCommand( message, duid, aliasList );
|
||||
case RFSS_STATUS_BROADCAST:
|
||||
return new RFSSStatusBroadcast( message, duid,
|
||||
aliasList );
|
||||
return new RFSSStatusBroadcast( message, duid, aliasList );
|
||||
case ROAMING_ADDRESS_COMMAND:
|
||||
return new RoamingAddressCommand( message, duid,
|
||||
aliasList );
|
||||
return new RoamingAddressCommand( message, duid, aliasList );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
|
||||
return new SecondaryControlChannelBroadcast( message,
|
||||
duid, aliasList );
|
||||
return new SecondaryControlChannelBroadcast( message, duid, aliasList );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
return new SecondaryControlChannelBroadcastExplicit(
|
||||
message, duid, aliasList );
|
||||
return new SecondaryControlChannelBroadcastExplicit( message, duid, aliasList );
|
||||
case SNDCP_DATA_CHANNEL_GRANT:
|
||||
return new SNDCPDataChannelGrant( message, duid,
|
||||
aliasList );
|
||||
return new SNDCPDataChannelGrant( message, duid, aliasList );
|
||||
case SNDCP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
|
||||
return new SNDCPDataChannelAnnouncementExplicit(
|
||||
message, duid, aliasList );
|
||||
return new SNDCPDataChannelAnnouncementExplicit( message, duid, aliasList );
|
||||
case SNDCP_DATA_PAGE_REQUEST:
|
||||
return new SNDCPDataPageRequest( message, duid,
|
||||
aliasList );
|
||||
return new SNDCPDataPageRequest( message, duid, aliasList );
|
||||
case STATUS_QUERY:
|
||||
return new StatusQuery( message, duid, aliasList );
|
||||
case STATUS_UPDATE:
|
||||
@@ -172,35 +146,25 @@ public class TSBKMessageFactory
|
||||
case TDMA_SYNC_BROADCAST:
|
||||
return new SyncBroadcast( message, duid, aliasList );
|
||||
case SYSTEM_SERVICE_BROADCAST:
|
||||
return new SystemServiceBroadcast( message, duid,
|
||||
aliasList );
|
||||
return new SystemServiceBroadcast( message, duid, aliasList );
|
||||
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
|
||||
return new TelephoneInterconnectAnswerRequest(
|
||||
message, duid, aliasList );
|
||||
return new TelephoneInterconnectAnswerRequest( message, duid, aliasList );
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
|
||||
return new TelephoneInterconnectVoiceChannelGrant(
|
||||
message, duid, aliasList );
|
||||
return new TelephoneInterconnectVoiceChannelGrant( message, duid, aliasList );
|
||||
case TIME_DATE_ANNOUNCEMENT:
|
||||
return new TimeAndDateAnnouncement( message, duid,
|
||||
aliasList );
|
||||
return new TimeAndDateAnnouncement( message, duid, aliasList );
|
||||
case UNIT_DEREGISTRATION_ACKNOWLEDGE:
|
||||
return new UnitDeregistrationAcknowledge( message,
|
||||
duid, aliasList );
|
||||
return new UnitDeregistrationAcknowledge( message, duid, aliasList );
|
||||
case UNIT_REGISTRATION_COMMAND:
|
||||
return new UnitRegistrationCommand( message, duid,
|
||||
aliasList );
|
||||
return new UnitRegistrationCommand( message, duid, aliasList );
|
||||
case UNIT_REGISTRATION_RESPONSE:
|
||||
return new UnitRegistrationResponse( message, duid,
|
||||
aliasList );
|
||||
return new UnitRegistrationResponse( message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
return new UnitToUnitAnswerRequest( message, duid,
|
||||
aliasList );
|
||||
return new UnitToUnitAnswerRequest( message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
|
||||
return new UnitToUnitVoiceChannelGrant( message,
|
||||
duid, aliasList );
|
||||
return new UnitToUnitVoiceChannelGrant( message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
|
||||
return new UnitToUnitVoiceChannelGrantUpdate( message,
|
||||
duid, aliasList );
|
||||
return new UnitToUnitVoiceChannelGrantUpdate( message, duid, aliasList );
|
||||
default:
|
||||
return new TSBKMessage( message, duid, aliasList );
|
||||
}
|
||||
@@ -235,4 +199,4 @@ public class TSBKMessageFactory
|
||||
return new TSBKMessage( message, duid, aliasList );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,4 +156,4 @@ public class IdentifierUpdateTDMA extends IdentifierUpdate
|
||||
{
|
||||
HALF_RATE, FULL_RATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,4 +271,4 @@ public class SyncBroadcast extends TSBKMessage
|
||||
{
|
||||
return mMessage.getInt( MICRO_SLOTS );
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/module/decode/p25/message/vselp/VSELP1Message.java
Normal file
42
src/module/decode/p25/message/vselp/VSELP1Message.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package module.decode.p25.message.vselp;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class VSELP1Message extends P25Message
|
||||
{
|
||||
/**
|
||||
* Motorola VSELP audio message 1.
|
||||
*
|
||||
* @param message
|
||||
* @param duid
|
||||
* @param aliasList
|
||||
*/
|
||||
public VSELP1Message( BinaryMessage message, DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "VSELP 1 VOICE FRAME" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
42
src/module/decode/p25/message/vselp/VSELP2Message.java
Normal file
42
src/module/decode/p25/message/vselp/VSELP2Message.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package module.decode.p25.message.vselp;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
|
||||
public class VSELP2Message extends P25Message
|
||||
{
|
||||
/**
|
||||
* Motorola VSELP audio message 1.
|
||||
*
|
||||
* @param message
|
||||
* @param duid
|
||||
* @param aliasList
|
||||
*/
|
||||
public VSELP2Message( BinaryMessage message, DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "VSELP 2 VOICE FRAME" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public enum DataUnitID
|
||||
TSBK1( 7, 260, false, "TSBK1", "Trunking Signaling Block" ),
|
||||
TSBK2( 7, 260, false, "TSBK2", "Trunking Signaling Block" ),
|
||||
TSBK3( 7, 260, false, "TSBK3", "Trunking Signaling Block" ),
|
||||
VSELP2( 9, 1680, false, "VSEL1", "Motorola VSELP Unit 1" ),
|
||||
VSELP2( 9, 1680, false, "VSEL2", "Motorola VSELP Unit 2" ),
|
||||
LDU2 ( 10, 1632, true, "LDU2 ", "Logical Link Data Unit 2" ),
|
||||
PDU0 ( 12, 260, false, "PDU0 ", "Packet Header Data Unit" ),
|
||||
PDU1 ( 12, 356, false, "PDU1 ", "Packet Data Unit-Unconfirmed" ),
|
||||
@@ -75,8 +75,12 @@ public enum DataUnitID
|
||||
return TDU;
|
||||
case 5:
|
||||
return LDU1;
|
||||
case 6:
|
||||
return VSELP1;
|
||||
case 7:
|
||||
return TSBK1;
|
||||
case 9:
|
||||
return VSELP2;
|
||||
case 10:
|
||||
return LDU2;
|
||||
case 12:
|
||||
|
||||
@@ -17,7 +17,7 @@ public enum PDUType
|
||||
PDU_TYPE_11( "PDU TYPE 11 UNKNOWN", 11 ),
|
||||
|
||||
/* Inbound */
|
||||
SN_ACTIVATE_TDS_CONTEXT_REQUEST( "SN-ACTIVATE TDS CONTEXT REQUEST", 0 ),
|
||||
SNDCP_ACTIVATE_TDS_CONTEXT_REQUEST( "SNDCP-ACTIVATE TDS CONTEXT REQUEST", 0 ),
|
||||
|
||||
UNKNOWN( "UNKNOWN", -1 );
|
||||
|
||||
@@ -48,9 +48,9 @@ public enum PDUType
|
||||
}
|
||||
else if( value == 0 && !outbound )
|
||||
{
|
||||
return SN_ACTIVATE_TDS_CONTEXT_REQUEST;
|
||||
return SNDCP_ACTIVATE_TDS_CONTEXT_REQUEST;
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package module.decode.p25.reference;
|
||||
|
||||
public enum ServiceAccessPoint
|
||||
{
|
||||
UNENCRYPTED_USER_DATA( "UNENCRYPTED USER DATA", 0 ),
|
||||
UNENCRYPTED_USER_DATA( "USER DATA", 0 ),
|
||||
ENCRYPTED_USER_DATA( "ENCRYPTED USER DATA", 1 ),
|
||||
CIRCUIT_DATA( "CIRCUIT DATA", 2 ),
|
||||
CIRCUIT_DATA_CONTROL( "CIRCUIT DATA CONTROL", 3 ),
|
||||
|
||||
@@ -23,12 +23,13 @@ import instrument.tap.TapGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IUnFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
@@ -36,7 +37,7 @@ import bits.SyncPattern;
|
||||
import dsp.fsk.LTRFSKDecoder;
|
||||
|
||||
public class PassportDecoder extends Decoder
|
||||
implements IRealBufferListener, Instrumentable
|
||||
implements IUnFilteredRealBufferListener, Instrumentable
|
||||
{
|
||||
public static final int PASSPORT_MESSAGE_LENGTH = 68;
|
||||
public static final int PASSPORT_SYNC_LENGTH = 9;
|
||||
@@ -47,8 +48,11 @@ public class PassportDecoder extends Decoder
|
||||
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
|
||||
public PassportDecoder( DecodeConfiguration config,
|
||||
AliasList aliasList )
|
||||
/**
|
||||
* Passport Decoder. Decodes unfiltered (e.g. demodulated but with no DC or
|
||||
* audio filtering) samples and produces Passport messages.
|
||||
*/
|
||||
public PassportDecoder( DecodeConfiguration config, AliasList aliasList )
|
||||
{
|
||||
mPassportFSKDecoder = new LTRFSKDecoder();
|
||||
|
||||
@@ -60,11 +64,11 @@ public class PassportDecoder extends Decoder
|
||||
|
||||
mPassportMessageProcessor = new PassportMessageProcessor( aliasList );
|
||||
mPassportMessageFramer.addMessageListener( mPassportMessageProcessor );
|
||||
mPassportMessageProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mPassportMessageProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getUnFilteredRealBufferListener()
|
||||
{
|
||||
return mPassportFSKDecoder;
|
||||
}
|
||||
@@ -107,7 +111,7 @@ public class PassportDecoder extends Decoder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
159
src/module/decode/passport/PassportDecoderEditor.java
Normal file
159
src/module/decode/passport/PassportDecoderEditor.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.passport;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EditorValidationException;
|
||||
import gui.editor.ValidatingEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class PassportDecoderEditor extends ValidatingEditor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAFC;
|
||||
private JSlider mAFCMaximumCorrection;
|
||||
|
||||
public PassportDecoderEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) );
|
||||
|
||||
mAFC = new JCheckBox( "AFC: 3000 Hz" );
|
||||
mAFC.setEnabled( false );
|
||||
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
|
||||
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
|
||||
mAFC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
setModified( true );
|
||||
|
||||
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( true );
|
||||
}
|
||||
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
|
||||
{
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mAFC );
|
||||
|
||||
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
|
||||
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
|
||||
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
|
||||
mAFCMaximumCorrection.setPaintTicks( true );
|
||||
|
||||
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mAFCMaximumCorrection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate( Editor<Channel> editor ) throws EditorValidationException
|
||||
{
|
||||
//No validation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
DecodeConfigPassport passport = new DecodeConfigPassport();
|
||||
|
||||
passport.setAFC( mAFC.isSelected() );
|
||||
passport.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
|
||||
|
||||
getItem().setDecodeConfiguration( passport );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mAFC.isEnabled() != enabled )
|
||||
{
|
||||
mAFC.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
DecodeConfiguration config = getItem().getDecodeConfiguration();
|
||||
|
||||
if( config instanceof DecodeConfigPassport )
|
||||
{
|
||||
DecodeConfigPassport passport = (DecodeConfigPassport)config;
|
||||
|
||||
mAFC.setSelected( passport.isAFCEnabled() );
|
||||
mAFCMaximumCorrection.setValue( passport.getAFCMaximumCorrection() );
|
||||
mAFCMaximumCorrection.setEnabled( passport.isAFCEnabled() );
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mAFC.setSelected( false );
|
||||
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
|
||||
mAFCMaximumCorrection.setEnabled( false );
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
@@ -75,7 +76,7 @@ public class PassportDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.passport;
|
||||
|
||||
import module.decode.DecodeEditor;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
|
||||
public class PassportEditor extends DecodeEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PassportEditor( DecodeConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,11 @@
|
||||
******************************************************************************/
|
||||
package module.decode.state;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.DecoderType;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
|
||||
@@ -33,9 +31,6 @@ import audio.metadata.MetadataType;
|
||||
*/
|
||||
public class AlwaysUnsquelchedDecoderState extends DecoderState
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AlwaysUnsquelchedDecoderState.class );
|
||||
|
||||
private DecoderType mDecoderType;
|
||||
private String mChannelName;
|
||||
|
||||
@@ -90,7 +85,7 @@ public class AlwaysUnsquelchedDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
broadcast( new Metadata( MetadataType.TO, mChannelName, false ) );
|
||||
broadcast( new DecoderStateEvent( this, Event.ALWAYS_UNSQUELCH, State.IDLE ) );
|
||||
|
||||
@@ -26,4 +26,4 @@ public class ChangeChannelTimeoutEvent extends DecoderStateEvent
|
||||
{
|
||||
return mCallTimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package module.decode.state;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import playlist.PlaylistManager;
|
||||
import settings.SettingsManager;
|
||||
import controller.channel.Channel;
|
||||
|
||||
/**
|
||||
* Channel Collection assembles a primary channel panel and any related decoder
|
||||
* state panels, provides contextual access to the channel and supports channel
|
||||
* selection.
|
||||
*/
|
||||
public class ChannelCollectionPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ChannelCollectionPanel.class );
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
private List<ChannelStatePanel> mChannelPanels = new ArrayList<ChannelStatePanel>();
|
||||
|
||||
public ChannelCollectionPanel( PlaylistManager playlistManager,
|
||||
SettingsManager settingsManager,
|
||||
Channel channel )
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mSettingsManager = settingsManager;
|
||||
|
||||
init( channel );
|
||||
}
|
||||
|
||||
protected void init( Channel channel )
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]0[]") );
|
||||
|
||||
setOpaque( false );
|
||||
|
||||
ChannelStatePanel csp = new ChannelStatePanel( mPlaylistManager,
|
||||
mSettingsManager, channel );
|
||||
|
||||
mChannelPanels.add( csp );
|
||||
|
||||
add( csp, "span,grow" );
|
||||
|
||||
}
|
||||
|
||||
public Channel getChannel()
|
||||
{
|
||||
if( mChannelPanels.size() >= 1 )
|
||||
{
|
||||
return mChannelPanels.get( 0 ).getChannel();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
for( ChannelStatePanel panel: mChannelPanels )
|
||||
{
|
||||
panel.dispose();
|
||||
}
|
||||
|
||||
mChannelPanels.clear();
|
||||
|
||||
mPlaylistManager = null;
|
||||
mSettingsManager = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the selection state of the channel if it matches the channel
|
||||
* argument. Otherwise, sets the selection state to false.
|
||||
*/
|
||||
public void setSelectedChannel( Channel channel )
|
||||
{
|
||||
for( ChannelStatePanel panel: mChannelPanels )
|
||||
{
|
||||
if( panel.getChannel() == channel )
|
||||
{
|
||||
/* Toggle the selection state */
|
||||
panel.getChannel().setSelected( !panel.getChannel().isSelected() );
|
||||
panel.repaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panel.getChannel().isSelected() )
|
||||
{
|
||||
panel.getChannel().setSelected( false );
|
||||
panel.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel represented by the channel panel at the gui point
|
||||
* location, to selecting the channel
|
||||
*
|
||||
* @param point - current location of the mouse
|
||||
*
|
||||
* @return - channel or null
|
||||
*/
|
||||
public Channel getChannelAt( Point point )
|
||||
{
|
||||
Component c = this.getComponentAt( point );
|
||||
|
||||
if( c instanceof ChannelCollectionPanel )
|
||||
{
|
||||
return ((ChannelCollectionPanel)c).getChannel();
|
||||
}
|
||||
else
|
||||
{
|
||||
return getChannel();
|
||||
}
|
||||
}
|
||||
|
||||
protected SettingsManager getSettingsManager()
|
||||
{
|
||||
return mSettingsManager;
|
||||
}
|
||||
|
||||
|
||||
public JMenu getContextMenu()
|
||||
{
|
||||
if( !mChannelPanels.isEmpty() )
|
||||
{
|
||||
return mChannelPanels.get( 0 ).getContextMenu();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package module.decode.state;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.Map;
|
||||
@@ -29,21 +28,19 @@ import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import playlist.PlaylistManager;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.ColorSettingMenuItem;
|
||||
import settings.ColorSettingResetMenuItem;
|
||||
import settings.SettingsManager;
|
||||
import audio.AudioPanel;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
|
||||
/**
|
||||
* Gui wrapper for the list of currently processing primary channels
|
||||
@@ -52,29 +49,37 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ChannelList.class );
|
||||
private Map<Channel,ChannelPanel> mDisplayedPanels = new ConcurrentHashMap<>();
|
||||
|
||||
private Map<Channel,ChannelCollectionPanel> mDisplayedPanels =
|
||||
new ConcurrentHashMap<Channel,ChannelCollectionPanel>();
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
private AudioPanel mAudioPanel;
|
||||
|
||||
public ChannelList( PlaylistManager playlistManager,
|
||||
SettingsManager settingsManager )
|
||||
public ChannelList( ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
SettingsManager settingsManager,
|
||||
AudioPanel audioPanel )
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mAudioPanel = audioPanel;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]") );
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 1", "[grow,fill]", "[]0[]") );
|
||||
setBackground( Color.BLACK );
|
||||
|
||||
addMouseListener( new ListSelectionListener() );
|
||||
|
||||
add( mAudioPanel );
|
||||
|
||||
JSeparator separator = new JSeparator( JSeparator.HORIZONTAL );
|
||||
add( separator );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,10 +87,10 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case CHANNEL_PROCESSING_STARTED:
|
||||
case NOTIFICATION_PROCESSING_START:
|
||||
addChannelPanel( event.getChannel() );
|
||||
break;
|
||||
case CHANNEL_PROCESSING_STOPPED:
|
||||
case NOTIFICATION_PROCESSING_STOP:
|
||||
removeChannelPanel( event.getChannel() );
|
||||
break;
|
||||
default:
|
||||
@@ -97,12 +102,12 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
if( !mDisplayedPanels.containsKey( channel ) )
|
||||
{
|
||||
ChannelCollectionPanel panel = new ChannelCollectionPanel(
|
||||
mPlaylistManager, mSettingsManager, channel );
|
||||
ChannelPanel channelPanel = new ChannelPanel( mChannelModel,
|
||||
mChannelProcessingManager, mSettingsManager, channel );
|
||||
|
||||
add( panel, "wrap" );
|
||||
add( channelPanel );
|
||||
|
||||
mDisplayedPanels.put( channel, panel );
|
||||
mDisplayedPanels.put( channel, channelPanel );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
@@ -113,7 +118,7 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
if( mDisplayedPanels.containsKey( channel ) )
|
||||
{
|
||||
ChannelCollectionPanel panel = mDisplayedPanels.remove( channel );
|
||||
ChannelPanel panel = mDisplayedPanels.remove( channel );
|
||||
|
||||
if( panel != null )
|
||||
{
|
||||
@@ -127,18 +132,6 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectedChannel( Channel channel )
|
||||
{
|
||||
synchronized( mDisplayedPanels )
|
||||
{
|
||||
/* Send channel selection to each channel panel */
|
||||
for( ChannelCollectionPanel panel: mDisplayedPanels.values() )
|
||||
{
|
||||
panel.setSelectedChannel( channel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ListSelectionListener implements MouseListener
|
||||
{
|
||||
@Override
|
||||
@@ -146,18 +139,22 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
{
|
||||
Component component = getComponentAt( e.getPoint() );
|
||||
|
||||
if( component instanceof ChannelCollectionPanel )
|
||||
if( component instanceof ChannelPanel )
|
||||
{
|
||||
ChannelCollectionPanel panel = (ChannelCollectionPanel)component;
|
||||
ChannelPanel panel = (ChannelPanel)component;
|
||||
|
||||
Point translatedPoint = SwingUtilities
|
||||
.convertPoint( e.getComponent(), e.getPoint(), panel );
|
||||
|
||||
Channel channel = panel.getChannelAt( translatedPoint );
|
||||
Channel channel = panel.getChannel();
|
||||
|
||||
if( e.getButton() == MouseEvent.BUTTON1 )
|
||||
{
|
||||
setSelectedChannel( channel );
|
||||
if( channel.isSelected() )
|
||||
{
|
||||
mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_DESELECT ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_SELECT ) );
|
||||
}
|
||||
}
|
||||
else if( e.getButton() == MouseEvent.BUTTON3 )
|
||||
{
|
||||
@@ -254,6 +251,20 @@ public class ChannelList extends JPanel implements ChannelEventListener
|
||||
idleMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_IDLE ) );
|
||||
|
||||
JMenu noTunerMenu = new JMenu( "No Tuner" );
|
||||
channelsMenu.add( noTunerMenu );
|
||||
|
||||
noTunerMenu.add( new ColorSettingMenuItem( mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER ) );
|
||||
noTunerMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER ) );
|
||||
noTunerMenu.add( new JSeparator() );
|
||||
|
||||
noTunerMenu.add( new ColorSettingMenuItem( mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER ) );
|
||||
noTunerMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
|
||||
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER ) );
|
||||
|
||||
JMenu labelMenu = new JMenu( "Labels" );
|
||||
colorMenu.add( labelMenu );
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import module.ProcessingChain;
|
||||
import module.decode.DecoderFactory;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelUtils;
|
||||
import module.decode.DecoderFactory;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import playlist.PlaylistManager;
|
||||
import record.RecorderType;
|
||||
import record.config.RecordConfiguration;
|
||||
import sample.Listener;
|
||||
@@ -30,17 +29,22 @@ import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import settings.SettingsManager;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelEventListener;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.ChannelUtils;
|
||||
|
||||
public class ChannelStatePanel extends JPanel
|
||||
implements Listener<ChangedAttribute>, SettingChangeListener
|
||||
public class ChannelPanel extends JPanel
|
||||
implements Listener<ChangedAttribute>,
|
||||
SettingChangeListener,
|
||||
ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ChannelStatePanel.class );
|
||||
|
||||
private static final boolean ENABLED = true;
|
||||
private static final boolean DISABLED = false;
|
||||
private static final boolean BROADCAST_CHANGE = true;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ChannelPanel.class );
|
||||
|
||||
private Font mFontDetails = new Font( Font.MONOSPACED, Font.PLAIN, 12 );
|
||||
private Font mFontDecoder = new Font( Font.MONOSPACED, Font.PLAIN, 12 );
|
||||
@@ -71,11 +75,13 @@ public class ChannelStatePanel extends JPanel
|
||||
private JLabel mSiteLabel;
|
||||
private JLabel mChannelLabel;
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
protected SettingsManager mSettingsManager;
|
||||
|
||||
private Channel mChannel;
|
||||
private ChannelState mChannelState;
|
||||
private List<DecoderPanel> mDecoderPanels = new ArrayList<>();
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
/**
|
||||
* Gui component to a channel state. Provides System, Site and channel
|
||||
@@ -83,26 +89,40 @@ public class ChannelStatePanel extends JPanel
|
||||
*
|
||||
* Updates color background according to current channel state.
|
||||
*/
|
||||
public ChannelStatePanel( PlaylistManager playlistManager,
|
||||
SettingsManager settingsManager,
|
||||
Channel channel )
|
||||
public ChannelPanel( ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
SettingsManager settingsManager,
|
||||
Channel channel )
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mSettingsManager.addListener( this );
|
||||
|
||||
mChannel = channel;
|
||||
mChannel.getChannelState().setChangedAttributeListener( this );
|
||||
|
||||
init();
|
||||
ProcessingChain processingChain =
|
||||
channelProcessingManager.getProcessingChain( mChannel );
|
||||
|
||||
for( DecoderState decoderState: getChannel().getProcessingChain().getDecoderStates() )
|
||||
{
|
||||
DecoderPanel panel = DecoderFactory.getDecoderPanel( mSettingsManager, decoderState );
|
||||
mDecoderPanels.add( panel );
|
||||
add( panel, "grow,span" );
|
||||
}
|
||||
if( processingChain != null )
|
||||
{
|
||||
mChannelState = processingChain.getChannelState();
|
||||
|
||||
init();
|
||||
|
||||
for( DecoderState decoderState: processingChain.getDecoderStates() )
|
||||
{
|
||||
DecoderPanel panel = DecoderFactory.getDecoderPanel( mSettingsManager, decoderState );
|
||||
mDecoderPanels.add( panel );
|
||||
add( panel, "grow,span" );
|
||||
}
|
||||
|
||||
mChannelState.setChangedAttributeListener( this );
|
||||
mChannelModel.addListener( this );
|
||||
mSettingsManager.addListener( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "Processing Chain was null!" );
|
||||
}
|
||||
}
|
||||
|
||||
private void init()
|
||||
@@ -111,12 +131,12 @@ public class ChannelStatePanel extends JPanel
|
||||
|
||||
setLayout( new MigLayout( "insets 1 1 1 1", "[grow,fill]", "[]0[]0[]") );
|
||||
|
||||
mSystemLabel = new JLabel( mChannel.getSystem().getName() );
|
||||
mSystemLabel = new JLabel( mChannel.getSystem() );
|
||||
mSystemLabel.setFont( mFontDetails );
|
||||
mSystemLabel.setForeground( mColorLabelDetails );
|
||||
add( mSystemLabel );
|
||||
|
||||
mSiteLabel = new JLabel( mChannel.getSite().getName() );
|
||||
mSiteLabel = new JLabel( mChannel.getSite() );
|
||||
mSiteLabel.setFont( mFontDetails );
|
||||
mSiteLabel.setForeground( mColorLabelDetails );
|
||||
add( mSiteLabel );
|
||||
@@ -126,8 +146,7 @@ public class ChannelStatePanel extends JPanel
|
||||
mChannelLabel.setForeground( mColorLabelDetails );
|
||||
add( mChannelLabel, "wrap" );
|
||||
|
||||
mStateLabel = new JLabel( mChannel.getChannelState().getState()
|
||||
.getDisplayValue() );
|
||||
mStateLabel = new JLabel( mChannelState.getState().getDisplayValue() );
|
||||
mStateLabel.setFont( mFontDecoder );
|
||||
mStateLabel.setForeground( mColorLabelDecoder );
|
||||
add( mStateLabel );
|
||||
@@ -161,8 +180,6 @@ public class ChannelStatePanel extends JPanel
|
||||
mOptionsLabel.setFont( mFontDetails );
|
||||
mOptionsLabel.setForeground( mColorLabelAuxDecoder );
|
||||
add( mOptionsLabel, "wrap" );
|
||||
|
||||
// add( new JSeparator( JSeparator.HORIZONTAL ), "span,growx" );
|
||||
}
|
||||
|
||||
public Channel getChannel()
|
||||
@@ -172,12 +189,16 @@ public class ChannelStatePanel extends JPanel
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mPlaylistManager = null;
|
||||
mChannelModel.removeListener( this );
|
||||
mChannelModel = null;
|
||||
|
||||
mChannelProcessingManager = null;
|
||||
|
||||
mSettingsManager.removeListener( this );
|
||||
mSettingsManager = null;
|
||||
|
||||
mChannel.getChannelState().removeChangedAttributeListener();
|
||||
mChannelState.removeChangedAttributeListener();
|
||||
mChannelState = null;
|
||||
mChannel = null;
|
||||
|
||||
for( DecoderPanel panel: mDecoderPanels )
|
||||
@@ -192,8 +213,6 @@ public class ChannelStatePanel extends JPanel
|
||||
@Override
|
||||
public void receive( final ChangedAttribute changedAttribute )
|
||||
{
|
||||
final ChannelState state = mChannel.getChannelState();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
@@ -202,9 +221,9 @@ public class ChannelStatePanel extends JPanel
|
||||
switch( changedAttribute )
|
||||
{
|
||||
case CHANNEL_STATE:
|
||||
if( state != null && state.getState() != null )
|
||||
if( mChannelState != null && mChannelState.getState() != null )
|
||||
{
|
||||
mStateLabel.setText( state.getState().getDisplayValue() );
|
||||
mStateLabel.setText( mChannelState.getState().getDisplayValue() );
|
||||
}
|
||||
break;
|
||||
case SOURCE:
|
||||
@@ -214,7 +233,7 @@ public class ChannelStatePanel extends JPanel
|
||||
case CHANNEL_NAME:
|
||||
case SITE_NAME:
|
||||
case SYSTEM_NAME:
|
||||
mChannelLabel.setText( mChannel.getChannelDisplayName() );
|
||||
mChannelLabel.setText( mChannel.toString() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -238,11 +257,9 @@ public class ChannelStatePanel extends JPanel
|
||||
|
||||
final Channel channel = mChannel;
|
||||
|
||||
final ChannelState channelState = ( channel == null ? null : channel.getChannelState() );
|
||||
|
||||
if( channelState != null )
|
||||
if( mChannelState != null )
|
||||
{
|
||||
switch( channelState.getState() )
|
||||
switch( mChannelState.getState() )
|
||||
{
|
||||
case CALL:
|
||||
p = getGradient( mColorTopCall, mColorMiddleCall );
|
||||
@@ -260,7 +277,7 @@ public class ChannelStatePanel extends JPanel
|
||||
default:
|
||||
p = getGradient( mColorTopIdle, mColorMiddleIdle );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( p == null )
|
||||
@@ -419,7 +436,17 @@ public class ChannelStatePanel extends JPanel
|
||||
|
||||
public JMenu getContextMenu()
|
||||
{
|
||||
return ChannelUtils.getContextMenu( mPlaylistManager, mChannel,
|
||||
ChannelStatePanel.this );
|
||||
return ChannelUtils.getContextMenu( mChannelModel, mChannelProcessingManager,
|
||||
mChannel, ChannelPanel.this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelChanged( ChannelEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
event.getChannel() == mChannel )
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,32 +18,30 @@
|
||||
package module.decode.state;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import module.Module;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import audio.metadata.IMetadataProvider;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataReset;
|
||||
import audio.metadata.MetadataType;
|
||||
import audio.squelch.ISquelchStateProvider;
|
||||
import audio.squelch.SquelchState;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import module.Module;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
import sample.Listener;
|
||||
|
||||
public class ChannelState extends Module implements ICallEventProvider,
|
||||
IChangedAttributeProvider, IDecoderStateEventListener,
|
||||
IDecoderStateEventProvider, IMetadataProvider, ISquelchStateProvider
|
||||
public class ChannelState extends Module implements ICallEventProvider, IChangedAttributeProvider,
|
||||
IDecoderStateEventListener, IDecoderStateEventProvider, IMetadataProvider, ISquelchStateProvider
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelState.class );
|
||||
@@ -65,19 +63,16 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
private boolean mSelected = false;
|
||||
|
||||
private long mStandardChannelFadeTimeout = FADE_TIMEOUT_DELAY;
|
||||
private long mTrafficChannelFadeTimeout =
|
||||
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS * 1000;
|
||||
private long mTrafficChannelFadeTimeout = DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS * 1000;
|
||||
private long mFadeTimeout;
|
||||
private long mEndTimeout;
|
||||
|
||||
private StateMonitor mStateMonitor = new StateMonitor();
|
||||
private AtomicBoolean mMonitoring = new AtomicBoolean();
|
||||
private ScheduledFuture<?> mStateMonitorFuture;
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ChannelType mChannelType;
|
||||
|
||||
private TrafficChannelStatusListener mTrafficChannelStatusListener;
|
||||
private TrafficChannelManager mTrafficChannelEndListener;
|
||||
private CallEvent mTrafficChannelCallEvent;
|
||||
|
||||
/**
|
||||
@@ -106,9 +101,8 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
* 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( ThreadPoolManager manager, ChannelType channelType )
|
||||
public ChannelState( ChannelType channelType )
|
||||
{
|
||||
mThreadPoolManager = manager;
|
||||
mChannelType = channelType;
|
||||
}
|
||||
|
||||
@@ -126,23 +120,22 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
//Start a monitoring task to check for FADE and END event timeouts
|
||||
if( mMonitoring.compareAndSet( false, true ) )
|
||||
if( mStateMonitorFuture == null && mStateMonitor != null )
|
||||
{
|
||||
if( mStateMonitorFuture == null && mStateMonitor != null )
|
||||
if( mTrafficChannelEndListener != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
mStateMonitorFuture = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.DECODER, mStateMonitor, 20, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
catch( RejectedExecutionException ree )
|
||||
{
|
||||
mLog.error( "state monitor scheduled task rejected", ree );
|
||||
mMonitoring.set( false );
|
||||
}
|
||||
setState( State.CALL );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mStateMonitorFuture = executor.scheduleAtFixedRate( mStateMonitor, 0, 20, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
catch( RejectedExecutionException ree )
|
||||
{
|
||||
mLog.error( "state monitor scheduled task rejected", ree );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,23 +143,29 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
mSquelchLocked = false;
|
||||
|
||||
//Shutdown the state montoring task
|
||||
if( mMonitoring.compareAndSet( true, false ) )
|
||||
if( mStateMonitorFuture != null )
|
||||
{
|
||||
if( mStateMonitorFuture != null )
|
||||
{
|
||||
boolean success = mThreadPoolManager.cancel( mStateMonitorFuture );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
mLog.error("Couldn't stop monitoring scheduled future" );
|
||||
}
|
||||
}
|
||||
boolean success = mStateMonitorFuture.cancel( true );
|
||||
|
||||
mStateMonitorFuture = null;
|
||||
if( !success )
|
||||
{
|
||||
mLog.error("Couldn't stop monitoring scheduled future" );
|
||||
}
|
||||
}
|
||||
|
||||
mTrafficChannelEndListener = null;
|
||||
|
||||
if( mTrafficChannelCallEvent != null )
|
||||
{
|
||||
mTrafficChannelCallEvent.end();
|
||||
broadcast( mTrafficChannelCallEvent );
|
||||
}
|
||||
|
||||
mTrafficChannelCallEvent = null;
|
||||
|
||||
mStateMonitorFuture = null;
|
||||
|
||||
mSquelchLocked = false;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -175,7 +174,6 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
mChangedAttributeListener = null;
|
||||
mDecoderStateListener = null;
|
||||
mSquelchStateListener = null;
|
||||
mThreadPoolManager = null;
|
||||
mStateMonitor = null;
|
||||
}
|
||||
|
||||
@@ -205,7 +203,7 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
{
|
||||
mFadeTimeout = mTrafficChannelFadeTimeout;
|
||||
mFadeTimeout = System.currentTimeMillis() + mTrafficChannelFadeTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +235,7 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
{
|
||||
mFadeTimeout = System.currentTimeMillis() + mStandardChannelFadeTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,23 +388,9 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
|
||||
if( mTrafficChannelCallEvent != null )
|
||||
if( mTrafficChannelEndListener != null )
|
||||
{
|
||||
mTrafficChannelCallEvent.end();
|
||||
|
||||
broadcast( mTrafficChannelCallEvent );
|
||||
mTrafficChannelCallEvent = null;
|
||||
}
|
||||
|
||||
if( mTrafficChannelStatusListener != null )
|
||||
{
|
||||
mTrafficChannelStatusListener.callEnd();
|
||||
mTrafficChannelStatusListener = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "Traffic channel status listener was null - couldn't "
|
||||
+ "teardown the channel");
|
||||
mTrafficChannelEndListener.callEnd( mTrafficChannelCallEvent.getChannel() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,11 +515,11 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
* 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( TrafficChannelStatusListener listener,
|
||||
TrafficChannelAllocationEvent allocationEvent )
|
||||
public void configureAsTrafficChannel( TrafficChannelManager manager, CallEvent callEvent )
|
||||
{
|
||||
mTrafficChannelStatusListener = listener;
|
||||
mTrafficChannelCallEvent = allocationEvent.getCallEvent();
|
||||
mTrafficChannelEndListener = manager;
|
||||
|
||||
mTrafficChannelCallEvent = callEvent;
|
||||
|
||||
/* Broadcast the call event details as metadata for the audio manager */
|
||||
String channel = mTrafficChannelCallEvent.getChannel();
|
||||
@@ -543,9 +528,9 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
{
|
||||
broadcast( new Metadata( MetadataType.CHANNEL_NUMBER, channel, true ) );
|
||||
}
|
||||
|
||||
|
||||
broadcast( new Metadata( MetadataType.PROTOCOL,
|
||||
mTrafficChannelCallEvent.getDecoderType().getDisplayString(), true ) );
|
||||
mTrafficChannelCallEvent.getDecoderType().getDisplayString(), true ) );
|
||||
|
||||
String details = mTrafficChannelCallEvent.getDetails();
|
||||
|
||||
@@ -574,13 +559,12 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
|
||||
if( frequency > 0 )
|
||||
{
|
||||
broadcast( new Metadata( MetadataType.FREQUENCY,
|
||||
String.valueOf( frequency ), true ) );
|
||||
broadcast( new Metadata( MetadataType.FREQUENCY, String.valueOf( frequency ), true ) );
|
||||
}
|
||||
|
||||
/* Rebroadcast the allocation event so that the internal decoder states
|
||||
* can self-configure with the call event details */
|
||||
broadcast( allocationEvent );
|
||||
broadcast( mTrafficChannelCallEvent );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -662,7 +646,6 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
if( State.CALL_STATES.contains( mState ) &&
|
||||
mFadeTimeout <= System.currentTimeMillis() )
|
||||
{
|
||||
mState = State.FADE;
|
||||
processFadeState();
|
||||
}
|
||||
else if( mState == State.FADE &&
|
||||
|
||||
@@ -7,10 +7,6 @@ import module.decode.DecoderType;
|
||||
import module.decode.event.ActivitySummaryProvider;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
@@ -33,8 +29,6 @@ public abstract class DecoderState extends Module
|
||||
IMessageListener,
|
||||
IMetadataProvider
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( DecoderState.class );
|
||||
|
||||
/* This has to be a broadcaster in order for references to persist */
|
||||
private Broadcaster<CallEvent> mCallEventBroadcaster = new Broadcaster<>();
|
||||
private Listener<ChangedAttribute> mChangedAttributeListener;
|
||||
|
||||
@@ -65,4 +65,4 @@ public class DecoderStateEvent
|
||||
START,
|
||||
TRAFFIC_CHANNEL_ALLOCATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,20 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.decode.state;
|
||||
|
||||
import java.util.EnumSet;
|
||||
@@ -86,11 +103,8 @@ public enum State
|
||||
|
||||
private String mDisplayValue;
|
||||
|
||||
public static final EnumSet<State> CALL_STATES =
|
||||
EnumSet.of( CALL, CONTROL, DATA, ENCRYPTED );
|
||||
|
||||
public static final EnumSet<State> IDLE_STATES =
|
||||
EnumSet.of( IDLE, FADE );
|
||||
public static final EnumSet<State> CALL_STATES = EnumSet.of( CALL, CONTROL, DATA, ENCRYPTED );
|
||||
public static final EnumSet<State> IDLE_STATES = EnumSet.of( IDLE, FADE );
|
||||
|
||||
private State( String displayValue )
|
||||
{
|
||||
@@ -103,4 +117,4 @@ public enum State
|
||||
{
|
||||
return mDisplayValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.Module;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
@@ -15,18 +16,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import record.config.RecordConfiguration;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannel.Type;
|
||||
import alias.Alias;
|
||||
import alias.priority.Priority;
|
||||
import controller.ResourceManager;
|
||||
import alias.id.priority.Priority;
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.site.Site;
|
||||
import controller.system.System;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
import controller.channel.TrafficChannelEvent;
|
||||
|
||||
public class TrafficChannelManager extends Module
|
||||
implements ICallEventProvider, IDecoderStateEventListener
|
||||
@@ -41,15 +43,14 @@ public class TrafficChannelManager extends Module
|
||||
private DecoderStateEventListener mEventListener = new DecoderStateEventListener();
|
||||
private Listener<CallEvent> mCallEventListener;
|
||||
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private DecodeConfiguration mDecodeConfiguration;
|
||||
private RecordConfiguration mRecordConfiguration;
|
||||
private ResourceManager mResourceManager;
|
||||
private System mSystem;
|
||||
private Site mSite;
|
||||
private String mSystem;
|
||||
private String mSite;
|
||||
private String mAliasListName;
|
||||
private long mTrafficChannelTimeout;
|
||||
private CallEvent mPreviousDoNotMonitorCallEvent;
|
||||
private boolean mShuttingDown = false;
|
||||
|
||||
/**
|
||||
* Monitors call events and allocates traffic decoder channels in response
|
||||
@@ -69,22 +70,23 @@ public class TrafficChannelManager extends Module
|
||||
* @param trafficChannelPoolSize - maximum number of allocated traffic channels
|
||||
* in the pool
|
||||
*/
|
||||
public TrafficChannelManager( ResourceManager resourceManager,
|
||||
public TrafficChannelManager( ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
DecodeConfiguration decodeConfiguration,
|
||||
RecordConfiguration recordConfiguration,
|
||||
System system,
|
||||
Site site,
|
||||
String system,
|
||||
String site,
|
||||
String aliasListName,
|
||||
long trafficChannelTimeout,
|
||||
int trafficChannelPoolSize )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mDecodeConfiguration = decodeConfiguration;
|
||||
mRecordConfiguration = recordConfiguration;
|
||||
mSystem = system;
|
||||
mSite = site;
|
||||
mAliasListName = aliasListName;
|
||||
mTrafficChannelTimeout = trafficChannelTimeout;
|
||||
mTrafficChannelPoolMaximumSize = trafficChannelPoolSize;
|
||||
}
|
||||
|
||||
@@ -93,14 +95,14 @@ public class TrafficChannelManager extends Module
|
||||
{
|
||||
for( Channel trafficChannel: mTrafficChannelPool )
|
||||
{
|
||||
trafficChannel.setEnabled( false );
|
||||
trafficChannel.dispose();
|
||||
mChannelModel.broadcast( new ChannelEvent( trafficChannel, Event.REQUEST_DISABLE ) );
|
||||
}
|
||||
|
||||
|
||||
mTrafficChannelPool.clear();
|
||||
|
||||
mTrafficChannelsInUse.clear();
|
||||
|
||||
mCallEventListener = null;
|
||||
mResourceManager = null;
|
||||
mDecodeConfiguration = null;
|
||||
mPreviousDoNotMonitorCallEvent = null;
|
||||
}
|
||||
@@ -124,7 +126,7 @@ public class TrafficChannelManager extends Module
|
||||
{
|
||||
for( Channel configuredChannel: mTrafficChannelPool )
|
||||
{
|
||||
if( !configuredChannel.isProcessing() )
|
||||
if( !configuredChannel.getEnabled() )
|
||||
{
|
||||
channel = configuredChannel;
|
||||
break;
|
||||
@@ -139,39 +141,22 @@ public class TrafficChannelManager extends Module
|
||||
|
||||
channel.setRecordConfiguration( mRecordConfiguration );
|
||||
|
||||
channel.setResourceManager( mResourceManager );
|
||||
|
||||
channel.setTrafficChannelTimeout( mTrafficChannelTimeout );
|
||||
|
||||
channel.setAliasListName( mAliasListName );
|
||||
|
||||
mChannelModel.addChannel( channel );
|
||||
|
||||
mTrafficChannelPool.add( channel );
|
||||
}
|
||||
|
||||
/* If we have a configured channel, start it and track it */
|
||||
/* If we have a configured channel, update metadata */
|
||||
if( channel != null )
|
||||
{
|
||||
channel.setSourceConfiguration( new SourceConfigTuner( tunerChannel ) );
|
||||
|
||||
channel.setSystem( mSystem, false );
|
||||
channel.setSite( mSite, false );
|
||||
channel.setSystem( mSystem );
|
||||
channel.setSite( mSite );
|
||||
channel.setName( channelNumber );
|
||||
|
||||
channel.setEnabled( true );
|
||||
|
||||
/* Check the channel obtained a source and is currently processing */
|
||||
if( channel.isProcessing() )
|
||||
{
|
||||
mTrafficChannelsInUse.put( channelNumber, channel );
|
||||
}
|
||||
else
|
||||
{
|
||||
channel.setEnabled( false );
|
||||
|
||||
channel.setSystem( mSystem, false );
|
||||
channel.setSite( mSite, false );
|
||||
channel.setName( "Traffic" );
|
||||
}
|
||||
mChannelModel.broadcast( new ChannelEvent( channel, Event.NOTIFICATION_CONFIGURATION_CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,33 +197,26 @@ public class TrafficChannelManager extends Module
|
||||
}
|
||||
else if( frequency > 0 )
|
||||
{
|
||||
Channel channel = getChannel( callEvent.getChannel(),
|
||||
new TunerChannel( Type.TRAFFIC, frequency,
|
||||
mDecodeConfiguration.getDecoderType()
|
||||
.getChannelBandwidth() ) );
|
||||
Channel channel = getChannel( callEvent.getChannel(), new TunerChannel( Type.TRAFFIC,
|
||||
frequency, mDecodeConfiguration.getDecoderType().getChannelBandwidth() ) );
|
||||
|
||||
if( channel != null )
|
||||
{
|
||||
if( channel.isProcessing() )
|
||||
TrafficChannelEvent trafficChannelEvent =
|
||||
new TrafficChannelEvent( this, channel, Event.REQUEST_ENABLE, callEvent );
|
||||
|
||||
//Request to enable the channel
|
||||
mChannelModel.broadcast( trafficChannelEvent );
|
||||
|
||||
if( channel.getEnabled() )
|
||||
{
|
||||
callEvent.setDetails( "TRAFFIC CHANNEL ALLOCATED" );
|
||||
|
||||
ChannelState state = channel.getChannelState();
|
||||
|
||||
/* Register as a listener to be notified when the call
|
||||
* is completed */
|
||||
state.configureAsTrafficChannel(
|
||||
new TrafficChannelStatusListener( this,
|
||||
callEvent.getChannel() ), event );
|
||||
|
||||
/* Set state to call so that audio squelch state is correct */
|
||||
state.setState( State.CALL );
|
||||
mTrafficChannelsInUse.put( callEvent.getChannel(), channel );
|
||||
}
|
||||
else
|
||||
{
|
||||
callEvent.setCallEventType( CallEventType.CALL_DETECT );
|
||||
callEvent.setDetails( "CHANNEL PROCESSING ERROR" );
|
||||
}
|
||||
callEvent.setDetails( "CHANNEL START REJECTED" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -325,7 +303,7 @@ public class TrafficChannelManager extends Module
|
||||
Alias to = event.getToIDAlias();
|
||||
|
||||
if( to != null &&
|
||||
to.hasPriority() &&
|
||||
to.hasCallPriority() &&
|
||||
to.getCallPriority() == Priority.DO_NOT_MONITOR )
|
||||
{
|
||||
return true;
|
||||
@@ -334,7 +312,7 @@ public class TrafficChannelManager extends Module
|
||||
Alias from = event.getFromIDAlias();
|
||||
|
||||
if( from != null &&
|
||||
from.hasPriority() &&
|
||||
from.hasCallPriority() &&
|
||||
from.getCallPriority() == Priority.DO_NOT_MONITOR )
|
||||
{
|
||||
return true;
|
||||
@@ -367,7 +345,7 @@ public class TrafficChannelManager extends Module
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -399,15 +377,13 @@ public class TrafficChannelManager extends Module
|
||||
{
|
||||
synchronized( mTrafficChannelsInUse )
|
||||
{
|
||||
if( channelNumber != null &&
|
||||
mTrafficChannelsInUse.containsKey( channelNumber ) )
|
||||
if( channelNumber != null && mTrafficChannelsInUse.containsKey( channelNumber ) )
|
||||
{
|
||||
Channel channel = mTrafficChannelsInUse.get( channelNumber );
|
||||
|
||||
mTrafficChannelsInUse.remove( channelNumber );
|
||||
|
||||
/* Disable the channel and broadcast a notification */
|
||||
channel.setEnabled( false, true );
|
||||
mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_DISABLE ) );
|
||||
|
||||
mTrafficChannelsInUse.remove( channelNumber );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package module.decode.state;
|
||||
|
||||
public class TrafficChannelStatusListener
|
||||
{
|
||||
private TrafficChannelManager mTrafficChannelManager;
|
||||
private String mChannelNumber;
|
||||
|
||||
public TrafficChannelStatusListener( TrafficChannelManager manager, String channelNumber )
|
||||
{
|
||||
mTrafficChannelManager = manager;
|
||||
mChannelNumber = channelNumber;
|
||||
}
|
||||
|
||||
public void callEnd()
|
||||
{
|
||||
if( mTrafficChannelManager != null )
|
||||
{
|
||||
mTrafficChannelManager.callEnd( mChannelNumber );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,13 @@ import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import alias.AliasList;
|
||||
import bits.MessageFramer;
|
||||
@@ -45,7 +46,7 @@ import dsp.fsk.FSK2Decoder.Output;
|
||||
/**
|
||||
* TAIT 1200 - 1200 baud 2FSK decoder
|
||||
*/
|
||||
public class Tait1200Decoder extends Decoder implements IRealBufferListener,
|
||||
public class Tait1200Decoder extends Decoder implements IFilteredRealBufferListener,
|
||||
Instrumentable
|
||||
{
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
@@ -104,8 +105,8 @@ public class Tait1200Decoder extends Decoder implements IRealBufferListener,
|
||||
mMessageFramerGPS.addMessageListener( mMessageAProcessor );
|
||||
mMessageFramerANI.addMessageListener( mMessageBProcessor );
|
||||
|
||||
mMessageAProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageBProcessor.setMessageListener( mMessageBroadcaster );
|
||||
mMessageAProcessor.setMessageListener( this );
|
||||
mMessageBProcessor.setMessageListener( this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -179,7 +180,7 @@ public class Tait1200Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
@@ -198,7 +199,7 @@ public class Tait1200Decoder extends Decoder implements IRealBufferListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class Tait1200DecoderState extends DecoderState
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
******************************************************************************/
|
||||
package module.demodulate.am;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.Module;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.IComplexBufferListener;
|
||||
import sample.real.IRealBufferProvider;
|
||||
import sample.real.IFilteredRealBufferProvider;
|
||||
import sample.real.RealBuffer;
|
||||
import dsp.am.AMDemodulator_CB;
|
||||
import dsp.filter.FilterFactory;
|
||||
@@ -31,7 +33,7 @@ import dsp.filter.fir.real.RealFIRFilter_RB_RB;
|
||||
import dsp.gain.AutomaticGainControl_RB;
|
||||
|
||||
public class AMDemodulatorModule extends Module
|
||||
implements IComplexBufferListener, IRealBufferProvider
|
||||
implements IComplexBufferListener, IFilteredRealBufferProvider
|
||||
{
|
||||
private static final int SAMPLE_RATE = 48000;
|
||||
|
||||
@@ -99,19 +101,19 @@ public class AMDemodulatorModule extends Module
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRealBufferListener( Listener<RealBuffer> listener )
|
||||
public void setFilteredRealBufferListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mAGC.setListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRealBufferListener()
|
||||
public void removeFilteredRealBufferListener()
|
||||
{
|
||||
mAGC.removeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
102
src/module/demodulate/audio/DemodulatedAudioFilterModule.java
Normal file
102
src/module/demodulate/audio/DemodulatedAudioFilterModule.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package module.demodulate.audio;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.Module;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.IFilteredRealBufferProvider;
|
||||
import sample.real.IUnFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.dc.DCRemovalFilter_RealBuffer;
|
||||
import dsp.filter.fir.real.RealFIRFilter_RB_RB;
|
||||
|
||||
public class DemodulatedAudioFilterModule extends Module
|
||||
implements IUnFilteredRealBufferListener, IFilteredRealBufferProvider
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( DemodulatedAudioFilterModule.class );
|
||||
|
||||
private DCRemovalFilter_RealBuffer mDCFilter = new DCRemovalFilter_RealBuffer();
|
||||
private RealFIRFilter_RB_RB mBandPassFilter;
|
||||
/**
|
||||
* Filters demodulated audio and removes any DC component from the buffer
|
||||
*
|
||||
* @param pass - audio pass band pass frequency
|
||||
* @param stop - audio pass band stop frequency
|
||||
*/
|
||||
public DemodulatedAudioFilterModule( int pass, int stop )
|
||||
{
|
||||
assert( stop > pass );
|
||||
|
||||
//TODO: change this to a band pass filter
|
||||
mBandPassFilter = new RealFIRFilter_RB_RB( FilterFactory.getLowPass( 48000, pass, stop, 60,
|
||||
WindowType.HANNING, true ), 1.0f );
|
||||
|
||||
mDCFilter.setListener( mBandPassFilter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
mBandPassFilter.dispose();
|
||||
mBandPassFilter = null;
|
||||
|
||||
mDCFilter.dispose();
|
||||
mDCFilter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilteredRealBufferListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mBandPassFilter.setListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFilteredRealBufferListener()
|
||||
{
|
||||
mBandPassFilter.removeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getUnFilteredRealBufferListener()
|
||||
{
|
||||
return mDCFilter;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user