Fully implements application shutdown procedure that is invoked when the

user closes the the main gui window or invokes exit from the file menu.
This commit is contained in:
Denny
2018-07-14 14:44:03 -04:00
parent 8c237be682
commit 20a8f2bb3c
13 changed files with 195 additions and 35 deletions

View File

@@ -363,6 +363,22 @@ public class ChannelProcessingManager implements ChannelEventListener
} }
} }
/**
* Stops all currently processing channels to prepare for shutdown.
*/
public void shutdown()
{
mLog.debug("Stopping Channels ...");
for(Channel channel: mChannelModel.getChannels())
{
if(channel.isProcessing())
{
mLog.debug("Stopping channel: " + channel.toString());
stopProcessing(channel, true);
}
}
}
/** /**
* Adds a message listener that will be added to all channels to receive * Adds a message listener that will be added to all channels to receive
* any messages. * any messages.

View File

@@ -69,6 +69,8 @@ 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;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
@@ -88,6 +90,7 @@ public class SDRTrunk implements Listener<TunerEvent>
private ControllerPanel mControllerPanel; private ControllerPanel mControllerPanel;
private ChannelModel mChannelModel; private ChannelModel mChannelModel;
private ChannelProcessingManager mChannelProcessingManager; private ChannelProcessingManager mChannelProcessingManager;
private SourceManager mSourceManager;
private SettingsManager mSettingsManager; private SettingsManager mSettingsManager;
private SpectralDisplayPanel mSpectralPanel; private SpectralDisplayPanel mSpectralPanel;
private JFrame mMainGui = new JFrame(); private JFrame mMainGui = new JFrame();
@@ -141,10 +144,10 @@ public class SDRTrunk implements Listener<TunerEvent>
RecorderManager recorderManager = new RecorderManager(); RecorderManager recorderManager = new RecorderManager();
SourceManager sourceManager = new SourceManager(tunerModel, mSettingsManager); mSourceManager = new SourceManager(tunerModel, mSettingsManager);
mChannelProcessingManager = new ChannelProcessingManager(mChannelModel, channelMapModel, aliasModel, mChannelProcessingManager = new ChannelProcessingManager(mChannelModel, channelMapModel, aliasModel,
eventLogManager, recorderManager, sourceManager); eventLogManager, recorderManager, mSourceManager);
mChannelProcessingManager.addAudioPacketListener(recorderManager); mChannelProcessingManager.addAudioPacketListener(recorderManager);
mChannelModel.addListener(mChannelProcessingManager); mChannelModel.addListener(mChannelProcessingManager);
@@ -156,7 +159,7 @@ public class SDRTrunk implements Listener<TunerEvent>
AliasActionManager aliasActionManager = new AliasActionManager(); AliasActionManager aliasActionManager = new AliasActionManager();
mChannelProcessingManager.addMessageListener(aliasActionManager); mChannelProcessingManager.addMessageListener(aliasActionManager);
AudioManager audioManager = new AudioManager(sourceManager.getMixerManager()); AudioManager audioManager = new AudioManager(mSourceManager.getMixerManager());
mChannelProcessingManager.addAudioPacketListener(audioManager); mChannelProcessingManager.addAudioPacketListener(audioManager);
mBroadcastModel = new BroadcastModel(mIconManager); mBroadcastModel = new BroadcastModel(mIconManager);
@@ -168,13 +171,13 @@ public class SDRTrunk implements Listener<TunerEvent>
mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel, mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel,
mChannelModel, channelMapModel, mChannelProcessingManager, mIconManager, mChannelModel, channelMapModel, mChannelProcessingManager, mIconManager,
mapService, mSettingsManager, sourceManager, tunerModel); mapService, mSettingsManager, mSourceManager, tunerModel);
mSpectralPanel = new SpectralDisplayPanel(mChannelModel, mSpectralPanel = new SpectralDisplayPanel(mChannelModel,
mChannelProcessingManager, mSettingsManager); mChannelProcessingManager, mSettingsManager);
TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel, TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
mChannelModel, mChannelProcessingManager, mSettingsManager); mChannelModel, mChannelProcessingManager, mSettingsManager);
tunerModel.addListener(tunerSpectralDisplayManager); tunerModel.addListener(tunerSpectralDisplayManager);
tunerModel.addListener(this); tunerModel.addListener(this);
@@ -223,14 +226,6 @@ public class SDRTrunk implements Listener<TunerEvent>
} }
} }
/**
* Launch the application.
*/
public static void main(String[] args)
{
new SDRTrunk();
}
/** /**
* Initialize the contents of the frame. * Initialize the contents of the frame.
*/ */
@@ -243,9 +238,10 @@ public class SDRTrunk implements Listener<TunerEvent>
*/ */
mTitle = SystemProperties.getInstance().getApplicationName(); mTitle = SystemProperties.getInstance().getApplicationName();
mMainGui.setTitle(mTitle); mMainGui.setTitle(mTitle);
mMainGui.setSize(new Dimension(1280,800)); mMainGui.setSize(new Dimension(1280, 800));
mMainGui.setLocationRelativeTo(null); mMainGui.setLocationRelativeTo(null);
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mMainGui.addWindowListener(new ShutdownMonitor());
//Set preferred sizes to influence the split //Set preferred sizes to influence the split
mSpectralPanel.setPreferredSize(new Dimension(1280, 300)); mSpectralPanel.setPreferredSize(new Dimension(1280, 300));
@@ -318,6 +314,7 @@ public class SDRTrunk implements Listener<TunerEvent>
{ {
public void actionPerformed(ActionEvent event) public void actionPerformed(ActionEvent event)
{ {
processShutdown();
System.exit(0); System.exit(0);
} }
} }
@@ -400,6 +397,21 @@ public class SDRTrunk implements Listener<TunerEvent>
menuBar.add(screenCaptureItem); menuBar.add(screenCaptureItem);
} }
/**
* Performs shutdown operations
*/
private void processShutdown()
{
mLog.debug("Application shutdown started ...");
mLog.debug("Stopping channels ...");
mChannelProcessingManager.shutdown();
mLog.debug("Stopping spectral display ...");
mSpectralPanel.clearTuner();
mLog.debug("Releasing tuners ...");
mSourceManager.shutdown();
mLog.debug("Shutdown complete.");
}
/** /**
* Lazy constructor for broadcast status panel * Lazy constructor for broadcast status panel
*/ */
@@ -520,6 +532,15 @@ public class SDRTrunk implements Listener<TunerEvent>
} }
} }
public class ShutdownMonitor extends WindowAdapter
{
@Override
public void windowClosing(WindowEvent e)
{
processShutdown();
}
}
public class BroadcastStatusVisibleMenuItem extends JCheckBoxMenuItem public class BroadcastStatusVisibleMenuItem extends JCheckBoxMenuItem
{ {
private ControllerPanel mControllerPanel; private ControllerPanel mControllerPanel;
@@ -543,4 +564,12 @@ public class SDRTrunk implements Listener<TunerEvent>
}); });
} }
} }
/**
* Launch the application.
*/
public static void main(String[] args)
{
new SDRTrunk();
}
} }

