mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 00:57:31 -05:00
Merges from master branch.
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2017 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.source.tuner.channel;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.FilterFactory;
|
||||
import io.github.dsheirer.dsp.filter.Window;
|
||||
import io.github.dsheirer.dsp.filter.cic.ComplexPrimeCICDecimate;
|
||||
import io.github.dsheirer.dsp.mixer.Oscillator;
|
||||
import io.github.dsheirer.sample.Buffer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.OverflowableTransferQueue;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.ComplexBuffer;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CICTunerChannelSource extends TunerChannelSource
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(CICTunerChannelSource.class);
|
||||
|
||||
//Maximum number of filled buffers for the blocking queue
|
||||
private static final int BUFFER_MAX_CAPACITY = 300;
|
||||
|
||||
//Threshold for resetting buffer overflow condition
|
||||
private static final int BUFFER_OVERFLOW_RESET_THRESHOLD = 100;
|
||||
|
||||
private static double CHANNEL_RATE = 48000.0;
|
||||
private static int CHANNEL_PASS_FREQUENCY = 12000;
|
||||
|
||||
private OverflowableTransferQueue<ComplexBuffer> mBuffer;
|
||||
|
||||
private Oscillator mFrequencyCorrectionMixer;
|
||||
private ComplexPrimeCICDecimate mDecimationFilter;
|
||||
private Listener<ComplexBuffer> mListener;
|
||||
private List<ComplexBuffer> mSampleBuffers = new ArrayList<ComplexBuffer>();
|
||||
private long mTunerFrequency = 0;
|
||||
private double mTunerSampleRate;
|
||||
private long mChannelFrequencyCorrection = 0;
|
||||
|
||||
/**
|
||||
* Implements a heterodyne/decimate Digital Drop Channel (DDC) to decimate the IQ output from a tuner down to a
|
||||
* fixed 48 kHz IQ channel rate.
|
||||
*
|
||||
* Note: this class can only be used once (started and stopped) and a new tuner channel source must be requested
|
||||
* from the tuner once this object has been stopped. This is because channels are managed dynamically and center
|
||||
* tuned frequency may have changed since this source was obtained and thus the tuner might no longer be able to
|
||||
* source this channel once it has been stopped.
|
||||
*
|
||||
* @param tunerChannel specifying the center frequency for the DDC
|
||||
*/
|
||||
public CICTunerChannelSource(Tuner tuner, TunerChannel tunerChannel)
|
||||
{
|
||||
super(tuner.getTunerController().getSourceEventListener(), tunerChannel);
|
||||
|
||||
mBuffer = new OverflowableTransferQueue<>(BUFFER_MAX_CAPACITY, BUFFER_OVERFLOW_RESET_THRESHOLD);
|
||||
mBuffer.setSourceOverflowListener(this);
|
||||
|
||||
//Setup the frequency translator to the current source frequency
|
||||
mTunerFrequency = tuner.getTunerController().getFrequency();
|
||||
long frequencyOffset = mTunerFrequency - getTunerChannel().getFrequency();
|
||||
mFrequencyCorrectionMixer = new Oscillator(frequencyOffset, tuner.getTunerController().getSampleRate());
|
||||
|
||||
//Setup the decimation filter chain
|
||||
setSampleRate(tuner.getTunerController().getSampleRate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the center frequency for the incoming sample buffers
|
||||
* @param frequency in hertz
|
||||
*/
|
||||
@Override
|
||||
protected void setFrequency(long frequency)
|
||||
{
|
||||
mTunerFrequency = frequency;
|
||||
|
||||
//Reset frequency correction so that consumer components can adjust
|
||||
setFrequencyCorrection(0);
|
||||
|
||||
updateMixerFrequencyOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current frequency correction being applied to the channel sample stream
|
||||
* @return correction in hertz
|
||||
*/
|
||||
@Override
|
||||
public long getFrequencyCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the frequency correction value and broadcasts the change to the registered downstream listener.
|
||||
* @param correction current frequency correction value.
|
||||
*/
|
||||
protected void setFrequencyCorrection(long correction)
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
|
||||
updateMixerFrequencyOffset();
|
||||
|
||||
broadcastConsumerSourceEvent(SourceEvent.frequencyCorrectionChange(mChannelFrequencyCorrection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary input method for receiving complex sample buffers from the wideband source (ie tuner)
|
||||
* @param buffer to receive and eventually process
|
||||
*/
|
||||
public void receive(ComplexBuffer buffer)
|
||||
{
|
||||
mBuffer.offer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(Listener<ComplexBuffer> listener)
|
||||
{
|
||||
/* Save a pointer to the listener so that if we have to change the
|
||||
* decimation filter, we can re-add the listener */
|
||||
mListener = listener;
|
||||
|
||||
mDecimationFilter.setListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(Listener<ComplexBuffer> listener)
|
||||
{
|
||||
mDecimationFilter.removeListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate to the requested value and notifies any downstream components of the change
|
||||
* @param sampleRate to set
|
||||
*/
|
||||
protected void setSampleRate(double sampleRate)
|
||||
{
|
||||
if(mTunerSampleRate != sampleRate)
|
||||
{
|
||||
mFrequencyCorrectionMixer.setSampleRate(sampleRate);
|
||||
|
||||
/* Get new decimation filter */
|
||||
mDecimationFilter = FilterFactory.getDecimationFilter((int)sampleRate, (int)CHANNEL_RATE, 1,
|
||||
CHANNEL_PASS_FREQUENCY, 60, Window.WindowType.HAMMING);
|
||||
|
||||
/* re-add the original output listener */
|
||||
mDecimationFilter.setListener(mListener);
|
||||
|
||||
mTunerSampleRate = sampleRate;
|
||||
|
||||
broadcastConsumerSourceEvent(SourceEvent.channelSampleRateChange(getSampleRate()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the local mixer frequency offset from the tuned frequency,
|
||||
* channel's requested frequency, and channel frequency correction.
|
||||
*/
|
||||
private void updateMixerFrequencyOffset()
|
||||
{
|
||||
long offset = mTunerFrequency - getTunerChannel().getFrequency() - mChannelFrequencyCorrection;
|
||||
mFrequencyCorrectionMixer.setFrequency(offset);
|
||||
}
|
||||
|
||||
public double getSampleRate()
|
||||
{
|
||||
return CHANNEL_RATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSamples()
|
||||
{
|
||||
mBuffer.drainTo(mSampleBuffers, 20);
|
||||
|
||||
for(Buffer buffer : mSampleBuffers)
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
|
||||
/* We make a copy of the buffer so that we don't affect
|
||||
* anyone else that is using the same buffer, like other
|
||||
* channels or the spectral display */
|
||||
float[] translated = new float[samples.length];
|
||||
|
||||
/* Perform frequency translation */
|
||||
for(int x = 0; x < samples.length; x += 2)
|
||||
{
|
||||
mFrequencyCorrectionMixer.rotate();
|
||||
|
||||
translated[x] = Complex.multiplyInphase(
|
||||
samples[x], samples[x + 1], mFrequencyCorrectionMixer.inphase(), mFrequencyCorrectionMixer.quadrature());
|
||||
|
||||
translated[x + 1] = Complex.multiplyQuadrature(
|
||||
samples[x], samples[x + 1], mFrequencyCorrectionMixer.inphase(), mFrequencyCorrectionMixer.quadrature());
|
||||
}
|
||||
|
||||
final ComplexPrimeCICDecimate filter = mDecimationFilter;
|
||||
|
||||
if(filter != null)
|
||||
{
|
||||
filter.receive(new ComplexBuffer(translated));
|
||||
}
|
||||
}
|
||||
|
||||
mSampleBuffers.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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.source.tuner.channel;
|
||||
|
||||
public class TunerChannel implements Comparable<TunerChannel>
|
||||
{
|
||||
private long mFrequency;
|
||||
private int mBandwidth;
|
||||
|
||||
public TunerChannel(long frequency, int bandwidth)
|
||||
{
|
||||
mFrequency = frequency;
|
||||
mBandwidth = bandwidth;
|
||||
}
|
||||
|
||||
public long getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public void setFrequency(long frequency)
|
||||
{
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mBandwidth;
|
||||
}
|
||||
|
||||
public void setBandwidth(int bandwidth)
|
||||
{
|
||||
mBandwidth = bandwidth;
|
||||
}
|
||||
|
||||
public long getMinFrequency()
|
||||
{
|
||||
return mFrequency - (mBandwidth / 2);
|
||||
}
|
||||
|
||||
public long getMaxFrequency()
|
||||
{
|
||||
return mFrequency + (mBandwidth / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if any part of this tuner channel overlaps the specified range
|
||||
*/
|
||||
public boolean overlaps(long minimum, long maximum)
|
||||
{
|
||||
long channelMin = getMinFrequency();
|
||||
long channelMax = getMaxFrequency();
|
||||
|
||||
return ((minimum <= channelMin && channelMin <= maximum) ||
|
||||
(minimum <= channelMax && channelMax <= maximum) ||
|
||||
(minimum <= channelMin && channelMax <= maximum) ||
|
||||
(channelMin <= minimum && maximum <= channelMax));
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Channel: ");
|
||||
sb.append(getMinFrequency());
|
||||
sb.append("-");
|
||||
sb.append(getMaxFrequency());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TunerChannel otherLock)
|
||||
{
|
||||
return Long.compare(getFrequency(), otherLock.getFrequency());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2017 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.source.tuner.channel;
|
||||
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
|
||||
public interface TunerChannelProvider
|
||||
{
|
||||
/**
|
||||
* Returns a tuner frequency channel source, tuned to the correct frequency
|
||||
*
|
||||
* @return - source for 48k sample rate
|
||||
*/
|
||||
public TunerChannelSource getChannel( TunerChannel channel ) throws SourceException;
|
||||
|
||||
/**
|
||||
* Releases the tuned channel resources
|
||||
*/
|
||||
public void releaseChannel( TunerChannelSource source );
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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.source.tuner.channel;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.ComplexBuffer;
|
||||
import io.github.dsheirer.source.ComplexSource;
|
||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.SourceEventListenerToProcessorAdapter;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class TunerChannelSource extends ComplexSource implements ISourceEventProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerChannelSource.class);
|
||||
private static final long BUFFER_PROCESSOR_RUN_INTERVAL_MILLISECONDS = 50;
|
||||
private SourceEventListenerToProcessorAdapter mConsumerSourceEventListenerAdapter;
|
||||
private TunerChannel mTunerChannel;
|
||||
private Listener<SourceEvent> mProducerSourceEventListener;
|
||||
private Listener<SourceEvent> mConsumerSourceEventListener;
|
||||
private BufferProcessor mBufferProcessor = new BufferProcessor();
|
||||
|
||||
/**
|
||||
* Tuner Channel Source is a Digital Drop Channel (DDC) abstract class that defines the minimum functionality
|
||||
* requirements for a channel sample source.
|
||||
*
|
||||
* @param producerSourceEventListener to receive source event requests (e.g. start/stop sample stream)
|
||||
* @param tunerChannel describing the desired channel frequency and bandwidth/minimum sample rate
|
||||
*/
|
||||
public TunerChannelSource(Listener<SourceEvent> producerSourceEventListener, TunerChannel tunerChannel)
|
||||
{
|
||||
mProducerSourceEventListener = producerSourceEventListener;
|
||||
mTunerChannel = tunerChannel;
|
||||
mConsumerSourceEventListenerAdapter = new SourceEventListenerToProcessorAdapter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency()
|
||||
{
|
||||
return mTunerChannel.getFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the center frequency for the sample streaming being sent from the producer.
|
||||
* @param frequency in hertz
|
||||
*/
|
||||
protected abstract void setFrequency(long frequency);
|
||||
|
||||
/**
|
||||
* Sets the sample rate of the incoming sample stream from the producer
|
||||
* @param sampleRate in hertz
|
||||
*/
|
||||
protected abstract void setSampleRate(double sampleRate);
|
||||
|
||||
/**
|
||||
* Sets the frequency correction for the outbound sample stream to the consumer
|
||||
* @param correction in hertz
|
||||
*/
|
||||
protected abstract void setFrequencyCorrection(long correction);
|
||||
|
||||
/**
|
||||
* Frequency correction value currently being applied to the outbound sample stream
|
||||
*/
|
||||
public abstract long getFrequencyCorrection();
|
||||
|
||||
/**
|
||||
* Sets the listener to receive the complex buffer sample output from this channel
|
||||
* @param complexBufferListener to receive complex buffers
|
||||
*/
|
||||
public abstract void setListener(Listener<ComplexBuffer> complexBufferListener);
|
||||
|
||||
/**
|
||||
* Commands sub-class to process queued samples and distribute them to the consumer. This method will be invoked
|
||||
* by an interval timer.
|
||||
*/
|
||||
protected abstract void processSamples();
|
||||
|
||||
/**
|
||||
* Tuner channel for this tuner channel source
|
||||
*/
|
||||
public TunerChannel getTunerChannel()
|
||||
{
|
||||
return mTunerChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this tuner channel source producing sample stream.
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
//Broadcast current frequency and sample rate so consumer can configure correctly
|
||||
broadcastConsumerSourceEvent(SourceEvent.frequencyChange(getFrequency()));
|
||||
broadcastConsumerSourceEvent(SourceEvent.sampleRateChange(getSampleRate()));
|
||||
|
||||
if(mProducerSourceEventListener != null)
|
||||
{
|
||||
mProducerSourceEventListener.receive(SourceEvent.startSampleStream(this));
|
||||
}
|
||||
|
||||
mBufferProcessor.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this tuner channel source from producing a sample stream. Note: tuner channel sources are one-time usage
|
||||
* only. Invoking this method will also tell the source manager to dispose of this source.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
if(mProducerSourceEventListener != null)
|
||||
{
|
||||
mProducerSourceEventListener.receive(SourceEvent.stopSampleStream(this));
|
||||
mProducerSourceEventListener.receive(SourceEvent.sourceDisposeRequest(this));
|
||||
}
|
||||
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
//Reset is not valid for a tuner channel source - ignored
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked after the buffer processor is completely shutdown so that this instance can perform any
|
||||
* cleanup operations needed to dispose of this instance.
|
||||
*/
|
||||
protected void performDisposal()
|
||||
{
|
||||
mProducerSourceEventListener = null;
|
||||
mConsumerSourceEventListener = null;
|
||||
mConsumerSourceEventListenerAdapter.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes source event notifications received from the producer/parent and source event requests received from
|
||||
* the consumer.
|
||||
*
|
||||
* @param sourceEvent to process
|
||||
* @throws SourceException if there is an error while processing the source event
|
||||
*/
|
||||
@Override
|
||||
public void process(SourceEvent sourceEvent) throws SourceException
|
||||
{
|
||||
switch(sourceEvent.getEvent())
|
||||
{
|
||||
//Notification events from the producer
|
||||
case NOTIFICATION_FREQUENCY_CHANGE:
|
||||
setFrequency(sourceEvent.getValue().longValue());
|
||||
break;
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
setSampleRate(sourceEvent.getValue().doubleValue());
|
||||
break;
|
||||
|
||||
//Request events from the consumer
|
||||
case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
setFrequencyCorrection(sourceEvent.getValue().longValue());
|
||||
break;
|
||||
|
||||
default:
|
||||
mLog.error("Ignoring unrecognized source event: " + sourceEvent.getEvent() + " from [" +
|
||||
sourceEvent.getSource().getClass() + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the source event to the incoming sample stream producer.
|
||||
* @param sourceEvent to broadcast
|
||||
*/
|
||||
protected void broadcastProducerSourceEvent(SourceEvent sourceEvent)
|
||||
{
|
||||
if(mProducerSourceEventListener != null)
|
||||
{
|
||||
mProducerSourceEventListener.receive(sourceEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the source event to the outbound sample stream consumer.
|
||||
* @param sourceEvent to broadcast
|
||||
*/
|
||||
protected void broadcastConsumerSourceEvent(SourceEvent sourceEvent)
|
||||
{
|
||||
if(mConsumerSourceEventListener != null)
|
||||
{
|
||||
mConsumerSourceEventListener.receive(sourceEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the ISourceEventListener interface for receiving source events (ie requests) from a consumer.
|
||||
*
|
||||
* Note: source events are simply transferred to the process() method in this class.
|
||||
*/
|
||||
@Override
|
||||
public Listener<SourceEvent> getSourceEventListener()
|
||||
{
|
||||
return mConsumerSourceEventListenerAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the ISourceEventProvider interface to set the consumer listener for source events.
|
||||
* @param listener to receive consumer source events
|
||||
*/
|
||||
@Override
|
||||
public void setSourceEventListener(Listener<SourceEvent> listener)
|
||||
{
|
||||
mConsumerSourceEventListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the ISourceEventProvider interface to remove the consumer listener for source events.
|
||||
*/
|
||||
@Override
|
||||
public void removeSourceEventListener()
|
||||
{
|
||||
mConsumerSourceEventListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processor to periodically invoke buffer sample processing on an interval timer. At each interval this processor
|
||||
* sends a heartbeat to the registered consumer and then commands the sub-class implementation to process any
|
||||
* queued buffers and distribute complex buffer sample(s) to the registered consumer.
|
||||
*/
|
||||
public class BufferProcessor implements Runnable
|
||||
{
|
||||
private ScheduledFuture<?> mScheduledFuture;
|
||||
private boolean mStopped = false;
|
||||
|
||||
/**
|
||||
* Commands this processor to do a shutdown at the end of this or the next iteration. Once successfully
|
||||
* shutdown, it will invoke the performDisposal() method to cleanup this instance.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
mStopped = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts buffer processing on a fixed interval using a scheduled thread pool
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
if(mScheduledFuture == null)
|
||||
{
|
||||
mScheduledFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(this, 0,
|
||||
BUFFER_PROCESSOR_RUN_INTERVAL_MILLISECONDS, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the Runnable interface to periodically send a heartbeat and then process buffer samples.
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!mStopped)
|
||||
{
|
||||
getHeartbeatManager().broadcast();
|
||||
processSamples();
|
||||
}
|
||||
|
||||
if(mStopped)
|
||||
{
|
||||
if(mScheduledFuture != null)
|
||||
{
|
||||
//Set may-interrupt to false so that we can complete this iteration
|
||||
mScheduledFuture.cancel(false);
|
||||
}
|
||||
|
||||
mScheduledFuture = null;
|
||||
|
||||
performDisposal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user