/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package instrument.gui;
import alias.AliasModel;
import controller.channel.Channel;
import controller.channel.ChannelModel;
import controller.channel.ChannelProcessingManager;
import controller.channel.map.ChannelMapModel;
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 message.Message;
import module.Module;
import module.decode.DecoderFactory;
import module.decode.config.DecodeConfiguration;
import module.log.EventLogManager;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import playlist.PlaylistManager;
import sample.Listener;
import source.IControllableFileSource;
import source.Source;
import javax.swing.*;
import java.awt.*;
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;
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(PlaylistManager playlistManager, Channel channel, IControllableFileSource source)
{
mSource = source;
mDecodeConfig = channel.getDecodeConfiguration();
mProcessingChain = new InstrumentableProcessingChain();
ChannelModel channelModel = new ChannelModel();
ChannelMapModel channelMapModel = new ChannelMapModel();
ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(channelModel, channelMapModel,
new AliasModel(), new EventLogManager(), null, null);
List<Module> modules = DecoderFactory.getModules(channelModel, channelMapModel, channelProcessingManager,
new AliasModel(), channel, mProcessingChain.getChannelState().getMutableMetadata());
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));
}
}
}
}