mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
saturation. Each tunerchannelsource was sharing a thread pool and as the processing load increased, the thread pool was not expanding and the processing tasks were backing up, causing the buffers to grow with unprocessed data. Changed so that each tuner channel source is handed a thread pool to use for processing incoming sample data. Processing chain maintains the thread pool and starts the channel source. This allows traffic channels to reuse the thread pool across multiple iterations.
363 lines
8.9 KiB
Java
363 lines
8.9 KiB
Java
/*******************************************************************************
|
|
* 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 instrument.gui;
|
|
|
|
import instrument.Instrumentable;
|
|
import instrument.InstrumentableProcessingChain;
|
|
import instrument.tap.Tap;
|
|
import instrument.tap.TapGroup;
|
|
import instrument.tap.TapViewPanel;
|
|
import instrument.tap.stream.BinaryTap;
|
|
import instrument.tap.stream.BinaryTapViewPanel;
|
|
import instrument.tap.stream.ComplexSampleTap;
|
|
import instrument.tap.stream.ComplexSampleTapViewPanel;
|
|
import instrument.tap.stream.ComplexTap;
|
|
import instrument.tap.stream.ComplexTapViewPanel;
|
|
import instrument.tap.stream.DibitTap;
|
|
import instrument.tap.stream.DibitTapViewPanel;
|
|
import instrument.tap.stream.EyeDiagramDataTap;
|
|
import instrument.tap.stream.EyeDiagramDataTapPanel;
|
|
import instrument.tap.stream.FloatTap;
|
|
import instrument.tap.stream.FloatTapViewPanel;
|
|
import instrument.tap.stream.QPSKTap;
|
|
import instrument.tap.stream.QPSKTapPanel;
|
|
import instrument.tap.stream.SymbolEventTap;
|
|
import instrument.tap.stream.SymbolEventTapViewPanel;
|
|
|
|
import java.awt.Dimension;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
import javax.swing.JCheckBoxMenuItem;
|
|
import javax.swing.JInternalFrame;
|
|
import javax.swing.JMenu;
|
|
import javax.swing.JMenuItem;
|
|
import javax.swing.JPopupMenu;
|
|
import javax.swing.JSeparator;
|
|
|
|
import message.Message;
|
|
import module.Module;
|
|
import module.decode.DecoderFactory;
|
|
import module.decode.config.AuxDecodeConfiguration;
|
|
import module.decode.config.DecodeConfiguration;
|
|
import net.miginfocom.swing.MigLayout;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import record.config.RecordConfiguration;
|
|
import sample.Listener;
|
|
import source.IControllableFileSource;
|
|
import source.Source;
|
|
import alias.AliasList;
|
|
import controller.ResourceManager;
|
|
import controller.channel.Channel.ChannelType;
|
|
import controller.site.Site;
|
|
import controller.system.System;
|
|
|
|
public class DecoderViewFrame extends JInternalFrame
|
|
implements Listener<Message>
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
private final static Logger mLog =
|
|
LoggerFactory.getLogger( DecoderViewFrame.class );
|
|
|
|
private DecodeConfiguration mDecodeConfig;
|
|
private InstrumentableProcessingChain mProcessingChain;
|
|
private IControllableFileSource mSource;
|
|
|
|
private HashMap<Tap,TapViewPanel> mPanelMap =
|
|
new HashMap<Tap,TapViewPanel>();
|
|
|
|
public DecoderViewFrame( ResourceManager resourceManager,
|
|
DecodeConfiguration decodeConfig,
|
|
RecordConfiguration recordConfig,
|
|
AuxDecodeConfiguration auxConfig,
|
|
AliasList aliasList,
|
|
IControllableFileSource source )
|
|
{
|
|
mSource = source;
|
|
|
|
mDecodeConfig = decodeConfig;
|
|
|
|
mProcessingChain = new InstrumentableProcessingChain( "instrumented" );
|
|
|
|
List<Module> modules = DecoderFactory
|
|
.getModules( ChannelType.STANDARD,
|
|
resourceManager,
|
|
decodeConfig,
|
|
recordConfig,
|
|
auxConfig,
|
|
aliasList,
|
|
new System( "Instrumented" ),
|
|
new Site( "Instrumented" ),
|
|
"Channel Name" );
|
|
|
|
mProcessingChain.addModules( modules );
|
|
|
|
mProcessingChain.addMessageListener( this );
|
|
|
|
mProcessingChain.setSource( (Source)mSource );
|
|
|
|
mProcessingChain.start();
|
|
|
|
initGui();
|
|
}
|
|
|
|
private void initGui()
|
|
{
|
|
setLayout( new MigLayout( "insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]" ) );
|
|
|
|
setTitle( "Decoder [" + mDecodeConfig.getDecoderType().getDisplayString() + "]" );
|
|
setPreferredSize( new Dimension( 450, 250 ) );
|
|
setSize( 450, 250 );
|
|
|
|
setResizable( true );
|
|
setClosable( true );
|
|
setIconifiable( true );
|
|
setMaximizable( false );
|
|
|
|
addMouseListener( new MouseListener()
|
|
{
|
|
@Override
|
|
public void mouseClicked( MouseEvent me )
|
|
{
|
|
if( me.getButton() == MouseEvent.BUTTON3 )
|
|
{
|
|
JPopupMenu popup = new JPopupMenu();
|
|
|
|
popup.add( getTapContextMenu() );
|
|
|
|
if( !mPanelMap.values().isEmpty() )
|
|
{
|
|
popup.add( new JSeparator() );
|
|
|
|
for( TapViewPanel panel: mPanelMap.values() )
|
|
{
|
|
popup.add( panel.getContextMenu() );
|
|
}
|
|
}
|
|
|
|
popup.show( DecoderViewFrame.this, me.getX(), me.getY() );
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseEntered( MouseEvent arg0 ) {}
|
|
@Override
|
|
public void mouseExited( MouseEvent arg0 ) {}
|
|
@Override
|
|
public void mousePressed( MouseEvent arg0 ) {}
|
|
@Override
|
|
public void mouseReleased( MouseEvent arg0 ) {}
|
|
|
|
} );
|
|
}
|
|
|
|
private JMenu getTapContextMenu()
|
|
{
|
|
JMenu menu = new JMenu( "Modules" );
|
|
|
|
if( mProcessingChain != null )
|
|
{
|
|
for( Module module: mProcessingChain.getModules() )
|
|
{
|
|
if( module instanceof Instrumentable )
|
|
{
|
|
List<TapGroup> groups = ((Instrumentable)module).getTapGroups();
|
|
|
|
for( TapGroup group: groups )
|
|
{
|
|
menu.add( new TapGroupMenu( group ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return menu;
|
|
}
|
|
|
|
public void add( Tap tap )
|
|
{
|
|
TapViewPanel panel = null;
|
|
|
|
switch( tap.getType() )
|
|
{
|
|
case EVENT_SYNC_DETECT:
|
|
break;
|
|
case STREAM_BINARY:
|
|
panel = new BinaryTapViewPanel( (BinaryTap)tap );
|
|
break;
|
|
case STREAM_COMPLEX:
|
|
panel = new ComplexTapViewPanel( (ComplexTap)tap );
|
|
break;
|
|
case STREAM_COMPLEX_SAMPLE:
|
|
panel = new ComplexSampleTapViewPanel( (ComplexSampleTap)tap );
|
|
break;
|
|
case STREAM_DIBIT:
|
|
panel = new DibitTapViewPanel( (DibitTap)tap );
|
|
break;
|
|
case STREAM_EYE_DIAGRAM:
|
|
panel = new EyeDiagramDataTapPanel( (EyeDiagramDataTap)tap ) ;
|
|
break;
|
|
case STREAM_FLOAT:
|
|
panel = new FloatTapViewPanel( (FloatTap)tap );
|
|
break;
|
|
case STREAM_QPSK:
|
|
panel = new QPSKTapPanel( (QPSKTap)tap );
|
|
break;
|
|
case STREAM_SYMBOL:
|
|
panel = new SymbolEventTapViewPanel( (SymbolEventTap)tap );
|
|
break;
|
|
}
|
|
|
|
if( panel != null )
|
|
{
|
|
add( panel, "span" );
|
|
|
|
validate();
|
|
|
|
mPanelMap.put( tap, panel );
|
|
|
|
for( Module module: mProcessingChain.getModules() )
|
|
{
|
|
if( module instanceof Instrumentable )
|
|
{
|
|
((Instrumentable)module).registerTap( tap );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mLog.info( "Tap panel is null, couldn't add for tap " +
|
|
tap.getName() + "[" + tap.getType().toString() + "]" );
|
|
}
|
|
}
|
|
|
|
public void remove( Tap tap )
|
|
{
|
|
for( Module module: mProcessingChain.getModules() )
|
|
{
|
|
if( module instanceof Instrumentable )
|
|
{
|
|
((Instrumentable)module).unregisterTap( tap );
|
|
}
|
|
}
|
|
|
|
TapViewPanel panel = mPanelMap.get( tap );
|
|
|
|
remove( panel );
|
|
|
|
validate();
|
|
|
|
mPanelMap.remove( tap );
|
|
}
|
|
|
|
public class AddAllTapsItem extends JMenuItem
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private final List<Tap> mTaps;
|
|
|
|
public AddAllTapsItem( final List<Tap> taps )
|
|
{
|
|
super( "All Taps" );
|
|
|
|
mTaps = taps;
|
|
|
|
addActionListener( new ActionListener()
|
|
{
|
|
@Override
|
|
public void actionPerformed( ActionEvent e )
|
|
{
|
|
for( Tap tap: mTaps )
|
|
{
|
|
DecoderViewFrame.this.add( tap );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
|
|
public class TapSelectionItem extends JCheckBoxMenuItem
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
private Tap mTap;
|
|
|
|
public TapSelectionItem( Tap tap )
|
|
{
|
|
super( tap.getName() );
|
|
|
|
mTap = tap;
|
|
|
|
if( mPanelMap.keySet().contains( tap ) )
|
|
{
|
|
setSelected( true );
|
|
}
|
|
|
|
addActionListener( new ActionListener()
|
|
{
|
|
@Override
|
|
public void actionPerformed( ActionEvent arg0 )
|
|
{
|
|
if( mPanelMap.keySet().contains( mTap ) )
|
|
{
|
|
DecoderViewFrame.this.remove( mTap );
|
|
}
|
|
else
|
|
{
|
|
DecoderViewFrame.this.add( mTap );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void receive( Message message )
|
|
{
|
|
mLog.info( message.toString() );
|
|
}
|
|
|
|
public class TapGroupMenu extends JMenu
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
private TapGroup mTapGroup;
|
|
|
|
public TapGroupMenu( TapGroup tapGroup )
|
|
{
|
|
super( tapGroup.getName() );
|
|
|
|
mTapGroup = tapGroup;
|
|
|
|
add( new AddAllTapsItem( mTapGroup.getTaps() ) );
|
|
|
|
add( new JSeparator() );
|
|
|
|
for( Tap tap: mTapGroup.getTaps() )
|
|
{
|
|
add( new TapSelectionItem( tap ) );
|
|
}
|
|
}
|
|
}
|
|
}
|