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:
denny
2016-04-01 08:23:49 -04:00
450 changed files with 19560 additions and 22805 deletions

View File

@@ -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 ) );

View File

@@ -26,4 +26,4 @@ public class ChangeChannelTimeoutEvent extends DecoderStateEvent
{
return mCallTimeout;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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 );

View File

@@ -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();
}
}
}

View File

@@ -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 &&

View File

@@ -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;

View File

@@ -65,4 +65,4 @@ public class DecoderStateEvent
START,
TRAFFIC_CHANNEL_ALLOCATION;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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 );
}
}
}