mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 17:47:32 -05:00
Merge pull request #329 from DSheirer/328-auto-start-ordering
328 Channel Auto-Start capability
This commit is contained in:
@@ -137,7 +137,7 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
|
|||||||
{
|
{
|
||||||
for(Channel configuredChannel : mTrafficChannelPool)
|
for(Channel configuredChannel : mTrafficChannelPool)
|
||||||
{
|
{
|
||||||
if(!configuredChannel.getEnabled())
|
if(!configuredChannel.isProcessing())
|
||||||
{
|
{
|
||||||
channel = configuredChannel;
|
channel = configuredChannel;
|
||||||
break;
|
break;
|
||||||
@@ -207,7 +207,7 @@ public class TrafficChannelManager extends Module implements ICallEventProvider,
|
|||||||
//Request to enable the channel
|
//Request to enable the channel
|
||||||
mChannelModel.broadcast(trafficChannelEvent);
|
mChannelModel.broadcast(trafficChannelEvent);
|
||||||
|
|
||||||
if(channel.getEnabled())
|
if(channel.isProcessing())
|
||||||
{
|
{
|
||||||
mTrafficChannelsInUse.put(callEvent.getChannel(), channel);
|
mTrafficChannelsInUse.put(callEvent.getChannel(), channel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
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<Channel> mChannels;
|
||||||
|
|
||||||
|
public AutoStartChannelModel(List<Channel> 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* sdrtrunk
|
* 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
|
* 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
|
* 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<FrequencyChangeEvent>
|
public class Channel extends Configuration implements Listener<FrequencyChangeEvent>
|
||||||
{
|
{
|
||||||
// Standard channels are persisted and traffic channels are temporary
|
// Standard channels are persisted and traffic channels are temporary
|
||||||
public enum ChannelType {STANDARD, TRAFFIC}
|
public enum ChannelType
|
||||||
|
{
|
||||||
|
STANDARD, TRAFFIC
|
||||||
|
}
|
||||||
|
|
||||||
// Static unique channel identifier tracking
|
// Static unique channel identifier tracking
|
||||||
private static int UNIQUE_ID = 0;
|
private static int UNIQUE_ID = 0;
|
||||||
|
|
||||||
private DecodeConfiguration mDecodeConfiguration = DecoderFactory.getDefaultDecodeConfiguration();
|
private DecodeConfiguration mDecodeConfiguration = DecoderFactory.getDefaultDecodeConfiguration();
|
||||||
private AuxDecodeConfiguration mAuxDecodeConfiguration =
|
private AuxDecodeConfiguration mAuxDecodeConfiguration = new AuxDecodeConfiguration();
|
||||||
new AuxDecodeConfiguration();
|
private SourceConfiguration mSourceConfiguration = SourceConfigFactory.getDefaultSourceConfiguration();
|
||||||
private SourceConfiguration mSourceConfiguration =
|
private EventLogConfiguration mEventLogConfiguration = new EventLogConfiguration();
|
||||||
SourceConfigFactory.getDefaultSourceConfiguration();
|
|
||||||
private EventLogConfiguration mEventLogConfiguration =
|
|
||||||
new EventLogConfiguration();
|
|
||||||
private RecordConfiguration mRecordConfiguration = new RecordConfiguration();
|
private RecordConfiguration mRecordConfiguration = new RecordConfiguration();
|
||||||
|
|
||||||
private String mAliasListName;
|
private String mAliasListName;
|
||||||
@@ -64,7 +64,9 @@ public class Channel extends Configuration implements Listener<FrequencyChangeEv
|
|||||||
private String mSite = "Site";
|
private String mSite = "Site";
|
||||||
private String mName = "Channel";
|
private String mName = "Channel";
|
||||||
|
|
||||||
private boolean mEnabled;
|
private boolean mProcessing;
|
||||||
|
private boolean mAutoStart;
|
||||||
|
private Integer mAutoStartOrder;
|
||||||
private boolean mSelected;
|
private boolean mSelected;
|
||||||
private TunerChannel mTunerChannel = null;
|
private TunerChannel mTunerChannel = null;
|
||||||
|
|
||||||
@@ -113,6 +115,8 @@ public class Channel extends Configuration implements Listener<FrequencyChangeEv
|
|||||||
channel.setSystem(mSystem);
|
channel.setSystem(mSystem);
|
||||||
channel.setSite(mSite);
|
channel.setSite(mSite);
|
||||||
channel.setAliasListName(mAliasListName);
|
channel.setAliasListName(mAliasListName);
|
||||||
|
channel.setAutoStart(mAutoStart);
|
||||||
|
channel.setAutoStartOrder(mAutoStartOrder);
|
||||||
|
|
||||||
AuxDecodeConfiguration aux = new AuxDecodeConfiguration();
|
AuxDecodeConfiguration aux = new AuxDecodeConfiguration();
|
||||||
|
|
||||||
@@ -258,27 +262,90 @@ public class Channel extends Configuration implements Listener<FrequencyChangeEv
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if this channel is enabled for processing.
|
* Indicates if this channel is currently started and processing.
|
||||||
*/
|
*/
|
||||||
@JacksonXmlProperty(isAttribute = true, localName = "enabled")
|
@JsonIgnore
|
||||||
public boolean getEnabled()
|
public boolean isProcessing()
|
||||||
{
|
{
|
||||||
return mEnabled;
|
return mProcessing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if this channel will automatically start processing on
|
* Indicates if this channel is currently started and processing.
|
||||||
* application startup or if this channel is currently processing after
|
|
||||||
* application startup.
|
|
||||||
*
|
*
|
||||||
* Note: this method is package private and is intended to be managed
|
* Note: this method is package private and is intended to be managed by a channel processing manager instance
|
||||||
* by a co-package central processing manager
|
|
||||||
*
|
*
|
||||||
* @see ChannelProcessingManager
|
* @see ChannelProcessingManager
|
||||||
*/
|
*/
|
||||||
void setEnabled(boolean enabled)
|
void setProcessing(boolean processing)
|
||||||
{
|
{
|
||||||
mEnabled = enabled;
|
mProcessing = processing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this channel has auto-start enabled.
|
||||||
|
*
|
||||||
|
* Note: the Json (de)serialization tag for auto-start is 'enabled'. We've re-purposed the now
|
||||||
|
* transient enabled property for the auto-start persisted value to maintain backward compatibility.
|
||||||
|
*
|
||||||
|
* @return true if this channel should be auto-started on application startup
|
||||||
|
*/
|
||||||
|
@JacksonXmlProperty(isAttribute = true, localName = "enabled")
|
||||||
|
public boolean getAutoStart()
|
||||||
|
{
|
||||||
|
return mAutoStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this channel is set for auto-start
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isAutoStart()
|
||||||
|
{
|
||||||
|
return mAutoStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the auto-start status for this channel.
|
||||||
|
*
|
||||||
|
* @param autoStart
|
||||||
|
*/
|
||||||
|
public void setAutoStart(boolean autoStart)
|
||||||
|
{
|
||||||
|
mAutoStart = autoStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-start order. Specifies an optional ordering for channels so that when the application starts up,
|
||||||
|
* the channels can be started in a user-specified order.
|
||||||
|
*
|
||||||
|
* @return auto-start order or null
|
||||||
|
*/
|
||||||
|
@JacksonXmlProperty(isAttribute = true, localName = "order")
|
||||||
|
public Integer getAutoStartOrder()
|
||||||
|
{
|
||||||
|
return mAutoStartOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the auto-start order for this channel
|
||||||
|
*
|
||||||
|
* @param order
|
||||||
|
*/
|
||||||
|
public void setAutoStartOrder(Integer order)
|
||||||
|
{
|
||||||
|
mAutoStartOrder = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this channel has an auto-start order specified (ie non-null).
|
||||||
|
*
|
||||||
|
* @return true if this channel has an auto-start order
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean hasAutoStartOrder()
|
||||||
|
{
|
||||||
|
return mAutoStartOrder != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,246 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
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<Channel> 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<Channel> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,11 +8,19 @@ import net.coderazzi.filters.gui.AutoChoices;
|
|||||||
import net.coderazzi.filters.gui.TableFilterHeader;
|
import net.coderazzi.filters.gui.TableFilterHeader;
|
||||||
import net.miginfocom.swing.MigLayout;
|
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.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
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.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
@@ -236,7 +244,7 @@ public class ChannelController extends JPanel
|
|||||||
|
|
||||||
Channel channel = model.getChannelAtIndex( index );
|
Channel channel = model.getChannelAtIndex( index );
|
||||||
|
|
||||||
boolean enabled = channel.getEnabled();
|
boolean enabled = channel.isProcessing();
|
||||||
|
|
||||||
if( isSelected )
|
if( isSelected )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* SDR Trunk
|
* SDR Trunk
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -30,221 +30,227 @@ import io.github.dsheirer.source.SourceConfigurationEditor;
|
|||||||
import io.github.dsheirer.source.SourceManager;
|
import io.github.dsheirer.source.SourceManager;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JButton;
|
||||||
import java.awt.*;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
public class ChannelEditor extends Editor<Channel> implements ActionListener, ChannelEventListener
|
public class ChannelEditor extends Editor<Channel> 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 SourceConfigurationEditor mSourceConfigurationEditor;
|
||||||
private DecodeConfigurationEditor mDecodeConfigurationEditor;
|
private DecodeConfigurationEditor mDecodeConfigurationEditor;
|
||||||
private AuxDecodeConfigurationEditor mAuxDecodeConfigurationEditor;
|
private AuxDecodeConfigurationEditor mAuxDecodeConfigurationEditor;
|
||||||
private EventLogConfigurationEditor mEventLogConfigurationEditor;
|
private EventLogConfigurationEditor mEventLogConfigurationEditor;
|
||||||
private RecordConfigurationEditor mRecordConfigurationEditor;
|
private RecordConfigurationEditor mRecordConfigurationEditor;
|
||||||
|
|
||||||
private JButton mEnableButton = new JButton( "Enable" );
|
private JButton mProcessingStateButton = new JButton(ACTION_START);
|
||||||
private JLabel mChannelName = new JLabel( "Channel:" );
|
private JLabel mChannelName = new JLabel("Channel:");
|
||||||
|
|
||||||
private ChannelModel mChannelModel;
|
private ChannelModel mChannelModel;
|
||||||
private ChannelMapModel mChannelMapModel;
|
private ChannelMapModel mChannelMapModel;
|
||||||
private SourceManager mSourceManager;
|
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 );
|
private boolean mChannelStartRequested = false;
|
||||||
|
|
||||||
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();
|
public ChannelEditor(ChannelModel channelModel,
|
||||||
mAuxDecodeConfigurationEditor.setSaveRequestListener( this );
|
ChannelMapModel channelMapModel,
|
||||||
tabs.addTab( "Aux Decoders", mAuxDecodeConfigurationEditor );
|
SourceManager sourceManager,
|
||||||
|
AliasModel aliasModel)
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
String command = e.getActionCommand();
|
mChannelModel = channelModel;
|
||||||
|
mChannelMapModel = channelMapModel;
|
||||||
if( command.contentEquals( "Enable" ) )
|
mSourceManager = sourceManager;
|
||||||
{
|
mNameConfigurationEditor = new NameConfigurationEditor(aliasModel, mChannelModel);
|
||||||
if( hasItem() )
|
|
||||||
{
|
init();
|
||||||
save();
|
}
|
||||||
|
|
||||||
mChannelEnableRequested = true;
|
private void init()
|
||||||
mChannelModel.broadcast( new ChannelEvent( getItem(), ChannelEvent.Event.REQUEST_ENABLE ) );
|
{
|
||||||
}
|
setLayout(new MigLayout("fill,wrap 3", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]"));
|
||||||
}
|
|
||||||
else if( command.contentEquals( "Disable" ) )
|
JideTabbedPane tabs = new JideTabbedPane();
|
||||||
{
|
tabs.setFont(this.getFont());
|
||||||
if( hasItem() )
|
tabs.setForeground(Color.BLACK);
|
||||||
{
|
|
||||||
mChannelModel.broadcast( new ChannelEvent( getItem(), ChannelEvent.Event.REQUEST_DISABLE ) );
|
tabs.setTabTrailingComponent(mChannelName);
|
||||||
}
|
|
||||||
}
|
mNameConfigurationEditor.setSaveRequestListener(this);
|
||||||
else if( command.contentEquals( "Save" ) )
|
tabs.addTab("Name/Alias", mNameConfigurationEditor);
|
||||||
{
|
|
||||||
save();
|
mSourceConfigurationEditor = new SourceConfigurationEditor(mSourceManager);
|
||||||
}
|
mSourceConfigurationEditor.setSaveRequestListener(this);
|
||||||
else if( command.contentEquals( "Reset" ) )
|
tabs.addTab("Source", mSourceConfigurationEditor);
|
||||||
{
|
|
||||||
setItem( getItem() );
|
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()
|
public void save()
|
||||||
{
|
{
|
||||||
if( hasItem() )
|
if(hasItem())
|
||||||
{
|
{
|
||||||
mNameConfigurationEditor.save();
|
mNameConfigurationEditor.save();
|
||||||
mSourceConfigurationEditor.save();
|
mSourceConfigurationEditor.save();
|
||||||
mDecodeConfigurationEditor.save();
|
mDecodeConfigurationEditor.save();
|
||||||
mAuxDecodeConfigurationEditor.save();
|
mAuxDecodeConfigurationEditor.save();
|
||||||
mEventLogConfigurationEditor.save();
|
mEventLogConfigurationEditor.save();
|
||||||
mRecordConfigurationEditor.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mChannelModel.broadcast( new ChannelEvent( getItem(),
|
try
|
||||||
ChannelEvent.Event.NOTIFICATION_CONFIGURATION_CHANGE ) );
|
{
|
||||||
}
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* SDR Trunk
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,6 +42,11 @@ public class ChannelEvent
|
|||||||
{
|
{
|
||||||
return mEvent;
|
return mEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getEvent().name() + " Channel:" + getChannel().getName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Channel events to describe the specific event
|
* Channel events to describe the specific event
|
||||||
@@ -55,7 +60,7 @@ public class ChannelEvent
|
|||||||
//Channel is deleted/removed
|
//Channel is deleted/removed
|
||||||
NOTIFICATION_DELETE,
|
NOTIFICATION_DELETE,
|
||||||
//Channel enable request was rejected
|
//Channel enable request was rejected
|
||||||
NOTIFICATION_ENABLE_REJECTED,
|
NOTIFICATION_START_PROCESSING_REJECTED,
|
||||||
//Channel has started processing/decoding
|
//Channel has started processing/decoding
|
||||||
NOTIFICATION_PROCESSING_START,
|
NOTIFICATION_PROCESSING_START,
|
||||||
//Channel has stopped processing/decoding
|
//Channel has stopped processing/decoding
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import io.github.dsheirer.module.decode.DecoderType;
|
|||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
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_ALIAS_LIST = 4;
|
||||||
public static final int COLUMN_SOURCE = 5;
|
public static final int COLUMN_SOURCE = 5;
|
||||||
public static final int COLUMN_DECODER = 6;
|
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",
|
private static final String[] COLUMN_NAMES = new String[] {"Playing", "System", "Site", "Name", "Alias List",
|
||||||
"Source", "Decoder"};
|
"Source", "Decoder", "Auto-Start"};
|
||||||
|
private static final String VALUE_YES = "Yes";
|
||||||
|
|
||||||
private List<Channel> mChannels = new CopyOnWriteArrayList<>();
|
private List<Channel> mChannels = new CopyOnWriteArrayList<>();
|
||||||
private List<Channel> mTrafficChannels = new CopyOnWriteArrayList<>();
|
private List<Channel> mTrafficChannels = new CopyOnWriteArrayList<>();
|
||||||
@@ -209,11 +212,6 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
|
|||||||
|
|
||||||
broadcast(new ChannelEvent(channel, Event.NOTIFICATION_ADD));
|
broadcast(new ChannelEvent(channel, Event.NOTIFICATION_ADD));
|
||||||
|
|
||||||
if(channel.getEnabled())
|
|
||||||
{
|
|
||||||
broadcast(new ChannelEvent(channel, Event.REQUEST_ENABLE));
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
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<Channel> getAutoStartChannels()
|
||||||
|
{
|
||||||
|
List<Channel> autoStartChannels = new ArrayList<>();
|
||||||
|
|
||||||
|
for(Channel channel: getChannels())
|
||||||
|
{
|
||||||
|
if(channel.isAutoStart())
|
||||||
|
{
|
||||||
|
autoStartChannels.add(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(autoStartChannels, new Comparator<Channel>()
|
||||||
|
{
|
||||||
|
@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
|
* Returns a list of channels that fall within the frequency range
|
||||||
*
|
*
|
||||||
@@ -331,7 +371,7 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
|
|||||||
switch(columnIndex)
|
switch(columnIndex)
|
||||||
{
|
{
|
||||||
case COLUMN_ENABLED:
|
case COLUMN_ENABLED:
|
||||||
return channel.getEnabled() ? "Enabled" : null;
|
return channel.isProcessing() ? VALUE_YES : null;
|
||||||
case COLUMN_SYSTEM:
|
case COLUMN_SYSTEM:
|
||||||
return channel.getSystem();
|
return channel.getSystem();
|
||||||
case COLUMN_SITE:
|
case COLUMN_SITE:
|
||||||
@@ -344,6 +384,19 @@ public class ChannelModel extends AbstractTableModel implements IChannelEventBro
|
|||||||
return channel.getSourceConfiguration().getDescription();
|
return channel.getSourceConfiguration().getDescription();
|
||||||
case COLUMN_DECODER:
|
case COLUMN_DECODER:
|
||||||
return channel.getDecodeConfiguration().getDecoderType().getShortDisplayString();
|
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;
|
return null;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REQUEST_DISABLE:
|
case REQUEST_DISABLE:
|
||||||
if(channel.getEnabled())
|
if(channel.isProcessing())
|
||||||
{
|
{
|
||||||
switch(channel.getChannelType())
|
switch(channel.getChannelType())
|
||||||
{
|
{
|
||||||
@@ -176,7 +176,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case NOTIFICATION_DELETE:
|
case NOTIFICATION_DELETE:
|
||||||
if(channel.getEnabled())
|
if(channel.isProcessing())
|
||||||
{
|
{
|
||||||
stopProcessing(channel, true);
|
stopProcessing(channel, true);
|
||||||
}
|
}
|
||||||
@@ -220,9 +220,9 @@ public class ChannelProcessingManager implements ChannelEventListener
|
|||||||
|
|
||||||
if(source == null)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
|||||||
|
|
||||||
getChannelMetadataModel().add(processingChain.getChannelState().getMutableMetadata(), channel);
|
getChannelMetadataModel().add(processingChain.getChannelState().getMutableMetadata(), channel);
|
||||||
|
|
||||||
channel.setEnabled(true);
|
channel.setProcessing(true);
|
||||||
|
|
||||||
mProcessingChains.put(channel.getChannelID(), processingChain);
|
mProcessingChains.put(channel.getChannelID(), processingChain);
|
||||||
|
|
||||||
@@ -334,7 +334,7 @@ public class ChannelProcessingManager implements ChannelEventListener
|
|||||||
|
|
||||||
private void stopProcessing(Channel channel, boolean remove)
|
private void stopProcessing(Channel channel, boolean remove)
|
||||||
{
|
{
|
||||||
channel.setEnabled(false);
|
channel.setProcessing(false);
|
||||||
|
|
||||||
if(mProcessingChains.containsKey(channel.getChannelID()))
|
if(mProcessingChains.containsKey(channel.getChannelID()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ import io.github.dsheirer.channel.state.DecoderState;
|
|||||||
import io.github.dsheirer.module.ProcessingChain;
|
import io.github.dsheirer.module.ProcessingChain;
|
||||||
import io.github.dsheirer.module.decode.event.ActivitySummaryFrame;
|
import io.github.dsheirer.module.decode.event.ActivitySummaryFrame;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JMenu;
|
||||||
import java.awt.*;
|
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.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
@@ -23,7 +26,7 @@ public class ChannelUtils
|
|||||||
{
|
{
|
||||||
JMenu menu = new JMenu( "Channel: " + channel.getName() );
|
JMenu menu = new JMenu( "Channel: " + channel.getName() );
|
||||||
|
|
||||||
if( channel.getEnabled() )
|
if( channel.isProcessing() )
|
||||||
{
|
{
|
||||||
JMenuItem disable = new JMenuItem( "Disable" );
|
JMenuItem disable = new JMenuItem( "Disable" );
|
||||||
disable.addActionListener( new ActionListener()
|
disable.addActionListener( new ActionListener()
|
||||||
|
|||||||
@@ -23,9 +23,21 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -48,6 +60,8 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
|
|||||||
private JComboBox<String> mSystemNameCombo;
|
private JComboBox<String> mSystemNameCombo;
|
||||||
private JComboBox<String> mSiteNameCombo;
|
private JComboBox<String> mSiteNameCombo;
|
||||||
private JComboBox<String> mAliasListCombo;
|
private JComboBox<String> mAliasListCombo;
|
||||||
|
private JCheckBox mAutoStartCheckBox;
|
||||||
|
private JSpinner mAutoStartOrder;
|
||||||
|
|
||||||
public NameConfigurationEditor(AliasModel aliasModel, ChannelModel model)
|
public NameConfigurationEditor(AliasModel aliasModel, ChannelModel model)
|
||||||
{
|
{
|
||||||
@@ -139,6 +153,40 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
|
|||||||
|
|
||||||
add(new JLabel("Site:"));
|
add(new JLabel("Site:"));
|
||||||
add(mSiteNameCombo);
|
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
|
@Override
|
||||||
@@ -156,6 +204,11 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
|
|||||||
|
|
||||||
Object aliasList = mAliasListCombo.getSelectedItem();
|
Object aliasList = mAliasListCombo.getSelectedItem();
|
||||||
getItem().setAliasListName(aliasList == null ? null : (String)aliasList);
|
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);
|
setModified(false);
|
||||||
@@ -182,6 +235,16 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
|
|||||||
{
|
{
|
||||||
mSiteNameCombo.setEnabled(enabled);
|
mSiteNameCombo.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mAutoStartCheckBox.isEnabled() != enabled)
|
||||||
|
{
|
||||||
|
mAutoStartCheckBox.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mAutoStartOrder.isEnabled() != enabled)
|
||||||
|
{
|
||||||
|
mAutoStartOrder.setEnabled(enabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,6 +307,19 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
|
|||||||
mChannelName.setText(null);
|
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);
|
setModified(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import io.github.dsheirer.audio.AudioManager;
|
|||||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
|
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
|
||||||
import io.github.dsheirer.controller.ControllerPanel;
|
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.ChannelModel;
|
||||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||||
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
||||||
@@ -51,8 +53,19 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
import java.awt.*;
|
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.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
@@ -61,6 +74,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class SDRTrunk implements Listener<TunerEvent>
|
public class SDRTrunk implements Listener<TunerEvent>
|
||||||
{
|
{
|
||||||
@@ -72,6 +86,8 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||||
private BroadcastModel mBroadcastModel;
|
private BroadcastModel mBroadcastModel;
|
||||||
private ControllerPanel mControllerPanel;
|
private ControllerPanel mControllerPanel;
|
||||||
|
private ChannelModel mChannelModel;
|
||||||
|
private ChannelProcessingManager mChannelProcessingManager;
|
||||||
private SettingsManager mSettingsManager;
|
private SettingsManager mSettingsManager;
|
||||||
private SpectralDisplayPanel mSpectralPanel;
|
private SpectralDisplayPanel mSpectralPanel;
|
||||||
private JFrame mMainGui = new JFrame();
|
private JFrame mMainGui = new JFrame();
|
||||||
@@ -117,7 +133,7 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
|
|
||||||
AliasModel aliasModel = new AliasModel();
|
AliasModel aliasModel = new AliasModel();
|
||||||
|
|
||||||
ChannelModel channelModel = new ChannelModel();
|
mChannelModel = new ChannelModel();
|
||||||
|
|
||||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||||
|
|
||||||
@@ -127,43 +143,42 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
|
|
||||||
SourceManager sourceManager = new SourceManager(tunerModel, mSettingsManager);
|
SourceManager sourceManager = new SourceManager(tunerModel, mSettingsManager);
|
||||||
|
|
||||||
ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(
|
mChannelProcessingManager = new ChannelProcessingManager(mChannelModel, channelMapModel, aliasModel,
|
||||||
channelModel, channelMapModel, aliasModel, eventLogManager, recorderManager, sourceManager);
|
eventLogManager, recorderManager, sourceManager);
|
||||||
channelProcessingManager.addAudioPacketListener(recorderManager);
|
mChannelProcessingManager.addAudioPacketListener(recorderManager);
|
||||||
|
|
||||||
channelModel.addListener(channelProcessingManager);
|
mChannelModel.addListener(mChannelProcessingManager);
|
||||||
|
|
||||||
ChannelSelectionManager channelSelectionManager =
|
ChannelSelectionManager channelSelectionManager =
|
||||||
new ChannelSelectionManager(channelModel);
|
new ChannelSelectionManager(mChannelModel);
|
||||||
channelModel.addListener(channelSelectionManager);
|
mChannelModel.addListener(channelSelectionManager);
|
||||||
|
|
||||||
AliasActionManager aliasActionManager = new AliasActionManager();
|
AliasActionManager aliasActionManager = new AliasActionManager();
|
||||||
channelProcessingManager.addMessageListener(aliasActionManager);
|
mChannelProcessingManager.addMessageListener(aliasActionManager);
|
||||||
|
|
||||||
AudioManager audioManager = new AudioManager(sourceManager.getMixerManager());
|
AudioManager audioManager = new AudioManager(sourceManager.getMixerManager());
|
||||||
channelProcessingManager.addAudioPacketListener(audioManager);
|
mChannelProcessingManager.addAudioPacketListener(audioManager);
|
||||||
|
|
||||||
mBroadcastModel = new BroadcastModel(mIconManager);
|
mBroadcastModel = new BroadcastModel(mIconManager);
|
||||||
|
|
||||||
channelProcessingManager.addAudioPacketListener(mBroadcastModel);
|
mChannelProcessingManager.addAudioPacketListener(mBroadcastModel);
|
||||||
|
|
||||||
MapService mapService = new MapService(mIconManager);
|
MapService mapService = new MapService(mIconManager);
|
||||||
channelProcessingManager.addMessageListener(mapService);
|
mChannelProcessingManager.addMessageListener(mapService);
|
||||||
|
|
||||||
mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel,
|
mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel,
|
||||||
channelModel, channelMapModel, channelProcessingManager, mIconManager,
|
mChannelModel, channelMapModel, mChannelProcessingManager, mIconManager,
|
||||||
mapService, mSettingsManager, sourceManager, tunerModel);
|
mapService, mSettingsManager, sourceManager, tunerModel);
|
||||||
|
|
||||||
mSpectralPanel = new SpectralDisplayPanel(channelModel,
|
mSpectralPanel = new SpectralDisplayPanel(mChannelModel,
|
||||||
channelProcessingManager, mSettingsManager);
|
mChannelProcessingManager, mSettingsManager);
|
||||||
|
|
||||||
TunerSpectralDisplayManager tunerSpectralDisplayManager =
|
TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
|
||||||
new TunerSpectralDisplayManager(mSpectralPanel,
|
mChannelModel, mChannelProcessingManager, mSettingsManager);
|
||||||
channelModel, channelProcessingManager, mSettingsManager);
|
|
||||||
tunerModel.addListener(tunerSpectralDisplayManager);
|
tunerModel.addListener(tunerSpectralDisplayManager);
|
||||||
tunerModel.addListener(this);
|
tunerModel.addListener(this);
|
||||||
|
|
||||||
PlaylistManager playlistManager = new PlaylistManager(aliasModel, mBroadcastModel, channelModel,
|
PlaylistManager playlistManager = new PlaylistManager(aliasModel, mBroadcastModel, mChannelModel,
|
||||||
channelMapModel);
|
channelMapModel);
|
||||||
|
|
||||||
playlistManager.init();
|
playlistManager.init();
|
||||||
@@ -183,6 +198,7 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
mMainGui.setVisible(true);
|
mMainGui.setVisible(true);
|
||||||
|
autoStartChannels();
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@@ -192,6 +208,21 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<Channel> channels = mChannelModel.getAutoStartChannels();
|
||||||
|
|
||||||
|
if(channels.size() > 0)
|
||||||
|
{
|
||||||
|
ChannelAutoStartFrame autoStartFrame = new ChannelAutoStartFrame(mChannelProcessingManager, channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch the application.
|
* Launch the application.
|
||||||
*/
|
*/
|
||||||
@@ -212,7 +243,8 @@ public class SDRTrunk implements Listener<TunerEvent>
|
|||||||
*/
|
*/
|
||||||
mTitle = SystemProperties.getInstance().getApplicationName();
|
mTitle = SystemProperties.getInstance().getApplicationName();
|
||||||
mMainGui.setTitle(mTitle);
|
mMainGui.setTitle(mTitle);
|
||||||
mMainGui.setBounds(100, 100, 1280, 800);
|
mMainGui.setSize(new Dimension(1280,800));
|
||||||
|
mMainGui.setLocationRelativeTo(null);
|
||||||
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
|
||||||
//Set preferred sizes to influence the split
|
//Set preferred sizes to influence the split
|
||||||
|
|||||||
@@ -30,8 +30,13 @@ import io.github.dsheirer.spectrum.menu.SmoothingItem;
|
|||||||
import io.github.dsheirer.spectrum.menu.SmoothingTypeItem;
|
import io.github.dsheirer.spectrum.menu.SmoothingTypeItem;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JLayeredPane;
|
||||||
import java.awt.*;
|
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.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
@@ -193,7 +198,7 @@ public class ChannelSpectrumPanel extends JPanel
|
|||||||
|
|
||||||
private void start()
|
private void start()
|
||||||
{
|
{
|
||||||
if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.getEnabled() )
|
if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.isProcessing() )
|
||||||
{
|
{
|
||||||
ProcessingChain processingChain = mChannelProcessingManager
|
ProcessingChain processingChain = mChannelProcessingManager
|
||||||
.getProcessingChain( mCurrentChannel );
|
.getProcessingChain( mCurrentChannel );
|
||||||
@@ -209,7 +214,7 @@ public class ChannelSpectrumPanel extends JPanel
|
|||||||
|
|
||||||
private void stop()
|
private void stop()
|
||||||
{
|
{
|
||||||
if( mCurrentChannel != null && mCurrentChannel.getEnabled() )
|
if( mCurrentChannel != null && mCurrentChannel.isProcessing() )
|
||||||
{
|
{
|
||||||
ProcessingChain processingChain = mChannelProcessingManager
|
ProcessingChain processingChain = mChannelProcessingManager
|
||||||
.getProcessingChain( mCurrentChannel );
|
.getProcessingChain( mCurrentChannel );
|
||||||
|
|||||||
@@ -34,8 +34,16 @@ import io.github.dsheirer.source.tuner.frequency.IFrequencyChangeProcessor;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JPanel;
|
||||||
import java.awt.*;
|
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.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
import java.awt.geom.Line2D;
|
import java.awt.geom.Line2D;
|
||||||
@@ -517,14 +525,14 @@ public class OverlayPanel extends JPanel implements ChannelEventListener, IFrequ
|
|||||||
for(Channel channel : mVisibleChannels)
|
for(Channel channel : mVisibleChannels)
|
||||||
{
|
{
|
||||||
if(mChannelDisplay == ChannelDisplay.ALL ||
|
if(mChannelDisplay == ChannelDisplay.ALL ||
|
||||||
(mChannelDisplay == ChannelDisplay.ENABLED && channel.getEnabled()))
|
(mChannelDisplay == ChannelDisplay.ENABLED && channel.isProcessing()))
|
||||||
{
|
{
|
||||||
//Choose the correct background color to use
|
//Choose the correct background color to use
|
||||||
if(channel.isSelected())
|
if(channel.isSelected())
|
||||||
{
|
{
|
||||||
graphics.setColor(mColorChannelConfigSelected);
|
graphics.setColor(mColorChannelConfigSelected);
|
||||||
}
|
}
|
||||||
else if(channel.getEnabled())
|
else if(channel.isProcessing())
|
||||||
{
|
{
|
||||||
graphics.setColor(mColorChannelConfigProcessing);
|
graphics.setColor(mColorChannelConfigProcessing);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user