View File

@@ -44,6 +44,15 @@ public class SourceManager
//in via the constructor. Perform loading outside of this class. //in via the constructor. Perform loading outside of this class.
} }
/**
* Prepare for shutdown and release all tuners
*/
public void shutdown()
{
mTunerManager.releaseTuners();
mTunerManager.dispose();
}
public MixerManager getMixerManager() public MixerManager getMixerManager()
{ {
return mMixerManager; return mMixerManager;

View File

@@ -98,8 +98,12 @@ public abstract class Tuner implements ISourceEventProcessor
return mName; return mName;
} }
/**
* Dispose and prepare for shutdown
*/
public void dispose() public void dispose()
{ {
getTunerController().dispose();
} }
/** /**

View File

@@ -61,6 +61,11 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
mSourceEventListener = new SourceEventListenerToProcessorAdapter(this); mSourceEventListener = new SourceEventListenerToProcessorAdapter(this);
} }
/**
* Dispose of this tuner controller and prepare for shutdown.
*/
public abstract void dispose();
/** /**
* Implements the ISourceEventListener interface to receive requests from sample consumers * Implements the ISourceEventListener interface to receive requests from sample consumers
*/ */

View File

@@ -1,19 +1,16 @@
/******************************************************************************* /*******************************************************************************
* sdrtrunk * sdr-trunk
* 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
* it under the terms of the GNU General Public License as published by * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* the Free Software Foundation, either version 3 of the License, or * 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
* but WITHOUT ANY WARRANTY; without even the implied warranty of * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* 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 * You should have received a copy of the GNU General Public License along with this program.
* along with this program. If not, see <http://www.gnu.org/licenses/> * If not, see <http://www.gnu.org/licenses/>
* *
******************************************************************************/ ******************************************************************************/
package io.github.dsheirer.source.tuner; package io.github.dsheirer.source.tuner;
@@ -74,7 +71,15 @@ public class TunerManager
*/ */
public void dispose() public void dispose()
{ {
LibUsb.exit(null); mLog.info("Shutting down LibUsb ...");
try
{
LibUsb.exit(null);
}
catch(Exception e)
{
mLog.error("Error shutting down LibUsb", e);
}
} }
/** /**
@@ -217,6 +222,22 @@ public class TunerManager
return new TunerInitStatus(null, "Unknown Device"); return new TunerInitStatus(null, "Unknown Device");
} }
/**
* Releases all tuners in preparation for shutdown
*/
public void releaseTuners()
{
mLog.info("Releasing [" + mTunerModel.getTuners().size() + "] tuner(s) ...");
Tuner tuner = mTunerModel.getTuner(0);
while(tuner != null)
{
mTunerModel.removeTuner(tuner);
tuner.dispose();
tuner = mTunerModel.getTuner(0);
}
}
private TunerInitStatus initAirspyTuner(Device device, private TunerInitStatus initAirspyTuner(Device device,
DeviceDescriptor descriptor) DeviceDescriptor descriptor)
{ {

View File

@@ -180,6 +180,24 @@ public class AirspyTunerController extends USBTunerController
USB_TRANSFER_BUFFER_SIZE); USB_TRANSFER_BUFFER_SIZE);
} }
@Override
public void dispose()
{
if(mDeviceHandle != null)
{
mLog.info("Releasing Airspy Tuner - " + getDeviceInfo().getSerialNumber());
try
{
LibUsb.close(mDeviceHandle);
}
catch(Exception e)
{
mLog.error("error while closing device handle", e);
}
mDeviceHandle = null;
}
}
@Override @Override
protected USBTransferProcessor getUSBTransferProcessor() protected USBTransferProcessor getUSBTransferProcessor()

