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 36a3353f..65d6bcbb 100644 --- a/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java +++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelProcessingManager.java @@ -25,6 +25,7 @@ import io.github.dsheirer.channel.metadata.ChannelAndMetadata; import io.github.dsheirer.channel.metadata.ChannelMetadata; import io.github.dsheirer.channel.metadata.ChannelMetadataModel; import io.github.dsheirer.controller.channel.event.ChannelStartProcessingRequest; +import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest; import io.github.dsheirer.controller.channel.event.PreloadDataContent; import io.github.dsheirer.controller.channel.map.ChannelMapModel; import io.github.dsheirer.identifier.Form; @@ -46,12 +47,9 @@ import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.config.SourceConfigTuner; import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency; +import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.manager.TunerManager; import io.github.dsheirer.util.ThreadPool; -import javafx.application.Platform; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.GraphicsEnvironment; import java.util.ArrayList; import java.util.List; @@ -62,6 +60,9 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import javafx.application.Platform; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Channel processing manager handles all starting and stopping of channel decoding. A processing chain is created @@ -124,7 +125,20 @@ public class ChannelProcessingManager implements Listener */ private boolean isProcessing(Channel channel) { - return mProcessingChains.containsKey(channel) && mProcessingChains.get(channel).isProcessing(); + boolean isProcessing = false; + + mLock.lock(); + + try + { + isProcessing = mProcessingChains.containsKey(channel) && mProcessingChains.get(channel).isProcessing(); + } + finally + { + mLock.unlock(); + } + + return isProcessing; } /** @@ -153,18 +167,60 @@ public class ChannelProcessingManager implements Listener */ public Channel getChannel(ProcessingChain processingChain) { + Channel channel = null; + if(processingChain != null) { - for(Map.Entry entry : mProcessingChains.entrySet()) + mLock.lock(); + + try { - if(entry.getValue() == processingChain) + for(Map.Entry entry : mProcessingChains.entrySet()) { - return entry.getKey(); + if(entry.getValue() == processingChain) + { + channel = entry.getKey(); + break; + } } } + finally + { + mLock.unlock(); + } } - return null; + return channel; + } + + /** + * Retrieves the channel associated with the processing chain that is consuming from the tuner channel source + * @param tunerChannelSource to find the channel + * @return channel + */ + private Channel getChannel(TunerChannelSource tunerChannelSource) + { + Channel channel = null; + + mLock.lock(); + + try + { + for(Map.Entry entry : mProcessingChains.entrySet()) + { + if(entry.getValue().hasSource(tunerChannelSource)) + { + channel = entry.getKey(); + break; + } + } + } + finally + { + mLock.unlock(); + } + + return channel; } /** @@ -273,6 +329,28 @@ public class ChannelProcessingManager implements Listener } } + /** + * Request to stop a channel that is currently processing + * @param request with the tuner channel source feeding the channel to be stopped. + */ + @Subscribe + public void stopChannelRequest(ChannelStopProcessingRequest request) + { + Channel channel = getChannel(request.getTunerChannelSource()); + + if(channel != null) + { + try + { + stop(channel); + } + catch(ChannelException ce) + { + mLog.error("Error stopping channel [" + channel + "]", ce); + } + } + } + /** * Stops the specified channel * @param channel to stop @@ -720,9 +798,7 @@ public class ChannelProcessingManager implements Listener { @Override public void receive(SourceEvent sourceEvent) { - if((sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE || - sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_TUNER_SHUTDOWN) && - sourceEvent.getSource() != null) + if(sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE && sourceEvent.getSource() != null) { Channel toShutdown = null; @@ -750,10 +826,6 @@ public class ChannelProcessingManager implements Listener { mLog.warn("Channel source error detected - stopping channel [" + toShutdown.getName() + "]"); } - else if(sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_TUNER_SHUTDOWN) - { - mLog.warn("Tuner removal detected - stopping channel [" + toShutdown.getName() + "]"); - } else { mLog.warn("Source event error - stopping channel [" + toShutdown.getName() + "]"); diff --git a/src/main/java/io/github/dsheirer/controller/channel/event/ChannelStopProcessingRequest.java b/src/main/java/io/github/dsheirer/controller/channel/event/ChannelStopProcessingRequest.java new file mode 100644 index 00000000..a9976374 --- /dev/null +++ b/src/main/java/io/github/dsheirer/controller/channel/event/ChannelStopProcessingRequest.java @@ -0,0 +1,44 @@ +/* + * ***************************************************************************** + * Copyright (C) 2014-2022 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.event; + +import io.github.dsheirer.module.ModuleEventBusMessage; +import io.github.dsheirer.source.tuner.channel.TunerChannelSource; + +/** + * Request to stop processing a channel for a specific tuner channel source + */ +public class ChannelStopProcessingRequest extends ModuleEventBusMessage +{ + private TunerChannelSource mTunerChannelSource; + /** + * Constructs an instance + * @param tunerChannelSource for the channel to stop + */ + public ChannelStopProcessingRequest(TunerChannelSource tunerChannelSource) + { + mTunerChannelSource = tunerChannelSource; + } + + public TunerChannelSource getTunerChannelSource() + { + return mTunerChannelSource; + } +} diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java index 9963de6e..8ea8ee2a 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java @@ -21,11 +21,13 @@ package io.github.dsheirer.dsp.filter.channelizer; import io.github.dsheirer.buffer.INativeBuffer; import io.github.dsheirer.buffer.INativeBufferProvider; import io.github.dsheirer.buffer.NativeBufferPoisonPill; +import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest; import io.github.dsheirer.dsp.filter.FilterFactory; import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor; import io.github.dsheirer.dsp.filter.channelizer.output.OneChannelOutputProcessor; import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcessor; import io.github.dsheirer.dsp.filter.design.FilterDesignException; +import io.github.dsheirer.eventbus.MyEventBus; import io.github.dsheirer.sample.Broadcaster; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.complex.InterleavedComplexSamples; @@ -37,10 +39,6 @@ import io.github.dsheirer.source.tuner.TunerController; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.util.Dispatcher; -import org.apache.commons.math3.util.FastMath; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -51,6 +49,9 @@ import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArrayList; +import org.apache.commons.math3.util.FastMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Polyphase Channel Manager is a DDC channel manager and complex buffer queue/processor for a tuner. This class @@ -136,14 +137,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor for(TunerChannelSource tunerChannelSource: toStop) { - try - { - tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource)); - } - catch(SourceException se) - { - mLog.error("Error stopping tuner channel source for tuner shutdown"); - } + MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource)); } } diff --git a/src/main/java/io/github/dsheirer/playlist/PlaylistManager.java b/src/main/java/io/github/dsheirer/playlist/PlaylistManager.java index 95c7c7ce..c5738170 100644 --- a/src/main/java/io/github/dsheirer/playlist/PlaylistManager.java +++ b/src/main/java/io/github/dsheirer/playlist/PlaylistManager.java @@ -32,6 +32,7 @@ import io.github.dsheirer.controller.channel.ChannelModel; import io.github.dsheirer.controller.channel.ChannelProcessingManager; import io.github.dsheirer.controller.channel.map.ChannelMap; import io.github.dsheirer.controller.channel.map.ChannelMapModel; +import io.github.dsheirer.eventbus.MyEventBus; import io.github.dsheirer.icon.IconModel; import io.github.dsheirer.module.log.EventLogManager; import io.github.dsheirer.preference.UserPreferences; @@ -40,10 +41,6 @@ import io.github.dsheirer.sample.Listener; import io.github.dsheirer.service.radioreference.RadioReference; import io.github.dsheirer.source.tuner.manager.TunerManager; import io.github.dsheirer.util.ThreadPool; -import javafx.collections.ListChangeListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -54,6 +51,9 @@ import java.util.ArrayList; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import javafx.collections.ListChangeListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Manages all aspects of playlists and related models @@ -104,6 +104,11 @@ public class PlaylistManager implements Listener mChannelModel = new ChannelModel(mAliasModel); mChannelProcessingManager = new ChannelProcessingManager(mChannelMapModel, eventLogManager, mTunerManager, mAliasModel, mUserPreferences); + + //Register the channel processing manager to receive global channel stop processing requests so that it can + //respond to tuner shutdown (ie error) events + MyEventBus.getGlobalEventBus().register(mChannelProcessingManager); + mChannelModel.addListener(mChannelProcessingManager); mChannelProcessingManager.addChannelEventListener(mChannelModel); diff --git a/src/main/java/io/github/dsheirer/sample/Broadcaster.java b/src/main/java/io/github/dsheirer/sample/Broadcaster.java index 6b51acba..494b289f 100644 --- a/src/main/java/io/github/dsheirer/sample/Broadcaster.java +++ b/src/main/java/io/github/dsheirer/sample/Broadcaster.java @@ -1,7 +1,6 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2019 Dennis Sheirer + * ***************************************************************************** + * Copyright (C) 2014-2022 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 @@ -15,17 +14,16 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see - * ***************************************************************************** + * **************************************************************************** */ package io.github.dsheirer.sample; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.ReentrantLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Broadcasts an item to multiple listeners @@ -33,7 +31,6 @@ import java.util.concurrent.locks.ReentrantLock; public class Broadcaster implements Listener { private final static Logger mLog = LoggerFactory.getLogger(Broadcaster.class); - private boolean mDebug; private ReentrantLock mLock = new ReentrantLock(); private List> mListeners = new ArrayList<>(); @@ -41,14 +38,6 @@ public class Broadcaster implements Listener { } - /** - * Turns on/off debugging to troubleshoot and log which listeners are receiving an item. - */ - public void setDebug(boolean debug) - { - mDebug = debug; - } - /** * Implements the Listener interface to receive an element and broadcast that element to all registered * listeners. @@ -66,16 +55,7 @@ public class Broadcaster implements Listener */ public void dispose() { - mLock.lock(); - - try - { - mListeners.clear(); - } - finally - { - mLock.unlock(); - } + clear(); } /** @@ -152,16 +132,7 @@ public class Broadcaster implements Listener */ public void clear() { - mLock.lock(); - - try - { - mListeners.clear(); - } - finally - { - mLock.unlock(); - } + mListeners.clear(); } /** @@ -173,21 +144,11 @@ public class Broadcaster implements Listener try { - if(mDebug) + List> listeners = new ArrayList<>(mListeners); + + for(Listener listener: listeners) { - for(Listener listener : mListeners) - { - mLog.debug("Sending [" + t + "] to listener [" + listener.getClass() + "]"); - listener.receive(t); - mLog.debug("Finished sending to listener [" + listener.getClass() + "]"); - } - } - else - { - for(Listener listener : mListeners) - { - listener.receive(t); - } + listener.receive(t); } } finally diff --git a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java index 749047db..aa86e174 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java @@ -28,6 +28,7 @@ import io.github.dsheirer.source.tuner.TunerEvent.Event; import io.github.dsheirer.source.tuner.manager.ChannelSourceManager; import io.github.dsheirer.source.tuner.manager.HeterodyneChannelSourceManager; import io.github.dsheirer.source.tuner.manager.PolyphaseChannelSourceManager; +import java.util.concurrent.atomic.AtomicBoolean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +45,7 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene private TunerController mTunerController; private TunerFrequencyErrorMonitor mTunerFrequencyErrorMonitor; private ITunerErrorListener mTunerErrorListener; + private AtomicBoolean mRunning = new AtomicBoolean(); public Tuner(TunerController tunerController, ITunerErrorListener tunerErrorListener) { @@ -85,20 +87,25 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene */ public void start() throws SourceException { - try + if(mRunning.compareAndSet(false, true)) { - getTunerController().start(); - } - catch(SourceException se) - { - //Rethrow the source exception - throw se; - } - catch(Exception e) - { - //Wrap any other exceptions in a new source exception - mLog.error("Error starting " + getTunerClass() + " tuner", e); - throw new SourceException("Unable to start " + getTunerClass() + " tuner", e); + try + { + getTunerController().start(); + } + catch(SourceException se) + { + mRunning.set(false); + //Rethrow the source exception + throw se; + } + catch(Exception e) + { + mRunning.set(false); + //Wrap any other exceptions in a new source exception + mLog.error("Error starting " + getTunerClass() + " tuner", e); + throw new SourceException("Unable to start " + getTunerClass() + " tuner", e); + } } } @@ -107,20 +114,24 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene */ public void stop() { - if(getChannelSourceManager() != null) + if(mRunning.compareAndSet(true, false)) { - getChannelSourceManager().stopAllChannels(); - getChannelSourceManager().dispose(); - mChannelSourceManager = null; + broadcast(new TunerEvent(this, Event.NOTIFICATION_SHUTTING_DOWN)); + + if(getChannelSourceManager() != null) + { + getChannelSourceManager().stopAllChannels(); + getChannelSourceManager().dispose(); + mChannelSourceManager = null; + } + + getTunerController().stop(); + getTunerController().dispose(); + + mTunerEventBroadcaster.clear(); + mTunerFrequencyErrorMonitor = null; + mTunerErrorListener = null; } - - broadcast(new TunerEvent(this, Event.NOTIFICATION_SHUTTING_DOWN)); - getTunerController().stop(); - getTunerController().dispose(); - - mTunerEventBroadcaster.clear(); - mTunerFrequencyErrorMonitor = null; - mTunerErrorListener = null; } /** diff --git a/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java b/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java index 7a866b14..0f121b61 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java +++ b/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java @@ -172,10 +172,6 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc sourceEvent.setSource(this); broadcastProducerSourceEvent(sourceEvent); break; - case NOTIFICATION_TUNER_SHUTDOWN: - //Rebroadcast this event so the channel processing manager receives it and shuts down the channel - broadcastConsumerSourceEvent(sourceEvent); - break; //Request events from the consumer case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE: setChannelFrequencyCorrection(sourceEvent.getValue().longValue()); diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/ChannelSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/ChannelSourceManager.java index 4a7541c0..ba001ce7 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/ChannelSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/ChannelSourceManager.java @@ -25,8 +25,9 @@ import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; - import java.util.SortedSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Interface to define the functionality of a channel source manager for handling tuner channel management and source @@ -34,6 +35,8 @@ import java.util.SortedSet; */ public abstract class ChannelSourceManager implements ISourceEventProcessor { + private Logger mLogger = LoggerFactory.getLogger(ChannelSourceManager.class); + private Broadcaster mSourceEventBroadcaster = new Broadcaster<>(); /** diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java index fa9fcc9d..55bdd571 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java @@ -19,7 +19,9 @@ package io.github.dsheirer.source.tuner.manager; import io.github.dsheirer.buffer.NativeSampleDelayBuffer; +import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest; import io.github.dsheirer.dsp.filter.design.FilterDesignException; +import io.github.dsheirer.eventbus.MyEventBus; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceException; @@ -28,14 +30,13 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.HalfBandTunerChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.CopyOnWriteArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Channel provider for heterodyne and decimate method of channel provisioning. @@ -68,14 +69,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager for(TunerChannelSource tunerChannelSource: toStop) { - try - { - tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource)); - } - catch(SourceException se) - { - mLog.error("Error stopping tuner channel source for tuner shutdown"); - } + MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource)); } } @@ -278,8 +272,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager //The start sample stream request contains a start timestamp and the delay buffer //will preload the channel with delayed sample buffers that either contain the //timestamp or occur later/newer than the timestamp. -// mSampleDelayBuffer.addListener((CICTunerChannelSource)sourceEvent.getSource(), -// sourceEvent.getValue().longValue()); mSampleDelayBuffer.addListener((HalfBandTunerChannelSource)sourceEvent.getSource(), sourceEvent.getValue().longValue()); } @@ -287,7 +279,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager case REQUEST_STOP_SAMPLE_STREAM: if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource) { -// mSampleDelayBuffer.removeListener((CICTunerChannelSource)sourceEvent.getSource()); mSampleDelayBuffer.removeListener((HalfBandTunerChannelSource)sourceEvent.getSource()); stopDelayBuffer(); } @@ -295,7 +286,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager case REQUEST_SOURCE_DISPOSE: if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource) { -// CICTunerChannelSource channelSource = (CICTunerChannelSource)sourceEvent.getSource(); HalfBandTunerChannelSource channelSource = (HalfBandTunerChannelSource) sourceEvent.getSource(); mChannelSources.remove(channelSource); mTunerChannels.remove(channelSource.getTunerChannel()); diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/PassThroughSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/PassThroughSourceManager.java index 1584df83..f1aeeb54 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/PassThroughSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/PassThroughSourceManager.java @@ -19,6 +19,8 @@ package io.github.dsheirer.source.tuner.manager; +import io.github.dsheirer.controller.channel.event.ChannelStopProcessingRequest; +import io.github.dsheirer.eventbus.MyEventBus; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceException; @@ -27,14 +29,13 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.PassThroughChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.CopyOnWriteArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Pass through source manager for relatively small bandwidth complex streams that don't warrant the overhead of @@ -62,14 +63,7 @@ public class PassThroughSourceManager extends ChannelSourceManager for(TunerChannelSource tunerChannelSource: toStop) { - try - { - tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource)); - } - catch(SourceException se) - { - mLog.error("Error stopping tuner channel source for tuner shutdown"); - } + MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource)); } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java index 062ee2c9..5d965361 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java @@ -31,14 +31,28 @@ import io.github.dsheirer.util.SwingUtils; import io.github.dsheirer.util.ThreadPool; import java.util.List; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** + * Spectral display manager for displaying tuner spectral content. + */ public class TunerSpectralDisplayManager implements Listener { + private Logger mLog = LoggerFactory.getLogger(TunerSpectralDisplayManager.class); + private SpectralDisplayPanel mSpectralDisplayPanel; private PlaylistManager mPlaylistManager; private SettingsManager mSettingsManager; private DiscoveredTunerModel mDiscoveredTunerModel; + /** + * Constructs an instance + * @param panel to manage + * @param playlistManager for channel updates + * @param settingsManager for settings + * @param discoveredTunerModel to access tuners + */ public TunerSpectralDisplayManager(SpectralDisplayPanel panel, PlaylistManager playlistManager, SettingsManager settingsManager, DiscoveredTunerModel discoveredTunerModel) {