diff --git a/src/main/java/io/github/dsheirer/channel/traffic/TrafficChannelManager.java b/src/main/java/io/github/dsheirer/channel/traffic/TrafficChannelManager.java
index dcd12ce5..efd9e52c 100644
--- a/src/main/java/io/github/dsheirer/channel/traffic/TrafficChannelManager.java
+++ b/src/main/java/io/github/dsheirer/channel/traffic/TrafficChannelManager.java
@@ -137,7 +137,7 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
{
for(Channel configuredChannel : mTrafficChannelPool)
{
- if(!configuredChannel.getEnabled())
+ if(!configuredChannel.isProcessing())
{
channel = configuredChannel;
break;
@@ -207,7 +207,7 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
//Request to enable the channel
mChannelModel.broadcast(trafficChannelEvent);
- if(channel.getEnabled())
+ if(channel.isProcessing())
{
mTrafficChannelsInUse.put(callEvent.getChannel(), channel);
}
diff --git a/src/main/java/io/github/dsheirer/controller/channel/AutoStartChannelModel.java b/src/main/java/io/github/dsheirer/controller/channel/AutoStartChannelModel.java
new file mode 100644
index 00000000..403a2fc7
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/controller/channel/AutoStartChannelModel.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * sdr-trunk
+ * Copyright (C) 2014-2018 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
+ *
+ ******************************************************************************/
+package io.github.dsheirer.controller.channel;
+
+import javax.swing.table.AbstractTableModel;
+import java.util.List;
+
+/**
+ * Auto-Start Channel Model
+ */
+public class AutoStartChannelModel extends AbstractTableModel
+{
+ private static final long serialVersionUID = 1L;
+
+ public static final int COLUMN_ORDER = 0;
+ public static final int COLUMN_SYSTEM = 1;
+ public static final int COLUMN_SITE = 2;
+ public static final int COLUMN_NAME = 3;
+ public static final int COLUMN_DECODER = 4;
+
+ private static final String[] COLUMN_NAMES = new String[] {"Order", "System", "Site", "Name", "Decoder"};
+
+ private List mChannels;
+
+ public AutoStartChannelModel(List autoStartChannels)
+ {
+ mChannels = autoStartChannels;
+ }
+
+ @Override
+ public int getRowCount()
+ {
+ return mChannels.size();
+ }
+
+ @Override
+ public int getColumnCount()
+ {
+ return COLUMN_NAMES.length;
+ }
+
+ @Override
+ public String getColumnName(int columnIndex)
+ {
+ if(columnIndex < COLUMN_NAMES.length)
+ {
+ return COLUMN_NAMES[columnIndex];
+ }
+
+ return null;
+ }
+
+ @Override
+ public Class> getColumnClass(int columnIndex)
+ {
+ return String.class;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex)
+ {
+ return false;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex)
+ {
+ Channel channel = mChannels.get(rowIndex);
+
+ switch(columnIndex)
+ {
+ case COLUMN_ORDER:
+ return channel.getAutoStartOrder();
+ case COLUMN_SYSTEM:
+ return channel.getSystem();
+ case COLUMN_SITE:
+ return channel.getSite();
+ case COLUMN_NAME:
+ return channel.getName();
+ case COLUMN_DECODER:
+ return channel.getDecodeConfiguration().getDecoderType().getShortDisplayString();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex)
+ {
+ throw new IllegalArgumentException("Not yet implemented");
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/controller/channel/Channel.java b/src/main/java/io/github/dsheirer/controller/channel/Channel.java
index 9c0cee7f..4927f68d 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/Channel.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/Channel.java
@@ -1,6 +1,6 @@
/*******************************************************************************
* sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * Copyright (C) 2014-2018 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
@@ -45,18 +45,18 @@ import io.github.dsheirer.source.tuner.frequency.FrequencyChangeEvent.Event;
public class Channel extends Configuration implements Listener
{
// Standard channels are persisted and traffic channels are temporary
- public enum ChannelType {STANDARD, TRAFFIC}
+ public enum ChannelType
+ {
+ STANDARD, TRAFFIC
+ }
// Static unique channel identifier tracking
private static int UNIQUE_ID = 0;
private DecodeConfiguration mDecodeConfiguration = DecoderFactory.getDefaultDecodeConfiguration();
- private AuxDecodeConfiguration mAuxDecodeConfiguration =
- new AuxDecodeConfiguration();
- private SourceConfiguration mSourceConfiguration =
- SourceConfigFactory.getDefaultSourceConfiguration();
- private EventLogConfiguration mEventLogConfiguration =
- new EventLogConfiguration();
+ private AuxDecodeConfiguration mAuxDecodeConfiguration = new AuxDecodeConfiguration();
+ private SourceConfiguration mSourceConfiguration = SourceConfigFactory.getDefaultSourceConfiguration();
+ private EventLogConfiguration mEventLogConfiguration = new EventLogConfiguration();
private RecordConfiguration mRecordConfiguration = new RecordConfiguration();
private String mAliasListName;
@@ -64,7 +64,9 @@ public class Channel extends Configuration implements Listener
+ *
+ ******************************************************************************/
+package io.github.dsheirer.controller.channel;
+
+import io.github.dsheirer.util.ThreadPool;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class ChannelAutoStartFrame extends JFrame
+{
+ private final static Logger mLog = LoggerFactory.getLogger(ChannelAutoStartFrame.class);
+
+ private static final int COUNTDOWN_SECONDS = 10;
+ private ChannelEventListener mChannelEventListener;
+ private List mChannels;
+
+ private JLabel mCountdownLabel;
+ private JButton mStartButton;
+ private JButton mCancelButton;
+ private JTable mChannelTable;
+ private AtomicBoolean mChannelsStarted = new AtomicBoolean();
+
+ private ScheduledFuture> mTimerFuture;
+
+ /**
+ * Creates and displays a channel auto-start gui for presenting the user with a list of channels that
+ * will be automatically started once the countdown timer reaches zero, or the user chooses to start
+ * now or cancel.
+ *
+ * @param listener to receive channel start/enable request(s)
+ * @param channels to auto-start
+ */
+ public ChannelAutoStartFrame(ChannelEventListener listener, List channels)
+ {
+ mChannelEventListener = listener;
+ mChannels = channels;
+ init();
+
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ setVisible(true);
+ startTimer();
+ }
+ });
+ }
+
+ private void init()
+ {
+ setTitle("Auto-Start Channels");
+ setSize(new Dimension(400,300));
+ setLocationRelativeTo(null);
+ addWindowListener(new WindowAdapter()
+ {
+ @Override
+ public void windowClosing(WindowEvent event)
+ {
+ mLog.info("Channel auto-start canceled by user - window closed");
+ stopTimer();
+ super.windowClosing(event);
+ }
+ });
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new MigLayout("","[grow,fill][grow,fill]",
+ "[][][grow,fill][]"));
+ panel.add(new JLabel("The following channels will be automatically"), "span");
+
+ mCountdownLabel = new JLabel(getCountdownText(COUNTDOWN_SECONDS));
+ panel.add(mCountdownLabel, "span");
+
+ panel.add(new JScrollPane(getChannelTable()), "span");
+
+ mStartButton = new JButton("Start Now");
+ mStartButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ mLog.info("Starting [" + mChannels.size() + "] channels now - user invoked");
+ startChannels();
+ stopTimer();
+ }
+ });
+ panel.add(mStartButton);
+
+ mCancelButton = new JButton("Cancel");
+ mCancelButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ mLog.info("Channel auto-start canceled by user");
+ stopTimer();
+ }
+ });
+ panel.add(mCancelButton);
+ setContentPane(panel);
+ }
+
+ private String getCountdownText(int value)
+ {
+ return "started in: " + value + " seconds.";
+ }
+
+ /**
+ * Updates the countdown text label on the swing event thread
+ * @param value for the countdown
+ */
+ private void updateCountdownText(final int value)
+ {
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ mCountdownLabel.setText(getCountdownText(value));
+ }
+ });
+ }
+
+ /**
+ * Creates (once) a table of auto-start channels
+ */
+ private JTable getChannelTable()
+ {
+ if(mChannelTable == null)
+ {
+ AutoStartChannelModel model = new AutoStartChannelModel(mChannels);
+ mChannelTable = new JTable(model);
+ }
+
+ return mChannelTable;
+ }
+
+ /**
+ * Sends an enable (ie start) request for each of the auto start channels.
+ *
+ * This method is thread-safe and will only be executed once.
+ *
+ * Although the redundant channel-start request would be ignored, this once-only will prevent the chance
+ * that both the timer and the user would attempt to start the channels at the same time.
+ */
+ private void startChannels()
+ {
+ if(mChannelsStarted.compareAndSet(false, true))
+ {
+ if(mChannelEventListener != null)
+ {
+ for(Channel channel: mChannels)
+ {
+ mChannelEventListener.channelChanged(new ChannelEvent(channel, ChannelEvent.Event.REQUEST_ENABLE));
+ }
+ }
+ }
+ }
+
+ /**
+ * Starts the countdown timer to fire once a second.
+ */
+ private void startTimer()
+ {
+ if(mTimerFuture == null)
+ {
+ mTimerFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new CountdownTimer(), 0, 1, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Stops the countdown timer and disposes this frame
+ */
+ private void stopTimer()
+ {
+ if(mTimerFuture != null)
+ {
+ mTimerFuture.cancel(true);
+ mTimerFuture = null;
+ }
+
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ dispose();
+ }
+ });
+ }
+
+ /**
+ * Updates the countdown text and auto-starts the channels once the timer falls below zero.
+ */
+ public class CountdownTimer implements Runnable
+ {
+ private int mCount = COUNTDOWN_SECONDS;
+
+ @Override
+ public void run()
+ {
+ if(mCount >= 0)
+ {
+ updateCountdownText(mCount);
+ mCount--;
+ }
+ else
+ {
+ mLog.info("Starting [" + mChannels.size() + "] now - timer invoked");
+ startChannels();
+ stopTimer();
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java
index 24ae4915..de1b7cde 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java
@@ -8,11 +8,19 @@ import net.coderazzi.filters.gui.AutoChoices;
import net.coderazzi.filters.gui.TableFilterHeader;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
-import java.awt.*;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -236,7 +244,7 @@ public class ChannelController extends JPanel
Channel channel = model.getChannelAtIndex( index );
- boolean enabled = channel.getEnabled();
+ boolean enabled = channel.isProcessing();
if( isSelected )
{
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelEditor.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelEditor.java
index 9f28bf69..65d2cade 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelEditor.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelEditor.java
@@ -1,17 +1,17 @@
/*******************************************************************************
* 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
******************************************************************************/
@@ -30,221 +30,227 @@ import io.github.dsheirer.source.SourceConfigurationEditor;
import io.github.dsheirer.source.SourceManager;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ChannelEditor extends Editor implements ActionListener, ChannelEventListener
{
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
+ private static final String ACTION_START = "Start";
+ private static final String ACTION_STOP = "Stop";
+ private static final String ACTION_SAVE = "Save";
+ private static final String ACTION_RESET = "Reset";
- private NameConfigurationEditor mNameConfigurationEditor;
+ private NameConfigurationEditor mNameConfigurationEditor;
private SourceConfigurationEditor mSourceConfigurationEditor;
private DecodeConfigurationEditor mDecodeConfigurationEditor;
private AuxDecodeConfigurationEditor mAuxDecodeConfigurationEditor;
private EventLogConfigurationEditor mEventLogConfigurationEditor;
private RecordConfigurationEditor mRecordConfigurationEditor;
-
- private JButton mEnableButton = new JButton( "Enable" );
- private JLabel mChannelName = new JLabel( "Channel:" );
-
- private ChannelModel mChannelModel;
- private ChannelMapModel mChannelMapModel;
+
+ private JButton mProcessingStateButton = new JButton(ACTION_START);
+ private JLabel mChannelName = new JLabel("Channel:");
+
+ private ChannelModel mChannelModel;
+ private ChannelMapModel mChannelMapModel;
private SourceManager mSourceManager;
-
- private boolean mChannelEnableRequested = false;
-
- public ChannelEditor( ChannelModel channelModel,
- ChannelMapModel channelMapModel,
- SourceManager sourceManager,
- AliasModel aliasModel )
- {
- mChannelModel = channelModel;
- mChannelMapModel = channelMapModel;
- mSourceManager = sourceManager;
- mNameConfigurationEditor = new NameConfigurationEditor( aliasModel, mChannelModel );
-
- init();
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 3", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]" ) );
-
- JideTabbedPane tabs = new JideTabbedPane();
- tabs.setFont( this.getFont() );
- tabs.setForeground( Color.BLACK );
- tabs.setTabTrailingComponent( mChannelName );
-
- mNameConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Name/Alias", mNameConfigurationEditor );
-
- mSourceConfigurationEditor = new SourceConfigurationEditor( mSourceManager );
- mSourceConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Source", mSourceConfigurationEditor );
-
- mDecodeConfigurationEditor = new DecodeConfigurationEditor( mChannelMapModel );
- mDecodeConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Decoder", mDecodeConfigurationEditor );
+ private boolean mChannelStartRequested = false;
- mAuxDecodeConfigurationEditor = new AuxDecodeConfigurationEditor();
- mAuxDecodeConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Aux Decoders", mAuxDecodeConfigurationEditor );
-
- mEventLogConfigurationEditor = new EventLogConfigurationEditor();
- mEventLogConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Logging", mEventLogConfigurationEditor );
-
- mRecordConfigurationEditor = new RecordConfigurationEditor();
- mRecordConfigurationEditor.setSaveRequestListener( this );
- tabs.addTab( "Recording", mRecordConfigurationEditor );
-
- add( tabs, "span" );
-
- mEnableButton.addActionListener( this );
- mEnableButton.setEnabled( false );
- mEnableButton.setToolTipText( "Start the currently selected channel running/decoding" );
- add( mEnableButton );
-
- JButton btnSave = new JButton( "Save" );
- btnSave.setToolTipText( "Save changes to the currently selected channel" );
- btnSave.addActionListener( ChannelEditor.this );
- add( btnSave );
-
- JButton btnReset = new JButton( "Reset" );
- btnReset.setToolTipText( "Reload the currently selected channel" );
- btnReset.addActionListener( ChannelEditor.this );
- add( btnReset );
- }
-
- @Override
- public void channelChanged( ChannelEvent event )
- {
- if( hasItem() && getItem() == event.getChannel() )
- {
- switch( event.getEvent() )
- {
- case NOTIFICATION_CONFIGURATION_CHANGE:
- case NOTIFICATION_PROCESSING_START:
- case NOTIFICATION_PROCESSING_STOP:
- setItem( getItem() );
- mChannelEnableRequested = false;
- break;
- case NOTIFICATION_DELETE:
- setItem( null );
- break;
- case NOTIFICATION_ENABLE_REJECTED:
- if( mChannelEnableRequested )
- {
- JOptionPane.showMessageDialog( ChannelEditor.this, "Channel could not be "
- + "enabled. This is likely because there are no tuner channels "
- + "available", "Couldn't enable channel", JOptionPane.INFORMATION_MESSAGE );
-
- mChannelEnableRequested = false;
- }
- break;
- default:
- break;
- }
- }
- }
-
- @Override
- public void actionPerformed( ActionEvent e )
+ public ChannelEditor(ChannelModel channelModel,
+ ChannelMapModel channelMapModel,
+ SourceManager sourceManager,
+ AliasModel aliasModel)
{
- String command = e.getActionCommand();
-
- if( command.contentEquals( "Enable" ) )
- {
- if( hasItem() )
- {
- save();
-
- mChannelEnableRequested = true;
- mChannelModel.broadcast( new ChannelEvent( getItem(), ChannelEvent.Event.REQUEST_ENABLE ) );
- }
- }
- else if( command.contentEquals( "Disable" ) )
- {
- if( hasItem() )
- {
- mChannelModel.broadcast( new ChannelEvent( getItem(), ChannelEvent.Event.REQUEST_DISABLE ) );
- }
- }
- else if( command.contentEquals( "Save" ) )
- {
- save();
- }
- else if( command.contentEquals( "Reset" ) )
- {
- setItem( getItem() );
- }
+ mChannelModel = channelModel;
+ mChannelMapModel = channelMapModel;
+ mSourceManager = sourceManager;
+ mNameConfigurationEditor = new NameConfigurationEditor(aliasModel, mChannelModel);
+
+ init();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]"));
+
+ JideTabbedPane tabs = new JideTabbedPane();
+ tabs.setFont(this.getFont());
+ tabs.setForeground(Color.BLACK);
+
+ tabs.setTabTrailingComponent(mChannelName);
+
+ mNameConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Name/Alias", mNameConfigurationEditor);
+
+ mSourceConfigurationEditor = new SourceConfigurationEditor(mSourceManager);
+ mSourceConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Source", mSourceConfigurationEditor);
+
+ mDecodeConfigurationEditor = new DecodeConfigurationEditor(mChannelMapModel);
+ mDecodeConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Decoder", mDecodeConfigurationEditor);
+
+ mAuxDecodeConfigurationEditor = new AuxDecodeConfigurationEditor();
+ mAuxDecodeConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Aux Decoders", mAuxDecodeConfigurationEditor);
+
+ mEventLogConfigurationEditor = new EventLogConfigurationEditor();
+ mEventLogConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Logging", mEventLogConfigurationEditor);
+
+ mRecordConfigurationEditor = new RecordConfigurationEditor();
+ mRecordConfigurationEditor.setSaveRequestListener(this);
+ tabs.addTab("Recording", mRecordConfigurationEditor);
+
+ add(tabs, "span");
+
+ mProcessingStateButton.addActionListener(this);
+ mProcessingStateButton.setEnabled(false);
+ mProcessingStateButton.setToolTipText("Start/Stop the currently selected channel");
+ add(mProcessingStateButton);
+
+ JButton btnSave = new JButton(ACTION_SAVE);
+ btnSave.setToolTipText("Save changes to the currently selected channel");
+ btnSave.addActionListener(ChannelEditor.this);
+ add(btnSave);
+
+ JButton btnReset = new JButton(ACTION_RESET);
+ btnReset.setToolTipText("Reload the currently selected channel");
+ btnReset.addActionListener(ChannelEditor.this);
+ add(btnReset);
+ }
+
+ @Override
+ public void channelChanged(ChannelEvent event)
+ {
+ if(hasItem() && getItem() == event.getChannel())
+ {
+ switch(event.getEvent())
+ {
+ case NOTIFICATION_CONFIGURATION_CHANGE:
+ case NOTIFICATION_PROCESSING_START:
+ case NOTIFICATION_PROCESSING_STOP:
+ setItem(getItem());
+ mChannelStartRequested = false;
+ break;
+ case NOTIFICATION_DELETE:
+ setItem(null);
+ break;
+ case NOTIFICATION_START_PROCESSING_REJECTED:
+ if(mChannelStartRequested)
+ {
+ JOptionPane.showMessageDialog(ChannelEditor.this, "Channel could not be "
+ + "started. This is likely because there are no tuner channels "
+ + "available", "Couldn't start channel", JOptionPane.INFORMATION_MESSAGE);
+
+ mChannelStartRequested = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ String command = e.getActionCommand();
+
+ if(command.contentEquals(ACTION_START))
+ {
+ if(hasItem())
+ {
+ save();
+
+ mChannelStartRequested = true;
+ mChannelModel.broadcast(new ChannelEvent(getItem(), ChannelEvent.Event.REQUEST_ENABLE));
+ }
+ }
+ else if(command.contentEquals(ACTION_STOP))
+ {
+ if(hasItem())
+ {
+ mChannelModel.broadcast(new ChannelEvent(getItem(), ChannelEvent.Event.REQUEST_DISABLE));
+ }
+ }
+ else if(command.contentEquals(ACTION_SAVE))
+ {
+ save();
+ }
+ else if(command.contentEquals(ACTION_RESET))
+ {
+ setItem(getItem());
+ }
+ }
+
+ /**
+ * Sets the channel configuration in each of the channel editor components
+ * Note: this method must be invoked on the swing event dispatch thread
+ */
+ public void setItem(final Channel channel)
+ {
+ super.setItem(channel);
+
+ mNameConfigurationEditor.setItem(channel);
+ mSourceConfigurationEditor.setItem(channel);
+ mDecodeConfigurationEditor.setItem(channel);
+ mAuxDecodeConfigurationEditor.setItem(channel);
+ mEventLogConfigurationEditor.setItem(channel);
+ mRecordConfigurationEditor.setItem(channel);
+
+ if(channel != null)
+ {
+ mChannelName.setText("Channel: " + channel.getName());
+ mProcessingStateButton.setText(channel.isProcessing() ? ACTION_STOP : ACTION_START);
+ mProcessingStateButton.setEnabled(true);
+ mProcessingStateButton.setBackground(channel.isProcessing() ? Color.GREEN : getBackground());
+ }
+ else
+ {
+ mChannelName.setText("Channel: ");
+ mProcessingStateButton.setText(ACTION_START);
+ mProcessingStateButton.setEnabled(false);
+ mProcessingStateButton.setBackground(getBackground());
+ }
}
- /**
- * Sets the channel configuration in each of the channel editor components
- * Note: this method must be invoked on the swing event dispatch thread
- */
- public void setItem( final Channel channel )
- {
- super.setItem( channel );
-
- mNameConfigurationEditor.setItem( channel );
- mSourceConfigurationEditor.setItem( channel );
- mDecodeConfigurationEditor.setItem( channel );
- mAuxDecodeConfigurationEditor.setItem( channel );
- mEventLogConfigurationEditor.setItem( channel );
- mRecordConfigurationEditor.setItem( channel );
-
- if( channel != null )
- {
- mChannelName.setText( "Channel: " + channel.getName() );
- mEnableButton.setText( channel.getEnabled() ? "Disable" : "Enable" );
- mEnableButton.setEnabled( true );
- mEnableButton.setBackground( channel.getEnabled() ? Color.GREEN : getBackground() );
- }
- else
- {
- mChannelName.setText( "Channel: " );
- mEnableButton.setText( "Enable" );
- mEnableButton.setEnabled( false );
- mEnableButton.setBackground( getBackground() );
- }
- }
-
public void save()
{
- if( hasItem() )
- {
- mNameConfigurationEditor.save();
- mSourceConfigurationEditor.save();
- mDecodeConfigurationEditor.save();
- mAuxDecodeConfigurationEditor.save();
- mEventLogConfigurationEditor.save();
- mRecordConfigurationEditor.save();
-
- try
- {
- mDecodeConfigurationEditor.validate( mSourceConfigurationEditor );
- mDecodeConfigurationEditor.validate( mAuxDecodeConfigurationEditor );
- }
- catch( EditorValidationException e )
- {
- e.getEditor().requestFocus();
-
- JOptionPane.showMessageDialog( e.getEditor(), e.getReason(),
- "Configuration Error", JOptionPane.ERROR_MESSAGE );
-
- return;
- }
-
+ if(hasItem())
+ {
+ mNameConfigurationEditor.save();
+ mSourceConfigurationEditor.save();
+ mDecodeConfigurationEditor.save();
+ mAuxDecodeConfigurationEditor.save();
+ mEventLogConfigurationEditor.save();
+ mRecordConfigurationEditor.save();
- mChannelModel.broadcast( new ChannelEvent( getItem(),
- ChannelEvent.Event.NOTIFICATION_CONFIGURATION_CHANGE ) );
- }
+ try
+ {
+ mDecodeConfigurationEditor.validate(mSourceConfigurationEditor);
+ mDecodeConfigurationEditor.validate(mAuxDecodeConfigurationEditor);
+ }
+ catch(EditorValidationException e)
+ {
+ e.getEditor().requestFocus();
- setModified( false );
+ JOptionPane.showMessageDialog(e.getEditor(), e.getReason(),
+ "Configuration Error", JOptionPane.ERROR_MESSAGE);
+
+ return;
+ }
+
+
+ mChannelModel.broadcast(new ChannelEvent(getItem(),
+ ChannelEvent.Event.NOTIFICATION_CONFIGURATION_CHANGE));
+ }
+
+ setModified(false);
}
}
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelEvent.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelEvent.java
index fc778521..42679a38 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelEvent.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelEvent.java
@@ -1,6 +1,6 @@
/*******************************************************************************
* SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
+ * Copyright (C) 2014-2018 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
@@ -42,6 +42,11 @@ public class ChannelEvent
{
return mEvent;
}
+
+ public String toString()
+ {
+ return getEvent().name() + " Channel:" + getChannel().getName();
+ }
/**
* Channel events to describe the specific event
@@ -55,7 +60,7 @@ public class ChannelEvent
//Channel is deleted/removed
NOTIFICATION_DELETE,
//Channel enable request was rejected
- NOTIFICATION_ENABLE_REJECTED,
+ NOTIFICATION_START_PROCESSING_REJECTED,
//Channel has started processing/decoding
NOTIFICATION_PROCESSING_START,
//Channel has stopped processing/decoding
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelModel.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelModel.java
index 8b0d2516..30939c9c 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelModel.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelModel.java
@@ -25,6 +25,7 @@ import io.github.dsheirer.module.decode.DecoderType;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -42,9 +43,11 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
public static final int COLUMN_ALIAS_LIST = 4;
public static final int COLUMN_SOURCE = 5;
public static final int COLUMN_DECODER = 6;
+ public static final int COLUMN_AUTO_START = 7;
- private static final String[] COLUMN_NAMES = new String[] {"Enabled", "System", "Site", "Name", "Alias List",
- "Source", "Decoder"};
+ private static final String[] COLUMN_NAMES = new String[] {"Playing", "System", "Site", "Name", "Alias List",
+ "Source", "Decoder", "Auto-Start"};
+ private static final String VALUE_YES = "Yes";
private List mChannels = new CopyOnWriteArrayList<>();
private List mTrafficChannels = new CopyOnWriteArrayList<>();
@@ -209,11 +212,6 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
broadcast(new ChannelEvent(channel, Event.NOTIFICATION_ADD));
- if(channel.getEnabled())
- {
- broadcast(new ChannelEvent(channel, Event.REQUEST_ENABLE));
- }
-
return index;
}
@@ -247,6 +245,48 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
}
}
+ /**
+ * List of channels that have the auto-start flag set.
+ *
+ * @return auto-start channels sorted by the channel order value.
+ */
+ public List getAutoStartChannels()
+ {
+ List autoStartChannels = new ArrayList<>();
+
+ for(Channel channel: getChannels())
+ {
+ if(channel.isAutoStart())
+ {
+ autoStartChannels.add(channel);
+ }
+ }
+
+ Collections.sort(autoStartChannels, new Comparator()
+ {
+ @Override
+ public int compare(Channel channel1, Channel channel2)
+ {
+ if(channel1.hasAutoStartOrder() && channel2.hasAutoStartOrder())
+ {
+ return Integer.compare(channel1.getAutoStartOrder(), channel2.getAutoStartOrder());
+ }
+ else if(channel1.hasAutoStartOrder())
+ {
+ return -1;
+ }
+ else if(channel2.hasAutoStartOrder())
+ {
+ return 1;
+ }
+
+ return 0;
+ }
+ });
+
+ return autoStartChannels;
+ }
+
/**
* Returns a list of channels that fall within the frequency range
*
@@ -331,7 +371,7 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
switch(columnIndex)
{
case COLUMN_ENABLED:
- return channel.getEnabled() ? "Enabled" : null;
+ return channel.isProcessing() ? VALUE_YES : null;
case COLUMN_SYSTEM:
return channel.getSystem();
case COLUMN_SITE:
@@ -344,6 +384,19 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
return channel.getSourceConfiguration().getDescription();
case COLUMN_DECODER:
return channel.getDecodeConfiguration().getDecoderType().getShortDisplayString();
+ case COLUMN_AUTO_START:
+ if(channel.isAutoStart())
+ {
+ if(channel.hasAutoStartOrder())
+ {
+ return channel.getAutoStartOrder();
+ }
+ else
+ {
+ return VALUE_YES;
+ }
+ }
+ break;
}
return null;
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java
index ee4a232d..c456b8e6 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java
@@ -159,7 +159,7 @@ public class ChannelProcessingManager implements ChannelEventListener
}
break;
case REQUEST_DISABLE:
- if(channel.getEnabled())
+ if(channel.isProcessing())
{
switch(channel.getChannelType())
{
@@ -176,7 +176,7 @@ public class ChannelProcessingManager implements ChannelEventListener
}
}
case NOTIFICATION_DELETE:
- if(channel.getEnabled())
+ if(channel.isProcessing())
{
stopProcessing(channel, true);
}
@@ -220,9 +220,9 @@ public class ChannelProcessingManager implements ChannelEventListener
if(source == null)
{
- channel.setEnabled(false);
+ channel.setProcessing(false);
- mChannelModel.broadcast(new ChannelEvent(channel, ChannelEvent.Event.NOTIFICATION_ENABLE_REJECTED));
+ mChannelModel.broadcast(new ChannelEvent(channel, ChannelEvent.Event.NOTIFICATION_START_PROCESSING_REJECTED));
return;
}
@@ -325,7 +325,7 @@ public class ChannelProcessingManager implements ChannelEventListener
getChannelMetadataModel().add(processingChain.getChannelState().getMutableMetadata(), channel);
- channel.setEnabled(true);
+ channel.setProcessing(true);
mProcessingChains.put(channel.getChannelID(), processingChain);
@@ -334,7 +334,7 @@ public class ChannelProcessingManager implements ChannelEventListener
private void stopProcessing(Channel channel, boolean remove)
{
- channel.setEnabled(false);
+ channel.setProcessing(false);
if(mProcessingChains.containsKey(channel.getChannelID()))
{
diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelUtils.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelUtils.java
index 657b65e4..69cff222 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/ChannelUtils.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelUtils.java
@@ -4,8 +4,11 @@ import io.github.dsheirer.channel.state.DecoderState;
import io.github.dsheirer.module.ProcessingChain;
import io.github.dsheirer.module.decode.event.ActivitySummaryFrame;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JSeparator;
+import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -23,7 +26,7 @@ public class ChannelUtils
{
JMenu menu = new JMenu( "Channel: " + channel.getName() );
- if( channel.getEnabled() )
+ if( channel.isProcessing() )
{
JMenuItem disable = new JMenuItem( "Disable" );
disable.addActionListener( new ActionListener()
diff --git a/src/main/java/io/github/dsheirer/controller/channel/NameConfigurationEditor.java b/src/main/java/io/github/dsheirer/controller/channel/NameConfigurationEditor.java
index 9d07aa73..94e0090d 100644
--- a/src/main/java/io/github/dsheirer/controller/channel/NameConfigurationEditor.java
+++ b/src/main/java/io/github/dsheirer/controller/channel/NameConfigurationEditor.java
@@ -23,9 +23,21 @@ import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.swing.*;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.JTextField;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
@@ -48,6 +60,8 @@ public class NameConfigurationEditor extends Editor implements Document
private JComboBox mSystemNameCombo;
private JComboBox mSiteNameCombo;
private JComboBox mAliasListCombo;
+ private JCheckBox mAutoStartCheckBox;
+ private JSpinner mAutoStartOrder;
public NameConfigurationEditor(AliasModel aliasModel, ChannelModel model)
{
@@ -139,6 +153,40 @@ public class NameConfigurationEditor extends Editor implements Document
add(new JLabel("Site:"));
add(mSiteNameCombo);
+
+ JPanel autoStartPanel = new JPanel();
+
+ mAutoStartCheckBox = new JCheckBox("Auto-Start");
+ mAutoStartCheckBox.setToolTipText("Automatically start this channel each time the application runs.");
+ mAutoStartCheckBox.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ mAutoStartOrder.setEnabled(mAutoStartCheckBox.isSelected());
+ setModified(true);
+ }
+ });
+ autoStartPanel.add(mAutoStartCheckBox);
+
+ SpinnerModel model = new SpinnerNumberModel(0,0,500,1);
+ mAutoStartOrder = new JSpinner(model);
+ mAutoStartOrder.setEnabled(false);
+ mAutoStartOrder.setPreferredSize(new Dimension(60, mAutoStartOrder.getPreferredSize().height));
+ mAutoStartOrder.setToolTipText("Auto-start order: 1 (high) <> 500 (low). 0 = no ordering");
+ mAutoStartOrder.addChangeListener(new ChangeListener()
+ {
+ @Override
+ public void stateChanged(ChangeEvent e)
+ {
+ setModified(true);
+ }
+ });
+
+ autoStartPanel.add(new JLabel("Order:"));
+ autoStartPanel.add(mAutoStartOrder);
+ add(new JLabel()); //Empty space holder
+ add(autoStartPanel);
}
@Override
@@ -156,6 +204,11 @@ public class NameConfigurationEditor extends Editor implements Document
Object aliasList = mAliasListCombo.getSelectedItem();
getItem().setAliasListName(aliasList == null ? null : (String)aliasList);
+
+ getItem().setAutoStart(mAutoStartCheckBox.isSelected());
+
+ int order = ((Number)mAutoStartOrder.getValue()).intValue();
+ getItem().setAutoStartOrder((order > 0 ? order : null));
}
setModified(false);
@@ -182,6 +235,16 @@ public class NameConfigurationEditor extends Editor implements Document
{
mSiteNameCombo.setEnabled(enabled);
}
+
+ if(mAutoStartCheckBox.isEnabled() != enabled)
+ {
+ mAutoStartCheckBox.setEnabled(enabled);
+ }
+
+ if(mAutoStartOrder.isEnabled() != enabled)
+ {
+ mAutoStartOrder.setEnabled(enabled);
+ }
}
@Override
@@ -244,6 +307,19 @@ public class NameConfigurationEditor extends Editor implements Document
mChannelName.setText(null);
}
+ if(channel.isAutoStart())
+ {
+ mAutoStartCheckBox.setSelected(channel.isAutoStart());
+ mAutoStartOrder.setEnabled(true);
+ }
+ else
+ {
+ mAutoStartCheckBox.setSelected(false);
+ mAutoStartOrder.setEnabled(false);
+ }
+
+ mAutoStartOrder.setValue(channel.hasAutoStartOrder() ? channel.getAutoStartOrder() : 0);
+
setModified(false);
}
diff --git a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
index 79cedda4..b6d6b6d8 100644
--- a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
+++ b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
@@ -25,6 +25,8 @@ import io.github.dsheirer.audio.AudioManager;
import io.github.dsheirer.audio.broadcast.BroadcastModel;
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
import io.github.dsheirer.controller.ControllerPanel;
+import io.github.dsheirer.controller.channel.Channel;
+import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
import io.github.dsheirer.controller.channel.ChannelModel;
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
@@ -51,8 +53,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JSeparator;
+import javax.swing.KeyStroke;
+import java.awt.AWTException;
+import java.awt.Desktop;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
@@ -61,6 +74,7 @@ import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.List;
public class SDRTrunk implements Listener
{
@@ -72,6 +86,8 @@ public class SDRTrunk implements Listener
private BroadcastStatusPanel mBroadcastStatusPanel;
private BroadcastModel mBroadcastModel;
private ControllerPanel mControllerPanel;
+ private ChannelModel mChannelModel;
+ private ChannelProcessingManager mChannelProcessingManager;
private SettingsManager mSettingsManager;
private SpectralDisplayPanel mSpectralPanel;
private JFrame mMainGui = new JFrame();
@@ -117,7 +133,7 @@ public class SDRTrunk implements Listener
AliasModel aliasModel = new AliasModel();
- ChannelModel channelModel = new ChannelModel();
+ mChannelModel = new ChannelModel();
ChannelMapModel channelMapModel = new ChannelMapModel();
@@ -127,43 +143,42 @@ public class SDRTrunk implements Listener
SourceManager sourceManager = new SourceManager(tunerModel, mSettingsManager);
- ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(
- channelModel, channelMapModel, aliasModel, eventLogManager, recorderManager, sourceManager);
- channelProcessingManager.addAudioPacketListener(recorderManager);
+ mChannelProcessingManager = new ChannelProcessingManager(mChannelModel, channelMapModel, aliasModel,
+ eventLogManager, recorderManager, sourceManager);
+ mChannelProcessingManager.addAudioPacketListener(recorderManager);
- channelModel.addListener(channelProcessingManager);
+ mChannelModel.addListener(mChannelProcessingManager);
ChannelSelectionManager channelSelectionManager =
- new ChannelSelectionManager(channelModel);
- channelModel.addListener(channelSelectionManager);
+ new ChannelSelectionManager(mChannelModel);
+ mChannelModel.addListener(channelSelectionManager);
AliasActionManager aliasActionManager = new AliasActionManager();
- channelProcessingManager.addMessageListener(aliasActionManager);
+ mChannelProcessingManager.addMessageListener(aliasActionManager);
AudioManager audioManager = new AudioManager(sourceManager.getMixerManager());
- channelProcessingManager.addAudioPacketListener(audioManager);
+ mChannelProcessingManager.addAudioPacketListener(audioManager);
mBroadcastModel = new BroadcastModel(mIconManager);
- channelProcessingManager.addAudioPacketListener(mBroadcastModel);
+ mChannelProcessingManager.addAudioPacketListener(mBroadcastModel);
MapService mapService = new MapService(mIconManager);
- channelProcessingManager.addMessageListener(mapService);
+ mChannelProcessingManager.addMessageListener(mapService);
mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel,
- channelModel, channelMapModel, channelProcessingManager, mIconManager,
+ mChannelModel, channelMapModel, mChannelProcessingManager, mIconManager,
mapService, mSettingsManager, sourceManager, tunerModel);
- mSpectralPanel = new SpectralDisplayPanel(channelModel,
- channelProcessingManager, mSettingsManager);
+ mSpectralPanel = new SpectralDisplayPanel(mChannelModel,
+ mChannelProcessingManager, mSettingsManager);
- TunerSpectralDisplayManager tunerSpectralDisplayManager =
- new TunerSpectralDisplayManager(mSpectralPanel,
- channelModel, channelProcessingManager, mSettingsManager);
+ TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
+ mChannelModel, mChannelProcessingManager, mSettingsManager);
tunerModel.addListener(tunerSpectralDisplayManager);
tunerModel.addListener(this);
- PlaylistManager playlistManager = new PlaylistManager(aliasModel, mBroadcastModel, channelModel,
+ PlaylistManager playlistManager = new PlaylistManager(aliasModel, mBroadcastModel, mChannelModel,
channelMapModel);
playlistManager.init();
@@ -183,6 +198,7 @@ public class SDRTrunk implements Listener
try
{
mMainGui.setVisible(true);
+ autoStartChannels();
}
catch(Exception e)
{
@@ -192,6 +208,21 @@ public class SDRTrunk implements Listener
});
}
+ /**
+ * Shows a dialog that lists the channels that have been designated for auto-start, sorted by auto-start order and
+ * allows the user to start now, cancel, or allow the timer to expire and then start the channels. The dialog will
+ * only show if there are one ore more channels designated for auto-start.
+ */
+ private void autoStartChannels()
+ {
+ List channels = mChannelModel.getAutoStartChannels();
+
+ if(channels.size() > 0)
+ {
+ ChannelAutoStartFrame autoStartFrame = new ChannelAutoStartFrame(mChannelProcessingManager, channels);
+ }
+ }
+
/**
* Launch the application.
*/
@@ -212,7 +243,8 @@ public class SDRTrunk implements Listener
*/
mTitle = SystemProperties.getInstance().getApplicationName();
mMainGui.setTitle(mTitle);
- mMainGui.setBounds(100, 100, 1280, 800);
+ mMainGui.setSize(new Dimension(1280,800));
+ mMainGui.setLocationRelativeTo(null);
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set preferred sizes to influence the split
diff --git a/src/main/java/io/github/dsheirer/spectrum/ChannelSpectrumPanel.java b/src/main/java/io/github/dsheirer/spectrum/ChannelSpectrumPanel.java
index 7b7bf9d0..ff383ac1 100644
--- a/src/main/java/io/github/dsheirer/spectrum/ChannelSpectrumPanel.java
+++ b/src/main/java/io/github/dsheirer/spectrum/ChannelSpectrumPanel.java
@@ -30,8 +30,13 @@ import io.github.dsheirer.spectrum.menu.SmoothingItem;
import io.github.dsheirer.spectrum.menu.SmoothingTypeItem;
import net.miginfocom.swing.MigLayout;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
+import javax.swing.SwingUtilities;
+import java.awt.Component;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
@@ -193,7 +198,7 @@ public class ChannelSpectrumPanel extends JPanel
private void start()
{
- if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.getEnabled() )
+ if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.isProcessing() )
{
ProcessingChain processingChain = mChannelProcessingManager
.getProcessingChain( mCurrentChannel );
@@ -209,7 +214,7 @@ public class ChannelSpectrumPanel extends JPanel
private void stop()
{
- if( mCurrentChannel != null && mCurrentChannel.getEnabled() )
+ if( mCurrentChannel != null && mCurrentChannel.isProcessing() )
{
ProcessingChain processingChain = mChannelProcessingManager
.getProcessingChain( mCurrentChannel );
diff --git a/src/main/java/io/github/dsheirer/spectrum/OverlayPanel.java b/src/main/java/io/github/dsheirer/spectrum/OverlayPanel.java
index d1317e11..3647a047 100644
--- a/src/main/java/io/github/dsheirer/spectrum/OverlayPanel.java
+++ b/src/main/java/io/github/dsheirer/spectrum/OverlayPanel.java
@@ -34,8 +34,16 @@ import io.github.dsheirer.source.tuner.frequency.IFrequencyChangeProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.JPanel;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.Stroke;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Line2D;
@@ -517,14 +525,14 @@ public class OverlayPanel extends JPanel implements ChannelEventListener, IFrequ
for(Channel channel : mVisibleChannels)
{
if(mChannelDisplay == ChannelDisplay.ALL ||
- (mChannelDisplay == ChannelDisplay.ENABLED && channel.getEnabled()))
+ (mChannelDisplay == ChannelDisplay.ENABLED && channel.isProcessing()))
{
//Choose the correct background color to use
if(channel.isSelected())
{
graphics.setColor(mColorChannelConfigSelected);
}
- else if(channel.getEnabled())
+ else if(channel.isProcessing())
{
graphics.setColor(mColorChannelConfigProcessing);
}