#1243 Updates USB tuner error handling to prevent stack overflow when tuner error occurs while streaming. (#1247)

Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
Denny Sheirer
2022-05-09 07:16:35 -04:00
committed by GitHub
parent 46a916a945
commit 8bfb1d5470
11 changed files with 222 additions and 138 deletions

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.channel.metadata.ChannelAndMetadata;
import io.github.dsheirer.channel.metadata.ChannelMetadata; import io.github.dsheirer.channel.metadata.ChannelMetadata;
import io.github.dsheirer.channel.metadata.ChannelMetadataModel; import io.github.dsheirer.channel.metadata.ChannelMetadataModel;
import io.github.dsheirer.controller.channel.event.ChannelStartProcessingRequest; 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.event.PreloadDataContent;
import io.github.dsheirer.controller.channel.map.ChannelMapModel; import io.github.dsheirer.controller.channel.map.ChannelMapModel;
import io.github.dsheirer.identifier.Form; 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.SourceException;
import io.github.dsheirer.source.config.SourceConfigTuner; import io.github.dsheirer.source.config.SourceConfigTuner;
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency; 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.source.tuner.manager.TunerManager;
import io.github.dsheirer.util.ThreadPool; import io.github.dsheirer.util.ThreadPool;
import javafx.application.Platform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -62,6 +60,9 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; 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 * 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<ChannelEvent>
*/ */
private boolean isProcessing(Channel channel) 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<ChannelEvent>
*/ */
public Channel getChannel(ProcessingChain processingChain) public Channel getChannel(ProcessingChain processingChain)
{ {
Channel channel = null;
if(processingChain != null) if(processingChain != null)
{ {
for(Map.Entry<Channel,ProcessingChain> entry : mProcessingChains.entrySet()) mLock.lock();
try
{ {
if(entry.getValue() == processingChain) for(Map.Entry<Channel,ProcessingChain> 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<Channel,ProcessingChain> 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<ChannelEvent>
} }
} }
/**
* 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 * Stops the specified channel
* @param channel to stop * @param channel to stop
@@ -720,9 +798,7 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
{ {
@Override public void receive(SourceEvent sourceEvent) @Override public void receive(SourceEvent sourceEvent)
{ {
if((sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE || if(sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_ERROR_STATE && sourceEvent.getSource() != null)
sourceEvent.getEvent() == SourceEvent.Event.NOTIFICATION_TUNER_SHUTDOWN) &&
sourceEvent.getSource() != null)
{ {
Channel toShutdown = null; Channel toShutdown = null;
@@ -750,10 +826,6 @@ public class ChannelProcessingManager implements Listener<ChannelEvent>
{ {
mLog.warn("Channel source error detected - stopping channel [" + toShutdown.getName() + "]"); 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 else
{ {
mLog.warn("Source event error - stopping channel [" + toShutdown.getName() + "]"); mLog.warn("Source event error - stopping channel [" + toShutdown.getName() + "]");

View File

@@ -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 <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
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;
}
}

View File

@@ -21,11 +21,13 @@ package io.github.dsheirer.dsp.filter.channelizer;
import io.github.dsheirer.buffer.INativeBuffer; import io.github.dsheirer.buffer.INativeBuffer;
import io.github.dsheirer.buffer.INativeBufferProvider; import io.github.dsheirer.buffer.INativeBufferProvider;
import io.github.dsheirer.buffer.NativeBufferPoisonPill; 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.FilterFactory;
import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor; 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.OneChannelOutputProcessor;
import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcessor; import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcessor;
import io.github.dsheirer.dsp.filter.design.FilterDesignException; 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.Broadcaster;
import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.complex.InterleavedComplexSamples; 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.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import io.github.dsheirer.util.Dispatcher; 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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@@ -51,6 +49,9 @@ import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList; 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 * 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) for(TunerChannelSource tunerChannelSource: toStop)
{ {
try MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
{
tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource));
}
catch(SourceException se)
{
mLog.error("Error stopping tuner channel source for tuner shutdown");
}
} }
} }

View File

@@ -32,6 +32,7 @@ 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.map.ChannelMap; import io.github.dsheirer.controller.channel.map.ChannelMap;
import io.github.dsheirer.controller.channel.map.ChannelMapModel; import io.github.dsheirer.controller.channel.map.ChannelMapModel;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.icon.IconModel; import io.github.dsheirer.icon.IconModel;
import io.github.dsheirer.module.log.EventLogManager; import io.github.dsheirer.module.log.EventLogManager;
import io.github.dsheirer.preference.UserPreferences; 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.service.radioreference.RadioReference;
import io.github.dsheirer.source.tuner.manager.TunerManager; import io.github.dsheirer.source.tuner.manager.TunerManager;
import io.github.dsheirer.util.ThreadPool; 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.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@@ -54,6 +51,9 @@ import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; 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 * Manages all aspects of playlists and related models
@@ -104,6 +104,11 @@ public class PlaylistManager implements Listener<ChannelEvent>
mChannelModel = new ChannelModel(mAliasModel); mChannelModel = new ChannelModel(mAliasModel);
mChannelProcessingManager = new ChannelProcessingManager(mChannelMapModel, eventLogManager, mTunerManager, mChannelProcessingManager = new ChannelProcessingManager(mChannelMapModel, eventLogManager, mTunerManager,
mAliasModel, mUserPreferences); 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); mChannelModel.addListener(mChannelProcessingManager);
mChannelProcessingManager.addChannelEventListener(mChannelModel); mChannelProcessingManager.addChannelEventListener(mChannelModel);

View File

@@ -1,7 +1,6 @@
/* /*
* ****************************************************************************** * *****************************************************************************
* sdrtrunk * Copyright (C) 2014-2022 Dennis Sheirer
* Copyright (C) 2014-2019 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
@@ -15,17 +14,16 @@
* *
* 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/>
* ***************************************************************************** * ****************************************************************************
*/ */
package io.github.dsheirer.sample; package io.github.dsheirer.sample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Broadcasts an item to multiple listeners * Broadcasts an item to multiple listeners
@@ -33,7 +31,6 @@ import java.util.concurrent.locks.ReentrantLock;
public class Broadcaster<T> implements Listener<T> public class Broadcaster<T> implements Listener<T>
{ {
private final static Logger mLog = LoggerFactory.getLogger(Broadcaster.class); private final static Logger mLog = LoggerFactory.getLogger(Broadcaster.class);
private boolean mDebug;
private ReentrantLock mLock = new ReentrantLock(); private ReentrantLock mLock = new ReentrantLock();
private List<Listener<T>> mListeners = new ArrayList<>(); private List<Listener<T>> mListeners = new ArrayList<>();
@@ -41,14 +38,6 @@ public class Broadcaster<T> implements Listener<T>
{ {
} }
/**
* Turns on/off debugging to troubleshoot and log which listeners are receiving an item.
*/
public void setDebug(boolean debug)
{
mDebug = debug;
}
/** /**
* Implements the Listener<T> interface to receive an element and broadcast that element to all registered * Implements the Listener<T> interface to receive an element and broadcast that element to all registered
* listeners. * listeners.
@@ -66,16 +55,7 @@ public class Broadcaster<T> implements Listener<T>
*/ */
public void dispose() public void dispose()
{ {
mLock.lock(); clear();
try
{
mListeners.clear();
}
finally
{
mLock.unlock();
}
} }
/** /**
@@ -152,16 +132,7 @@ public class Broadcaster<T> implements Listener<T>
*/ */
public void clear() public void clear()
{ {
mLock.lock(); mListeners.clear();
try
{
mListeners.clear();
}
finally
{
mLock.unlock();
}
} }
/** /**
@@ -173,21 +144,11 @@ public class Broadcaster<T> implements Listener<T>
try try
{ {
if(mDebug) List<Listener<T>> listeners = new ArrayList<>(mListeners);
for(Listener listener: listeners)
{ {
for(Listener<T> listener : mListeners) listener.receive(t);
{
mLog.debug("Sending [" + t + "] to listener [" + listener.getClass() + "]");
listener.receive(t);
mLog.debug("Finished sending to listener [" + listener.getClass() + "]");
}
}
else
{
for(Listener<T> listener : mListeners)
{
listener.receive(t);
}
} }
} }
finally finally

View File

@@ -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.ChannelSourceManager;
import io.github.dsheirer.source.tuner.manager.HeterodyneChannelSourceManager; import io.github.dsheirer.source.tuner.manager.HeterodyneChannelSourceManager;
import io.github.dsheirer.source.tuner.manager.PolyphaseChannelSourceManager; import io.github.dsheirer.source.tuner.manager.PolyphaseChannelSourceManager;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -44,6 +45,7 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
private TunerController mTunerController; private TunerController mTunerController;
private TunerFrequencyErrorMonitor mTunerFrequencyErrorMonitor; private TunerFrequencyErrorMonitor mTunerFrequencyErrorMonitor;
private ITunerErrorListener mTunerErrorListener; private ITunerErrorListener mTunerErrorListener;
private AtomicBoolean mRunning = new AtomicBoolean();
public Tuner(TunerController tunerController, ITunerErrorListener tunerErrorListener) public Tuner(TunerController tunerController, ITunerErrorListener tunerErrorListener)
{ {
@@ -85,20 +87,25 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
*/ */
public void start() throws SourceException public void start() throws SourceException
{ {
try if(mRunning.compareAndSet(false, true))
{ {
getTunerController().start(); try
} {
catch(SourceException se) getTunerController().start();
{ }
//Rethrow the source exception catch(SourceException se)
throw se; {
} mRunning.set(false);
catch(Exception e) //Rethrow the source exception
{ throw se;
//Wrap any other exceptions in a new source exception }
mLog.error("Error starting " + getTunerClass() + " tuner", e); catch(Exception e)
throw new SourceException("Unable to start " + getTunerClass() + " tuner", 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() public void stop()
{ {
if(getChannelSourceManager() != null) if(mRunning.compareAndSet(true, false))
{ {
getChannelSourceManager().stopAllChannels(); broadcast(new TunerEvent(this, Event.NOTIFICATION_SHUTTING_DOWN));
getChannelSourceManager().dispose();
mChannelSourceManager = null; 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;
} }
/** /**

View File

@@ -172,10 +172,6 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
sourceEvent.setSource(this); sourceEvent.setSource(this);
broadcastProducerSourceEvent(sourceEvent); broadcastProducerSourceEvent(sourceEvent);
break; 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 //Request events from the consumer
case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE: case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
setChannelFrequencyCorrection(sourceEvent.getValue().longValue()); setChannelFrequencyCorrection(sourceEvent.getValue().longValue());

View File

@@ -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.ChannelSpecification;
import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import java.util.SortedSet; 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 * 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 public abstract class ChannelSourceManager implements ISourceEventProcessor
{ {
private Logger mLogger = LoggerFactory.getLogger(ChannelSourceManager.class);
private Broadcaster<SourceEvent> mSourceEventBroadcaster = new Broadcaster<>(); private Broadcaster<SourceEvent> mSourceEventBroadcaster = new Broadcaster<>();
/** /**

View File

@@ -19,7 +19,9 @@
package io.github.dsheirer.source.tuner.manager; package io.github.dsheirer.source.tuner.manager;
import io.github.dsheirer.buffer.NativeSampleDelayBuffer; 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.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceException; 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.HalfBandTunerChannelSource;
import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Channel provider for heterodyne and decimate method of channel provisioning. * Channel provider for heterodyne and decimate method of channel provisioning.
@@ -68,14 +69,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
for(TunerChannelSource tunerChannelSource: toStop) for(TunerChannelSource tunerChannelSource: toStop)
{ {
try MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
{
tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource));
}
catch(SourceException se)
{
mLog.error("Error stopping tuner channel source for tuner shutdown");
}
} }
} }
@@ -278,8 +272,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
//The start sample stream request contains a start timestamp and the delay buffer //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 //will preload the channel with delayed sample buffers that either contain the
//timestamp or occur later/newer than the timestamp. //timestamp or occur later/newer than the timestamp.
// mSampleDelayBuffer.addListener((CICTunerChannelSource)sourceEvent.getSource(),
// sourceEvent.getValue().longValue());
mSampleDelayBuffer.addListener((HalfBandTunerChannelSource)sourceEvent.getSource(), mSampleDelayBuffer.addListener((HalfBandTunerChannelSource)sourceEvent.getSource(),
sourceEvent.getValue().longValue()); sourceEvent.getValue().longValue());
} }
@@ -287,7 +279,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
case REQUEST_STOP_SAMPLE_STREAM: case REQUEST_STOP_SAMPLE_STREAM:
if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource) if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource)
{ {
// mSampleDelayBuffer.removeListener((CICTunerChannelSource)sourceEvent.getSource());
mSampleDelayBuffer.removeListener((HalfBandTunerChannelSource)sourceEvent.getSource()); mSampleDelayBuffer.removeListener((HalfBandTunerChannelSource)sourceEvent.getSource());
stopDelayBuffer(); stopDelayBuffer();
} }
@@ -295,7 +286,6 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
case REQUEST_SOURCE_DISPOSE: case REQUEST_SOURCE_DISPOSE:
if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource) if(sourceEvent.getSource() instanceof HalfBandTunerChannelSource)
{ {
// CICTunerChannelSource channelSource = (CICTunerChannelSource)sourceEvent.getSource();
HalfBandTunerChannelSource channelSource = (HalfBandTunerChannelSource) sourceEvent.getSource(); HalfBandTunerChannelSource channelSource = (HalfBandTunerChannelSource) sourceEvent.getSource();
mChannelSources.remove(channelSource); mChannelSources.remove(channelSource);
mTunerChannels.remove(channelSource.getTunerChannel()); mTunerChannels.remove(channelSource.getTunerChannel());

View File

@@ -19,6 +19,8 @@
package io.github.dsheirer.source.tuner.manager; 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.sample.Listener;
import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceException; 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.PassThroughChannelSource;
import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannel;
import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList; 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 * 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) for(TunerChannelSource tunerChannelSource: toStop)
{ {
try MyEventBus.getGlobalEventBus().post(new ChannelStopProcessingRequest(tunerChannelSource));
{
tunerChannelSource.process(SourceEvent.tunerShutdown(tunerChannelSource));
}
catch(SourceException se)
{
mLog.error("Error stopping tuner channel source for tuner shutdown");
}
} }
} }

View File

@@ -31,14 +31,28 @@ import io.github.dsheirer.util.SwingUtils;
import io.github.dsheirer.util.ThreadPool; import io.github.dsheirer.util.ThreadPool;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; 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<TunerEvent> public class TunerSpectralDisplayManager implements Listener<TunerEvent>
{ {
private Logger mLog = LoggerFactory.getLogger(TunerSpectralDisplayManager.class);
private SpectralDisplayPanel mSpectralDisplayPanel; private SpectralDisplayPanel mSpectralDisplayPanel;
private PlaylistManager mPlaylistManager; private PlaylistManager mPlaylistManager;
private SettingsManager mSettingsManager; private SettingsManager mSettingsManager;
private DiscoveredTunerModel mDiscoveredTunerModel; 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, public TunerSpectralDisplayManager(SpectralDisplayPanel panel, PlaylistManager playlistManager,
SettingsManager settingsManager, DiscoveredTunerModel discoveredTunerModel) SettingsManager settingsManager, DiscoveredTunerModel discoveredTunerModel)
{ {