View File

@@ -37,10 +37,6 @@ public class HackRFTuner extends Tuner
return (HackRFTunerController)getTunerController(); return (HackRFTunerController)getTunerController();
} }
public void dispose()
{
}
@Override @Override
public TunerClass getTunerClass() public TunerClass getTunerClass()
{ {

View File

@@ -157,6 +157,25 @@ public class HackRFTunerController extends USBTunerController
mUSBTransferProcessor = new USBTransferProcessor(name, mDeviceHandle, mNativeBufferConverter, USB_TRANSFER_BUFFER_SIZE); mUSBTransferProcessor = new USBTransferProcessor(name, mDeviceHandle, mNativeBufferConverter, USB_TRANSFER_BUFFER_SIZE);
} }
@Override
public void dispose()
{
if(mDeviceHandle != null)
{
mLog.info("Releasing HackRF Tuner");
try
{
LibUsb.close(mDeviceHandle);
}
catch(Exception e)
{
mLog.error("error while closing device handle", e);
}
mDeviceHandle = null;
}
}
@Override @Override
protected USBTransferProcessor getUSBTransferProcessor() protected USBTransferProcessor getUSBTransferProcessor()
{ {

View File

@@ -38,10 +38,6 @@ public class RTL2832Tuner extends Tuner
mTunerClass = tunerClass; mTunerClass = tunerClass;
} }
public void dispose()
{
}
public RTL2832TunerController getController() public RTL2832TunerController getController()
{ {
return (RTL2832TunerController)getTunerController(); return (RTL2832TunerController)getTunerController();

View File

@@ -256,6 +256,26 @@ public class E4KTunerController extends RTL2832TunerController
USB_TRANSFER_BUFFER_SIZE); USB_TRANSFER_BUFFER_SIZE);
} }
@Override
public void dispose()
{
if(mDeviceHandle != null)
{
mLog.info("Releasing E4000 Tuner");
try
{
LibUsb.close(mDeviceHandle);
}
catch(Exception e)
{
mLog.error("error while closing device handle", e);
}
mDeviceHandle = null;
}
}
/** /**
* Sets the IF filters (mixer, channel and RC) to the correct filter setting * Sets the IF filters (mixer, channel and RC) to the correct filter setting
* for the selected bandwidth/sample rate * for the selected bandwidth/sample rate

View File

@@ -30,6 +30,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.usb4java.Device; import org.usb4java.Device;
import org.usb4java.DeviceDescriptor; import org.usb4java.DeviceDescriptor;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException; import org.usb4java.LibUsbException;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -260,6 +261,26 @@ public class R820TTunerController extends RTL2832TunerController
} }
} }
@Override
public void dispose()
{
mLog.info("Releasing R820T Tuner");
if(mDeviceHandle != null)
{
try
{
LibUsb.close(mDeviceHandle);
}
catch(Exception e)
{
mLog.error("error while closing device handle", e);
}
mDeviceHandle = null;
}
}
/** /**
* Initializes the tuner section. * Initializes the tuner section.
*/ */

View File

@@ -65,6 +65,12 @@ public class TestTunerController extends TunerController
} }
} }
@Override
public void dispose()
{
//no-op
}
@Override @Override
public void addBufferListener(Listener<ReusableComplexBuffer> listener) public void addBufferListener(Listener<ReusableComplexBuffer> listener)
{ {