mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 09:07:27 -05:00
#108 [WIP] Created new ThreadPool class with a static ScheduledThreadExecutor that is now shared by all components. Removed ThreadPoolManager from all classes. Consolidating into 1 pool seems to have reduced CPU usage by ~15-20%. Overall memory usage is also reduced.
This commit is contained in:
@@ -22,8 +22,6 @@ import audio.AudioEvent.Type;
|
||||
import audio.output.AudioOutput;
|
||||
import audio.output.MonoAudioOutput;
|
||||
import audio.output.StereoAudioOutput;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
@@ -32,6 +30,7 @@ import sample.Listener;
|
||||
import source.mixer.MixerChannel;
|
||||
import source.mixer.MixerChannelConfiguration;
|
||||
import source.mixer.MixerManager;
|
||||
import util.ThreadPool;
|
||||
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Mixer;
|
||||
@@ -70,7 +69,6 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
|
||||
private Broadcaster<AudioEvent> mControllerBroadcaster = new Broadcaster<>();
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture<?> mProcessingTask;
|
||||
private MixerManager mMixerManager;
|
||||
private MixerChannelConfiguration mMixerChannelConfiguration;
|
||||
@@ -81,9 +79,8 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
* packets to any combination of outputs based on any alias audio routing
|
||||
* options specified by the user.
|
||||
*/
|
||||
public AudioManager(ThreadPoolManager manager, MixerManager mixerManager)
|
||||
public AudioManager(MixerManager mixerManager)
|
||||
{
|
||||
mThreadPoolManager = manager;
|
||||
mMixerManager = mixerManager;
|
||||
|
||||
loadSettings();
|
||||
@@ -145,14 +142,13 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
if(mThreadPoolManager != null && mProcessingTask != null)
|
||||
if(mProcessingTask != null)
|
||||
{
|
||||
mThreadPoolManager.cancel(mProcessingTask);
|
||||
mProcessingTask.cancel(true);
|
||||
}
|
||||
|
||||
mAudioPacketQueue.clear();
|
||||
|
||||
mThreadPoolManager = null;
|
||||
mProcessingTask = null;
|
||||
|
||||
mChannelConnectionMap.clear();
|
||||
@@ -224,9 +220,9 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
{
|
||||
mControllerBroadcaster.broadcast(CONFIGURATION_CHANGE_STARTED);
|
||||
|
||||
if(mThreadPoolManager != null && mProcessingTask != null)
|
||||
if(mProcessingTask != null)
|
||||
{
|
||||
mThreadPoolManager.cancel(mProcessingTask);
|
||||
mProcessingTask.cancel(true);
|
||||
}
|
||||
|
||||
disposeCurrentConfiguration();
|
||||
@@ -234,19 +230,18 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
switch(entry.getMixerChannel())
|
||||
{
|
||||
case MONO:
|
||||
AudioOutput mono = new MonoAudioOutput(mThreadPoolManager,
|
||||
entry.getMixer());
|
||||
AudioOutput mono = new MonoAudioOutput(entry.getMixer());
|
||||
mAudioOutputConnections.add(new AudioOutputConnection(mono));
|
||||
mAvailableConnectionCount++;
|
||||
mAudioOutputMap.put(mono.getChannelName(), mono);
|
||||
break;
|
||||
case STEREO:
|
||||
AudioOutput left = new StereoAudioOutput(mThreadPoolManager, entry.getMixer(), MixerChannel.LEFT);
|
||||
AudioOutput left = new StereoAudioOutput(entry.getMixer(), MixerChannel.LEFT);
|
||||
mAudioOutputConnections.add(new AudioOutputConnection(left));
|
||||
mAvailableConnectionCount++;
|
||||
mAudioOutputMap.put(left.getChannelName(), left);
|
||||
|
||||
AudioOutput right = new StereoAudioOutput(mThreadPoolManager, entry.getMixer(), MixerChannel.RIGHT);
|
||||
AudioOutput right = new StereoAudioOutput(entry.getMixer(), MixerChannel.RIGHT);
|
||||
mAudioOutputConnections.add(new AudioOutputConnection(right));
|
||||
mAvailableConnectionCount++;
|
||||
mAudioOutputMap.put(right.getChannelName(), right);
|
||||
@@ -256,9 +251,8 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
|
||||
+ "configuration: " + entry.getMixerChannel());
|
||||
}
|
||||
|
||||
mProcessingTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.AUDIO_PROCESSING, new AudioPacketProcessor(), 15,
|
||||
TimeUnit.MILLISECONDS);
|
||||
mProcessingTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new AudioPacketProcessor(),
|
||||
0, 15, TimeUnit.MILLISECONDS);
|
||||
|
||||
mControllerBroadcaster.broadcast(CONFIGURATION_CHANGE_COMPLETE);
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ package audio.broadcast;
|
||||
|
||||
import audio.convert.ISilenceGenerator;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sample.Listener;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -40,7 +40,6 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
|
||||
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture mScheduledTask;
|
||||
|
||||
private RecordingQueueProcessor mRecordingQueueProcessor = new RecordingQueueProcessor();
|
||||
@@ -77,19 +76,13 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
* The last audio packet's metadata is automatically attached to the closed audio recording when it is enqueued for
|
||||
* broadcast. That metadata will be updated on the remote server once the audio recording is opened for streaming.
|
||||
*/
|
||||
public AudioBroadcaster(ThreadPoolManager threadPoolManager, BroadcastConfiguration broadcastConfiguration)
|
||||
public AudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mBroadcastConfiguration = broadcastConfiguration;
|
||||
mDelay = mBroadcastConfiguration.getDelay();
|
||||
mSilenceGenerator = BroadcastFactory.getSilenceGenerator(broadcastConfiguration.getBroadcastFormat());
|
||||
}
|
||||
|
||||
protected ThreadPoolManager getThreadPoolManager()
|
||||
{
|
||||
return mThreadPoolManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast binary audio data frames or sequences.
|
||||
*/
|
||||
@@ -129,11 +122,8 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
if(mScheduledTask == null)
|
||||
{
|
||||
if(mThreadPoolManager != null)
|
||||
{
|
||||
mScheduledTask = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
|
||||
mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
ThreadPool.SCHEDULED.scheduleAtFixedRate(mRecordingQueueProcessor, 0,
|
||||
PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,9 +135,9 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
|
||||
{
|
||||
if(mStreaming.compareAndSet(true, false))
|
||||
{
|
||||
if(mThreadPoolManager != null && mScheduledTask != null)
|
||||
if(mScheduledTask != null)
|
||||
{
|
||||
mThreadPoolManager.cancel(mScheduledTask);
|
||||
mScheduledTask.cancel(true);
|
||||
}
|
||||
|
||||
disconnect();
|
||||
|
||||
@@ -37,7 +37,6 @@ import audio.convert.IAudioConverter;
|
||||
import audio.convert.ISilenceGenerator;
|
||||
import audio.convert.MP3AudioConverter;
|
||||
import audio.convert.MP3SilenceGenerator;
|
||||
import controller.ThreadPoolManager;
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EmptyEditor;
|
||||
import icon.IconManager;
|
||||
@@ -45,25 +44,23 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import record.AudioRecorder;
|
||||
import record.mp3.MP3Recorder;
|
||||
import settings.SettingsManager;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class BroadcastFactory
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( BroadcastFactory.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(BroadcastFactory.class);
|
||||
|
||||
public static final int MP3_MONO_16_KHZ_BITRATE = 16;
|
||||
public static final boolean MP3_CONSTANT_BITRATE = false;
|
||||
|
||||
/**
|
||||
* Creates an audio streaming broadcaster for the configuration
|
||||
* @param threadPoolManager for creating an audio broadcasting connection thread
|
||||
*
|
||||
* @param configuration describing the server and audio types
|
||||
* @return configured broadcaster or null
|
||||
*/
|
||||
public static AudioBroadcaster getBroadcaster(ThreadPoolManager threadPoolManager,
|
||||
BroadcastConfiguration configuration)
|
||||
public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration)
|
||||
{
|
||||
if(configuration != null)
|
||||
{
|
||||
@@ -74,20 +71,15 @@ public class BroadcastFactory
|
||||
switch(configuration.getBroadcastServerType())
|
||||
{
|
||||
case BROADCASTIFY:
|
||||
return new IcecastTCPAudioBroadcaster(threadPoolManager,
|
||||
(BroadcastifyConfiguration)configuration);
|
||||
return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration);
|
||||
case ICECAST_TCP:
|
||||
return new IcecastTCPAudioBroadcaster(threadPoolManager,
|
||||
(IcecastTCPConfiguration)configuration);
|
||||
return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration);
|
||||
case ICECAST_HTTP:
|
||||
return new IcecastHTTPAudioBroadcaster(threadPoolManager,
|
||||
(IcecastHTTPConfiguration)configuration);
|
||||
return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration);
|
||||
case SHOUTCAST_V1:
|
||||
return new ShoutcastV1AudioBroadcaster(threadPoolManager,
|
||||
(ShoutcastV1Configuration)configuration);
|
||||
return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration);
|
||||
case SHOUTCAST_V2:
|
||||
return new ShoutcastV2AudioBroadcaster(threadPoolManager,
|
||||
(ShoutcastV2Configuration)configuration);
|
||||
return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration);
|
||||
case UNKNOWN:
|
||||
default:
|
||||
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
|
||||
@@ -101,6 +93,7 @@ public class BroadcastFactory
|
||||
|
||||
/**
|
||||
* Creates an audio convert to convert from 8 kHz PCM audio to the specified format
|
||||
*
|
||||
* @param configuration containing the requested output audio format
|
||||
* @return audio convert or null
|
||||
*/
|
||||
@@ -149,6 +142,7 @@ public class BroadcastFactory
|
||||
|
||||
/**
|
||||
* Constructs an editor for the specified broadcastAudio configuration
|
||||
*
|
||||
* @param configuration to modify or view
|
||||
* @param broadcastModel model for broadcastAudio configurations
|
||||
* @return an editor for the specified broadcastAudio configuration
|
||||
@@ -160,10 +154,10 @@ public class BroadcastFactory
|
||||
{
|
||||
Editor<BroadcastConfiguration> editor;
|
||||
|
||||
switch (configuration.getBroadcastServerType())
|
||||
switch(configuration.getBroadcastServerType())
|
||||
{
|
||||
case BROADCASTIFY:
|
||||
editor = new BroadcastifyConfigurationEditor(broadcastModel, aliasModel, iconManager);
|
||||
editor = new BroadcastifyConfigurationEditor(broadcastModel, aliasModel, iconManager);
|
||||
break;
|
||||
case ICECAST_TCP:
|
||||
editor = new IcecastTCPConfigurationEditor(broadcastModel, aliasModel, iconManager);
|
||||
@@ -192,7 +186,7 @@ public class BroadcastFactory
|
||||
*/
|
||||
public static AudioRecorder getAudioRecorder(Path path, BroadcastFormat broadcastFormat)
|
||||
{
|
||||
switch (broadcastFormat)
|
||||
switch(broadcastFormat)
|
||||
{
|
||||
case MP3:
|
||||
return new MP3Recorder(path);
|
||||
@@ -204,7 +198,7 @@ public class BroadcastFactory
|
||||
|
||||
public static ISilenceGenerator getSilenceGenerator(BroadcastFormat format)
|
||||
{
|
||||
switch (format)
|
||||
switch(format)
|
||||
{
|
||||
case MP3:
|
||||
return new MP3SilenceGenerator();
|
||||
|
||||
@@ -21,13 +21,13 @@ package audio.broadcast;
|
||||
import alias.id.broadcast.BroadcastChannel;
|
||||
import audio.AudioPacket;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import icon.IconManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import util.ThreadPool;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
@@ -66,7 +66,6 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
|
||||
private Map<String,BroadcastConfiguration> mBroadcastConfigurationMap = new HashMap<>();
|
||||
private Map<String,AudioBroadcaster> mBroadcasterMap = new HashMap<>();
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private IconManager mIconManager;
|
||||
private StreamManager mStreamManager;
|
||||
private Broadcaster<BroadcastEvent> mBroadcastEventBroadcaster = new Broadcaster<>();
|
||||
@@ -74,17 +73,16 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
/**
|
||||
* Model for managing Broadcast configurations and any associated broadcaster instances.
|
||||
*/
|
||||
public BroadcastModel(ThreadPoolManager threadPoolManager, IconManager iconManager)
|
||||
public BroadcastModel(IconManager iconManager)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mIconManager = iconManager;
|
||||
mStreamManager = new StreamManager(threadPoolManager, new CompletedRecordingListener(), BroadcastFormat.MP3,
|
||||
mStreamManager = new StreamManager(new CompletedRecordingListener(), BroadcastFormat.MP3,
|
||||
SystemProperties.getInstance().getApplicationFolder(TEMPORARY_STREAM_DIRECTORY));
|
||||
mStreamManager.start();
|
||||
|
||||
//Monitor to remove temporary recording files that have been streamed by all audio broadcasters
|
||||
mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_RECORDING,
|
||||
new RecordingDeletionMonitor(), 15l, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.scheduleAtFixedRate(new RecordingDeletionMonitor(),
|
||||
15l, 15l, TimeUnit.SECONDS);
|
||||
|
||||
removeOrphanedTemporaryRecordings();
|
||||
}
|
||||
@@ -293,8 +291,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
broadcastConfiguration.isValid() &&
|
||||
!mBroadcasterMap.containsKey(broadcastConfiguration.getName()))
|
||||
{
|
||||
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(mThreadPoolManager,
|
||||
broadcastConfiguration);
|
||||
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(broadcastConfiguration);
|
||||
|
||||
if(audioBroadcaster != null)
|
||||
{
|
||||
@@ -403,7 +400,8 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
||||
deleteBroadcaster(previousChannelName);
|
||||
|
||||
//Delay restarting the broadcaster to allow remote server time to cleanup
|
||||
mThreadPoolManager.scheduleOnce(new DelayedBroadcasterStartup(broadcastConfiguration), 1, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.schedule(new DelayedBroadcasterStartup(broadcastConfiguration),
|
||||
1, TimeUnit.SECONDS);
|
||||
break;
|
||||
case CONFIGURATION_DELETE:
|
||||
deleteBroadcaster(broadcastEvent.getBroadcastConfiguration().getName());
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
package audio.broadcast;
|
||||
|
||||
import audio.AudioPacket;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import record.AudioRecorder;
|
||||
import sample.Listener;
|
||||
import util.ThreadPool;
|
||||
import util.TimeStamp;
|
||||
|
||||
import java.nio.file.Files;
|
||||
@@ -44,7 +44,6 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
|
||||
private static AtomicInteger sNextRecordingNumber = new AtomicInteger();
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private Listener<AudioRecording> mAudioRecordingListener;
|
||||
private BroadcastFormat mBroadcastFormat;
|
||||
private Path mTempDirectory;
|
||||
@@ -61,17 +60,13 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
*
|
||||
* Completed streamable audio recordings are nominated to the output listener (for broadcast) upon completion
|
||||
*
|
||||
* @param threadPoolManager for scheduling runnables
|
||||
* @param listener to receive completed audio recordings
|
||||
* @param tempDirectory where to store temporary audio recordings
|
||||
*/
|
||||
public StreamManager(ThreadPoolManager threadPoolManager, Listener<AudioRecording> listener,
|
||||
BroadcastFormat broadcastFormat, Path tempDirectory)
|
||||
public StreamManager(Listener<AudioRecording> listener, BroadcastFormat broadcastFormat, Path tempDirectory)
|
||||
{
|
||||
assert (tempDirectory != null && Files.isDirectory(tempDirectory));
|
||||
assert (mThreadPoolManager != null);
|
||||
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mAudioRecordingListener = listener;
|
||||
mBroadcastFormat = broadcastFormat;
|
||||
mTempDirectory = tempDirectory;
|
||||
@@ -90,8 +85,8 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
mRecorderMonitor = new RecorderMonitor();
|
||||
}
|
||||
|
||||
mRecorderMonitorFuture = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
|
||||
mRecorderMonitor, 2, TimeUnit.SECONDS);
|
||||
mRecorderMonitorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(mRecorderMonitor,
|
||||
0,2, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +140,7 @@ public class StreamManager implements Listener<AudioPacket>
|
||||
{
|
||||
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
|
||||
mBroadcastFormat);
|
||||
recorder.start(mThreadPoolManager.getScheduledExecutorService());
|
||||
recorder.start(ThreadPool.SCHEDULED);
|
||||
recorder.receive(audioPacket);
|
||||
mStreamRecorders.put(channelMetadataID, recorder);
|
||||
}
|
||||
|
||||
@@ -21,15 +21,14 @@ package audio.broadcast.icecast;
|
||||
import audio.broadcast.AudioBroadcaster;
|
||||
import audio.broadcast.BroadcastConfiguration;
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
private IBroadcastMetadataUpdater mMetadataUpdater;
|
||||
|
||||
public IcecastAudioBroadcaster(ThreadPoolManager threadPoolManager, BroadcastConfiguration broadcastConfiguration)
|
||||
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
|
||||
{
|
||||
super(threadPoolManager, broadcastConfiguration);
|
||||
super(broadcastConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +36,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
|
||||
*/
|
||||
protected IcecastConfiguration getConfiguration()
|
||||
{
|
||||
return (IcecastConfiguration)getBroadcastConfiguration();
|
||||
return (IcecastConfiguration) getBroadcastConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +44,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
if(mMetadataUpdater == null)
|
||||
{
|
||||
mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getThreadPoolManager(), getConfiguration());
|
||||
mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration());
|
||||
}
|
||||
|
||||
return mMetadataUpdater;
|
||||
|
||||
@@ -20,7 +20,6 @@ package audio.broadcast.icecast;
|
||||
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@@ -33,6 +32,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.ConnectException;
|
||||
@@ -50,7 +50,6 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
private final static Logger mLog = LoggerFactory.getLogger(IcecastBroadcastMetadataUpdater.class);
|
||||
private final static String UTF8 = "UTF-8";
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private IcecastConfiguration mIcecastConfiguration;
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
@@ -65,9 +64,8 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
|
||||
* sequence, those updates will be queued and processed in the order received.
|
||||
*/
|
||||
public IcecastBroadcastMetadataUpdater(ThreadPoolManager threadPoolManager, IcecastConfiguration icecastConfiguration)
|
||||
public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mIcecastConfiguration = icecastConfiguration;
|
||||
}
|
||||
|
||||
@@ -128,7 +126,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
|
||||
|
||||
if(updateRequest != null)
|
||||
{
|
||||
mThreadPoolManager.scheduleOnce(new Runnable()
|
||||
ThreadPool.SCHEDULED.schedule(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
|
||||
@@ -20,7 +20,6 @@ package audio.broadcast.icecast;
|
||||
|
||||
import audio.broadcast.BroadcastState;
|
||||
import audio.convert.MP3AudioConverter;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
@@ -38,6 +37,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -48,12 +48,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger( IcecastHTTPAudioBroadcaster.class );
|
||||
private static final Logger mLog = LoggerFactory.getLogger(IcecastHTTPAudioBroadcaster.class);
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
private Map<String, String> mHTTPHeaders;
|
||||
private Map<String,String> mHTTPHeaders;
|
||||
|
||||
private long mLastConnectionAttempt = 0;
|
||||
private AtomicBoolean mConnecting = new AtomicBoolean();
|
||||
@@ -69,9 +69,9 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Icecast stream
|
||||
*/
|
||||
public IcecastHTTPAudioBroadcaster(ThreadPoolManager threadPoolManager, IcecastHTTPConfiguration configuration)
|
||||
public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration)
|
||||
{
|
||||
super(threadPoolManager, configuration);
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +101,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
private boolean connect()
|
||||
{
|
||||
if(!connected() && canConnect() &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
mConnecting.compareAndSet(false, true))
|
||||
{
|
||||
mLastConnectionAttempt = System.currentTimeMillis();
|
||||
@@ -159,7 +159,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
}
|
||||
};
|
||||
|
||||
getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
@@ -264,10 +264,10 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
if(throwable instanceof ProtocolDecoderException)
|
||||
{
|
||||
Throwable cause = ((ProtocolDecoderException)throwable).getCause();
|
||||
Throwable cause = ((ProtocolDecoderException) throwable).getCause();
|
||||
|
||||
if(cause instanceof HttpException &&
|
||||
((HttpException)cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
|
||||
((HttpException) cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
|
||||
{
|
||||
//Ignore - Icecast 2.4 sometimes doesn't send any headers with their HTTP responses. Mina expects a
|
||||
//content-length for HTTP responses.
|
||||
@@ -294,7 +294,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
if(object instanceof DefaultHttpResponse)
|
||||
{
|
||||
DefaultHttpResponse response = (DefaultHttpResponse)object;
|
||||
DefaultHttpResponse response = (DefaultHttpResponse) object;
|
||||
|
||||
switch(response.getStatus())
|
||||
{
|
||||
@@ -322,7 +322,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
else
|
||||
{
|
||||
mLog.error("Icecast HTTP broadcaster - unrecognized message [ " + object.getClass() +
|
||||
"] received:" + object.toString());
|
||||
"] received:" + object.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ package audio.broadcast.icecast;
|
||||
import audio.broadcast.BroadcastState;
|
||||
import audio.broadcast.icecast.codec.IcecastCodecFactory;
|
||||
import audio.convert.MP3AudioConverter;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
@@ -31,6 +30,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
@@ -40,7 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( IcecastTCPAudioBroadcaster.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(IcecastTCPAudioBroadcaster.class);
|
||||
private final static String TERMINATOR = "\r\n";
|
||||
private final static String SEPARATOR = ":";
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
@@ -62,9 +62,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Icecast stream
|
||||
*/
|
||||
public IcecastTCPAudioBroadcaster(ThreadPoolManager threadPoolManager, IcecastTCPConfiguration configuration)
|
||||
public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration)
|
||||
{
|
||||
super(threadPoolManager, configuration);
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
private boolean connect()
|
||||
{
|
||||
if(!connected() && canConnect() &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
mConnecting.compareAndSet(false, true))
|
||||
{
|
||||
mLastConnectionAttempt = System.currentTimeMillis();
|
||||
@@ -149,8 +149,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
}
|
||||
};
|
||||
|
||||
getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
|
||||
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return connected();
|
||||
@@ -241,9 +240,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
|
||||
{
|
||||
if(cause instanceof IOException && ((IOException)cause).getMessage().startsWith("Connection reset"))
|
||||
if(cause instanceof IOException && ((IOException) cause).getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
IOException ioe = (IOException)cause;
|
||||
IOException ioe = (IOException) cause;
|
||||
|
||||
if(ioe.getMessage() != null && ioe.getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
@@ -271,7 +270,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
if(object instanceof String)
|
||||
{
|
||||
String message = (String)object;
|
||||
String message = (String) object;
|
||||
|
||||
if(message != null && !message.trim().isEmpty())
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ package audio.broadcast.shoutcast.v1;
|
||||
import audio.broadcast.AudioBroadcaster;
|
||||
import audio.broadcast.BroadcastState;
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
@@ -32,6 +31,7 @@ import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
@@ -41,7 +41,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( ShoutcastV1AudioBroadcaster.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV1AudioBroadcaster.class);
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
@@ -61,9 +61,9 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
*
|
||||
* @param configuration for the Shoutcast stream
|
||||
*/
|
||||
public ShoutcastV1AudioBroadcaster(ThreadPoolManager threadPoolManager, ShoutcastV1Configuration configuration)
|
||||
public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration)
|
||||
{
|
||||
super(threadPoolManager, configuration);
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
*/
|
||||
private ShoutcastV1Configuration getConfiguration()
|
||||
{
|
||||
return (ShoutcastV1Configuration)getBroadcastConfiguration();
|
||||
return (ShoutcastV1Configuration) getBroadcastConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,7 +79,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
if(mMetadataUpdater == null)
|
||||
{
|
||||
mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getThreadPoolManager(), getConfiguration());
|
||||
mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration());
|
||||
}
|
||||
|
||||
return mMetadataUpdater;
|
||||
@@ -111,7 +111,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
private boolean connect()
|
||||
{
|
||||
if(!connected() && canConnect() &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
(mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
|
||||
mConnecting.compareAndSet(false, true))
|
||||
{
|
||||
mLastConnectionAttempt = System.currentTimeMillis();
|
||||
@@ -171,8 +171,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
}
|
||||
};
|
||||
|
||||
getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
|
||||
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return connected();
|
||||
@@ -242,9 +241,9 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
|
||||
{
|
||||
if(cause instanceof IOException && ((IOException)cause).getMessage().startsWith("Connection reset"))
|
||||
if(cause instanceof IOException && ((IOException) cause).getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
IOException ioe = (IOException)cause;
|
||||
IOException ioe = (IOException) cause;
|
||||
|
||||
if(ioe.getMessage() != null && ioe.getMessage().startsWith("Connection reset"))
|
||||
{
|
||||
@@ -272,7 +271,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
|
||||
{
|
||||
if(object instanceof String)
|
||||
{
|
||||
String message = (String)object;
|
||||
String message = (String) object;
|
||||
|
||||
if(message != null && !message.trim().isEmpty())
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@ package audio.broadcast.shoutcast.v1;
|
||||
|
||||
import audio.broadcast.IBroadcastMetadataUpdater;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@@ -32,6 +31,7 @@ import org.apache.mina.http.api.HttpVersion;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.ConnectException;
|
||||
@@ -49,7 +49,6 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV1BroadcastMetadataUpdater.class);
|
||||
private final static String UTF8 = "UTF-8";
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ShoutcastV1Configuration mShoutcastV1Configuration;
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
@@ -63,9 +62,8 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
|
||||
* sequence, those updates will be queued and processed in the order received.
|
||||
*/
|
||||
public ShoutcastV1BroadcastMetadataUpdater(ThreadPoolManager threadPoolManager, ShoutcastV1Configuration shoutcastV1Configuration)
|
||||
public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mShoutcastV1Configuration = shoutcastV1Configuration;
|
||||
}
|
||||
|
||||
@@ -127,7 +125,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
|
||||
|
||||
if(updateRequest != null)
|
||||
{
|
||||
mThreadPoolManager.scheduleOnce(new Runnable()
|
||||
ThreadPool.SCHEDULED.schedule(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
|
||||
@@ -38,7 +38,6 @@ import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
|
||||
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
|
||||
import audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import org.apache.mina.core.RuntimeIoException;
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
@@ -48,6 +47,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import properties.SystemProperties;
|
||||
import util.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
@@ -81,12 +81,11 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
* This broadcaster uses the Apache Mina library for the streaming socket connection. The
|
||||
* ShoutcastV2IOHandler manages all interaction with the Shoutcast server and manages the overall broadcast state.
|
||||
*
|
||||
* @param threadPoolManager for thread pool access
|
||||
* @param configuration for the Shoutcast V2 stream
|
||||
*/
|
||||
public ShoutcastV2AudioBroadcaster(ThreadPoolManager threadPoolManager, ShoutcastV2Configuration configuration)
|
||||
public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration)
|
||||
{
|
||||
super(threadPoolManager, configuration);
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
public ShoutcastV2Configuration getConfiguration()
|
||||
@@ -207,8 +206,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
|
||||
}
|
||||
};
|
||||
|
||||
getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
|
||||
|
||||
ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return connected();
|
||||
|
||||
@@ -22,13 +22,12 @@ import audio.AudioEvent;
|
||||
import audio.AudioPacket;
|
||||
import audio.AudioPacket.Type;
|
||||
import channel.metadata.Metadata;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import source.mixer.MixerChannel;
|
||||
import util.ThreadPool;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.BooleanControl;
|
||||
@@ -59,7 +58,6 @@ public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
|
||||
private Listener<Metadata> mMetadataListener;
|
||||
private Broadcaster<AudioEvent> mAudioEventBroadcaster = new Broadcaster<>();
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture<?> mProcessorTask;
|
||||
|
||||
private SourceDataLine mOutput;
|
||||
@@ -82,21 +80,18 @@ public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
|
||||
* Maintains an internal non-blocking audio packet queue and processes this
|
||||
* queue 25 times a second (every 40 ms).
|
||||
*
|
||||
* @param threadPoolManager for assigning buffer processing schedule task
|
||||
* @param mixer to obtain source data line
|
||||
* @param mixerChannel either mono or left/right stereo
|
||||
* @param audioFormat to use during playback
|
||||
* @param lineInfo to use when obtaining the source data line
|
||||
* @param requestedBufferSize of approximately 1 second of audio
|
||||
*/
|
||||
public AudioOutput(ThreadPoolManager threadPoolManager,
|
||||
Mixer mixer,
|
||||
public AudioOutput(Mixer mixer,
|
||||
MixerChannel mixerChannel,
|
||||
AudioFormat audioFormat,
|
||||
Line.Info lineInfo,
|
||||
int requestedBufferSize)
|
||||
{
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
mMixer = mixer;
|
||||
mMixerChannel = mixerChannel;
|
||||
|
||||
@@ -141,9 +136,8 @@ public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
|
||||
}
|
||||
|
||||
/* Run the queue processor task every 40 milliseconds or 25 times a second */
|
||||
mProcessorTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.AUDIO_PROCESSING, new BufferProcessor(),
|
||||
40, TimeUnit.MILLISECONDS);
|
||||
mProcessorTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BufferProcessor(),
|
||||
0, 40, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
mAudioStartEvent = new AudioEvent(AudioEvent.Type.AUDIO_STARTED,
|
||||
@@ -170,12 +164,11 @@ public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
|
||||
{
|
||||
mCanProcessAudio = false;
|
||||
|
||||
if(mProcessorTask != null && mThreadPoolManager != null)
|
||||
if(mProcessorTask != null)
|
||||
{
|
||||
mThreadPoolManager.cancel(mProcessorTask);
|
||||
mProcessorTask.cancel(true);
|
||||
}
|
||||
|
||||
mThreadPoolManager = null;
|
||||
mProcessorTask = null;
|
||||
|
||||
mBuffer.clear();
|
||||
|
||||
@@ -1,74 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
* 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 audio.output;
|
||||
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import source.mixer.MixerChannel;
|
||||
|
||||
import javax.sound.sampled.Mixer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import javax.sound.sampled.Mixer;
|
||||
|
||||
import source.mixer.MixerChannel;
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
/**
|
||||
* Mono Audio output implementation
|
||||
*/
|
||||
public class MonoAudioOutput extends AudioOutput
|
||||
{
|
||||
private final static int BUFFER_SIZE = 8000;
|
||||
|
||||
public MonoAudioOutput( ThreadPoolManager threadPoolManager, Mixer mixer )
|
||||
{
|
||||
super( threadPoolManager,
|
||||
mixer,
|
||||
MixerChannel.MONO,
|
||||
AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO,
|
||||
AudioFormats.MONO_SOURCE_DATALINE_INFO,
|
||||
BUFFER_SIZE );
|
||||
}
|
||||
private final static int BUFFER_SIZE = 8000;
|
||||
|
||||
public MonoAudioOutput(Mixer mixer)
|
||||
{
|
||||
super(mixer, MixerChannel.MONO, AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO,
|
||||
AudioFormats.MONO_SOURCE_DATALINE_INFO, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the audio packet data into mono audio frames.
|
||||
*/
|
||||
protected ByteBuffer convert(AudioPacket packet)
|
||||
{
|
||||
if(packet.hasAudioBuffer())
|
||||
{
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
/**
|
||||
* Converts the audio packet data into mono audio frames.
|
||||
*/
|
||||
protected ByteBuffer convert( AudioPacket packet )
|
||||
{
|
||||
if( packet.hasAudioBuffer() )
|
||||
{
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
/* Little-endian byte buffer */
|
||||
ByteBuffer buffer =
|
||||
ByteBuffer.allocate( samples.length * 2 )
|
||||
.order( ByteOrder.LITTLE_ENDIAN );
|
||||
ByteBuffer buffer = ByteBuffer.allocate(samples.length * 2).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
|
||||
for( float sample: samples )
|
||||
{
|
||||
shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
for(float sample : samples)
|
||||
{
|
||||
shortBuffer.put((short) (sample * Short.MAX_VALUE));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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/>
|
||||
* 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 audio.output;
|
||||
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import source.mixer.MixerChannel;
|
||||
|
||||
import javax.sound.sampled.Mixer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import javax.sound.sampled.Mixer;
|
||||
|
||||
import source.mixer.MixerChannel;
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
/**
|
||||
* Stereo audio output implementation.
|
||||
* Stereo audio output implementation.
|
||||
*/
|
||||
public class StereoAudioOutput extends AudioOutput
|
||||
{
|
||||
private final static int BUFFER_SIZE = 16000;
|
||||
|
||||
public StereoAudioOutput( ThreadPoolManager threadPoolManager,
|
||||
Mixer mixer, MixerChannel channel )
|
||||
{
|
||||
super( threadPoolManager,
|
||||
mixer,
|
||||
channel,
|
||||
AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO,
|
||||
AudioFormats.STEREO_SOURCE_DATALINE_INFO,
|
||||
BUFFER_SIZE );
|
||||
}
|
||||
private final static int BUFFER_SIZE = 16000;
|
||||
|
||||
public StereoAudioOutput(Mixer mixer, MixerChannel channel)
|
||||
{
|
||||
super(mixer, channel, AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO, AudioFormats.STEREO_SOURCE_DATALINE_INFO,
|
||||
BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the audio packet data into stereo audio frames with the mixer
|
||||
* channel containing the audio and the other channel containing zero
|
||||
* valued (silent) samples.
|
||||
*/
|
||||
protected ByteBuffer convert(AudioPacket packet)
|
||||
{
|
||||
if(packet.hasAudioBuffer())
|
||||
{
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
/**
|
||||
* Converts the audio packet data into stereo audio frames with the mixer
|
||||
* channel containing the audio and the other channel containing zero
|
||||
* valued (silent) samples.
|
||||
*/
|
||||
protected ByteBuffer convert( AudioPacket packet )
|
||||
{
|
||||
if( packet.hasAudioBuffer() )
|
||||
{
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
/* Little-endian byte buffer */
|
||||
ByteBuffer buffer = ByteBuffer.allocate( samples.length * 4 )
|
||||
.order( ByteOrder.LITTLE_ENDIAN );
|
||||
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(samples.length * 4)
|
||||
.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
if( getMixerChannel() == MixerChannel.LEFT )
|
||||
{
|
||||
for( float sample: samples )
|
||||
{
|
||||
shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
|
||||
shortBuffer.put( (short)0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( float sample: samples )
|
||||
{
|
||||
shortBuffer.put( (short)0 );
|
||||
shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
|
||||
if(getMixerChannel() == MixerChannel.LEFT)
|
||||
{
|
||||
for(float sample : samples)
|
||||
{
|
||||
shortBuffer.put((short) (sample * Short.MAX_VALUE));
|
||||
shortBuffer.put((short) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(float sample : samples)
|
||||
{
|
||||
shortBuffer.put((short) 0);
|
||||
shortBuffer.put((short) (sample * Short.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user