#90 [WIP] merged metadata management for channel state, decoder states and audio metadata into a new metadata class. The new metadata class is maintained for each decoding audio channel, or in the future, a decoding TDMA channel. Audio playback, recording and streaming all use the same metadata object for the channel. The list of channel processing gui panels have been deleted and channel processing status will now reside in a table where each table row is a metadata instance from the processing channel. The channel processing manager is responsible for adding/removing the channel's metadata instance to/from the metadata table. This allows the channel processing table to be the controller for the messages, events and channel spectrum views, keyed to the selected table row metadata.

I still have to clean up the gui components and wire in the table selection listeners.
This commit is contained in:
Denny
2017-01-17 19:24:54 -05:00
parent 16b69d4aef
commit bc8873de01
67 changed files with 6207 additions and 10127 deletions

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2016 Dennis Sheirer
* 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
@@ -18,14 +18,11 @@
******************************************************************************/
package audio.broadcast;
import audio.AudioPacket;
import audio.IAudioPacketListener;
import audio.convert.ISilenceGenerator;
import audio.metadata.AudioMetadata;
import channel.metadata.Metadata;
import controller.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
import sample.Listener;
import java.io.ByteArrayInputStream;
@@ -34,14 +31,13 @@ import java.nio.file.Files;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class AudioBroadcaster implements Listener<AudioRecording>
{
private final static Logger mLog = LoggerFactory.getLogger( AudioBroadcaster.class );
private final static Logger mLog = LoggerFactory.getLogger(AudioBroadcaster.class);
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
@@ -107,9 +103,10 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
/**
* Broadcasts the next song's audio metadata prior to streaming the next song.
*
* @param metadata for the next recording that will be streamed
*/
protected void broadcastMetadata(AudioMetadata metadata)
protected void broadcastMetadata(Metadata metadata)
{
IBroadcastMetadataUpdater metadataUpdater = getMetadataUpdater();
@@ -136,7 +133,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
if(mThreadPoolManager != null)
{
mScheduledTask = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS );
mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
}
}
}
@@ -160,6 +157,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
/**
* Stream name for the broadcast configuration for this broadcaster
*
* @return stream name or null
*/
public String getStreamName()
@@ -246,7 +244,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
{
if(mBroadcastState != state)
{
mLog.info("[" + getStreamName() + "] status: " + state);
mLog.info("[" + getStreamName() + "] status: " + state);
mBroadcastState = state;
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
@@ -386,7 +384,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
{
mStreamedAudioCount++;
broadcast(new BroadcastEvent(AudioBroadcaster.this,
BroadcastEvent.Event.BROADCASTER_STREAMED_COUNT_CHANGE));
BroadcastEvent.Event.BROADCASTER_STREAMED_COUNT_CHANGE));
metadataUpdateRequired = true;
}
@@ -431,7 +429,7 @@ public abstract class AudioBroadcaster implements Listener<AudioRecording>
if(connected())
{
broadcastMetadata(nextRecording.getAudioMetadata());
broadcastMetadata(nextRecording.getMetadata());
}
metadataUpdateRequired = false;

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2016 Dennis Sheirer
* 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
@@ -18,7 +18,7 @@
******************************************************************************/
package audio.broadcast;
import audio.metadata.AudioMetadata;
import channel.metadata.Metadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,22 +30,23 @@ public class AudioRecording implements Comparable<AudioRecording>
private final static Logger mLog = LoggerFactory.getLogger(StreamManager.class);
private Path mPath;
private AudioMetadata mAudioMetadata;
private long mStartTime;
private long mRecordingLength;
private AtomicInteger mPendingReplayCount = new AtomicInteger();
private Metadata mMetadata;
/**
* Audio recording that is ready to be streamed
*
* @param path to the audio recording file
* @param audioMetadata associated with the recording
* @param metadata associated with the recording
* @param start time of recording in milliseconds since epoch
* @param recordingLength in milliseconds
*/
public AudioRecording(Path path, AudioMetadata audioMetadata, long start, long recordingLength)
public AudioRecording(Path path, Metadata metadata, long start, long recordingLength)
{
mPath = path;
mAudioMetadata = audioMetadata;
mMetadata = metadata;
mStartTime = start;
mRecordingLength = recordingLength;
}
@@ -61,9 +62,9 @@ public class AudioRecording implements Comparable<AudioRecording>
/**
* Optional audio metadata for the recording.
*/
public AudioMetadata getAudioMetadata()
public Metadata getMetadata()
{
return mAudioMetadata;
return mMetadata;
}
/**

View File

@@ -20,7 +20,7 @@ package audio.broadcast;
import alias.id.broadcast.BroadcastChannel;
import audio.AudioPacket;
import audio.metadata.AudioMetadata;
import channel.metadata.Metadata;
import controller.ThreadPoolManager;
import icon.IconManager;
import org.slf4j.Logger;
@@ -48,7 +48,7 @@ import java.util.regex.Pattern;
public class BroadcastModel extends AbstractTableModel implements Listener<AudioPacket>
{
private final static Logger mLog = LoggerFactory.getLogger( BroadcastModel.class );
private final static Logger mLog = LoggerFactory.getLogger(BroadcastModel.class);
public static final String TEMPORARY_STREAM_DIRECTORY = "streaming";
public static final String TEMPORARY_STREAM_FILE_SUFFIX = "temporary_streaming_file_";
@@ -84,7 +84,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
//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 );
new RecordingDeletionMonitor(), 15l, TimeUnit.SECONDS);
removeOrphanedTemporaryRecordings();
}
@@ -96,7 +96,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
{
List<String> names = new ArrayList<>();
for(BroadcastConfiguration configuration: mBroadcastConfigurations)
for(BroadcastConfiguration configuration : mBroadcastConfigurations)
{
names.add(configuration.getName());
}
@@ -117,7 +117,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
*/
public void addBroadcastConfigurations(List<BroadcastConfiguration> configurations)
{
for(BroadcastConfiguration configuration: configurations)
for(BroadcastConfiguration configuration : configurations)
{
addBroadcastConfiguration(configuration);
}
@@ -138,11 +138,11 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
int index = mBroadcastConfigurations.size() - 1;
fireTableRowsInserted( index, index );
fireTableRowsInserted(index, index);
mBroadcastConfigurationMap.put(configuration.getName(), configuration);
process( new BroadcastEvent( configuration, BroadcastEvent.Event.CONFIGURATION_ADD) );
process(new BroadcastEvent(configuration, BroadcastEvent.Event.CONFIGURATION_ADD));
}
}
}
@@ -164,6 +164,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
/**
* Updates the configuration's name so that it is unique among all other broadcast configurations
*
* @param configuration
*/
private void ensureUniqueName(BroadcastConfiguration configuration)
@@ -235,11 +236,11 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
return false;
}
for(BroadcastConfiguration configurationToCompare: mBroadcastConfigurations)
for(BroadcastConfiguration configurationToCompare : mBroadcastConfigurations)
{
if(configurationToCompare != configuration &&
configurationToCompare.getName() != null &&
configurationToCompare.getName().equals(name))
configurationToCompare.getName() != null &&
configurationToCompare.getName().equals(name))
{
return false;
}
@@ -258,9 +259,9 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
mBroadcastConfigurationMap.remove(broadcastConfiguration.getName());
process(new BroadcastEvent( broadcastConfiguration, BroadcastEvent.Event.CONFIGURATION_DELETE));
process(new BroadcastEvent(broadcastConfiguration, BroadcastEvent.Event.CONFIGURATION_DELETE));
fireTableRowsDeleted( index, index );
fireTableRowsDeleted(index, index);
}
}
@@ -275,8 +276,8 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
@Override
public void receive(AudioPacket audioPacket)
{
if (audioPacket.hasAudioMetadata() &&
audioPacket.getAudioMetadata().isStreamable())
if(audioPacket.hasMetadata() &&
audioPacket.getMetadata().isStreamable())
{
mStreamManager.receive(audioPacket);
}
@@ -287,7 +288,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
*/
private void createBroadcaster(BroadcastConfiguration broadcastConfiguration)
{
if (broadcastConfiguration != null &&
if(broadcastConfiguration != null &&
broadcastConfiguration.isEnabled() &&
broadcastConfiguration.isValid() &&
!mBroadcasterMap.containsKey(broadcastConfiguration.getName()))
@@ -295,7 +296,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
AudioBroadcaster audioBroadcaster = BroadcastFactory.getBroadcaster(mThreadPoolManager,
broadcastConfiguration);
if (audioBroadcaster != null)
if(audioBroadcaster != null)
{
audioBroadcaster.setListener(new Listener<BroadcastEvent>()
{
@@ -377,7 +378,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
*/
private void broadcast(BroadcastEvent event)
{
mBroadcastEventBroadcaster.broadcast( event );
mBroadcastEventBroadcaster.broadcast(event);
}
/**
@@ -395,7 +396,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
case CONFIGURATION_CHANGE:
BroadcastConfiguration broadcastConfiguration = broadcastEvent.getBroadcastConfiguration();
int index = mBroadcastConfigurations.indexOf(broadcastConfiguration);
fireTableRowsUpdated( index, index );
fireTableRowsUpdated(index, index);
//Delete and recreate the broadcaster for any broadcast configuration changes
String previousChannelName = cleanupMapAssociations(broadcastConfiguration);
@@ -452,7 +453,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
{
String oldName = null;
for(Map.Entry<String,BroadcastConfiguration> entry: mBroadcastConfigurationMap.entrySet())
for(Map.Entry<String,BroadcastConfiguration> entry : mBroadcastConfigurationMap.entrySet())
{
if(entry.getValue() == broadcastConfiguration)
{
@@ -488,7 +489,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
{
try
{
if( rowIndex <= mBroadcastConfigurations.size())
if(rowIndex <= mBroadcastConfigurations.size())
{
BroadcastConfiguration configuration = mBroadcastConfigurations.get(rowIndex);
@@ -686,19 +687,19 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
@Override
public void receive(AudioRecording audioRecording)
{
AudioMetadata metadata = audioRecording.getAudioMetadata();
Metadata metadata = audioRecording.getMetadata();
if(metadata != null && metadata.isStreamable())
{
for (BroadcastChannel broadcastChannel : metadata.getBroadcastChannels())
for(BroadcastChannel broadcastChannel : metadata.getBroadcastChannels())
{
String channelName = broadcastChannel.getChannelName();
if (channelName != null)
if(channelName != null)
{
AudioBroadcaster audioBroadcaster = getBroadcaster(channelName);
if (audioBroadcaster != null)
if(audioBroadcaster != null)
{
audioRecording.addPendingReplay();
audioBroadcaster.receive(audioRecording);
@@ -739,7 +740,7 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
if(!recordingsToDelete.isEmpty())
{
for(AudioRecording recordingToDelete: recordingsToDelete)
for(AudioRecording recordingToDelete : recordingsToDelete)
{
mRecordingQueue.remove(recordingToDelete);
removeRecording(recordingToDelete);

View File

@@ -18,7 +18,7 @@
******************************************************************************/
package audio.broadcast;
import audio.metadata.AudioMetadata;
import channel.metadata.Metadata;
public interface IBroadcastMetadataUpdater
{
@@ -27,5 +27,5 @@ public interface IBroadcastMetadataUpdater
*
* @param metadata containing metadata attributes
*/
void update(AudioMetadata metadata);
void update(Metadata metadata);
}

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2016 Dennis Sheirer
* 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
@@ -48,7 +48,7 @@ public class StreamManager implements Listener<AudioPacket>
private Listener<AudioRecording> mAudioRecordingListener;
private BroadcastFormat mBroadcastFormat;
private Path mTempDirectory;
private Map<Integer, AudioRecorder> mStreamRecorders = new HashMap<>();
private Map<Integer,AudioRecorder> mStreamRecorders = new HashMap<>();
private Runnable mRecorderMonitor;
private ScheduledFuture<?> mRecorderMonitorFuture;
private AtomicBoolean mRunning = new AtomicBoolean();
@@ -68,8 +68,8 @@ public class StreamManager implements Listener<AudioPacket>
public StreamManager(ThreadPoolManager threadPoolManager, Listener<AudioRecording> listener,
BroadcastFormat broadcastFormat, Path tempDirectory)
{
assert(tempDirectory != null && Files.isDirectory(tempDirectory));
assert(mThreadPoolManager != null);
assert (tempDirectory != null && Files.isDirectory(tempDirectory));
assert (mThreadPoolManager != null);
mThreadPoolManager = threadPoolManager;
mAudioRecordingListener = listener;
@@ -91,7 +91,7 @@ public class StreamManager implements Listener<AudioPacket>
}
mRecorderMonitorFuture = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
mRecorderMonitor, 2, TimeUnit.SECONDS);
mRecorderMonitor, 2, TimeUnit.SECONDS);
}
}
@@ -107,11 +107,11 @@ public class StreamManager implements Listener<AudioPacket>
mRecorderMonitorFuture.cancel(true);
}
synchronized (mStreamRecorders)
synchronized(mStreamRecorders)
{
List<Integer> streamKeys = new ArrayList<>(mStreamRecorders.keySet());
for(Integer streamKey: streamKeys)
for(Integer streamKey : streamKeys)
{
removeRecorder(streamKey);
}
@@ -122,19 +122,19 @@ public class StreamManager implements Listener<AudioPacket>
@Override
public void receive(AudioPacket audioPacket)
{
if(mRunning.get() && audioPacket.hasAudioMetadata())
if(mRunning.get() && audioPacket.hasMetadata())
{
synchronized (mStreamRecorders)
synchronized(mStreamRecorders)
{
int sourceChannelID = audioPacket.getAudioMetadata().getSource();
int channelMetadataID = audioPacket.getMetadata().getMetadataID();
AudioPacket.Type type = audioPacket.getType();
if(type == AudioPacket.Type.AUDIO)
{
if(mStreamRecorders.containsKey(sourceChannelID))
if(mStreamRecorders.containsKey(channelMetadataID))
{
AudioRecorder recorder = mStreamRecorders.get(sourceChannelID);
AudioRecorder recorder = mStreamRecorders.get(channelMetadataID);
if(recorder != null)
{
@@ -144,15 +144,15 @@ public class StreamManager implements Listener<AudioPacket>
else
{
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
mBroadcastFormat);
mBroadcastFormat);
recorder.start(mThreadPoolManager.getScheduledExecutorService());
recorder.receive(audioPacket);
mStreamRecorders.put(sourceChannelID, recorder);
mStreamRecorders.put(channelMetadataID, recorder);
}
}
else if(type == AudioPacket.Type.END)
{
removeRecorder(sourceChannelID);
removeRecorder(channelMetadataID);
}
else
{
@@ -203,8 +203,8 @@ public class StreamManager implements Listener<AudioPacket>
StringBuilder sb = new StringBuilder();
sb.append(BroadcastModel.TEMPORARY_STREAM_FILE_SUFFIX);
sb.append(sNextRecordingNumber.incrementAndGet()).append("_");
sb.append( TimeStamp.getLongTimeStamp( "_" ) );
sb.append( mBroadcastFormat.getFileExtension() );
sb.append(TimeStamp.getLongTimeStamp("_"));
sb.append(mBroadcastFormat.getFileExtension());
Path temporaryRecordingPath = mTempDirectory.resolve(sb.toString());
@@ -219,19 +219,19 @@ public class StreamManager implements Listener<AudioPacket>
@Override
public void run()
{
synchronized (mStreamRecorders)
synchronized(mStreamRecorders)
{
long now = System.currentTimeMillis();
mStreamRecorders.entrySet().stream()
.filter(entry -> entry.getValue().getTimeRecordingStart() + MAXIMUM_RECORDER_LIFESPAN_MILLIS < now)
.forEach(entry ->
{
mLog.debug("Maximum recording time limit reached - removing recorder: " +
entry.getValue().getPath().toString());
{
mLog.debug("Maximum recording time limit reached - removing recorder: " +
entry.getValue().getPath().toString());
removeRecorder(entry.getKey());
});
removeRecorder(entry.getKey());
});
}
}
}

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2016 Dennis Sheirer
* 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
@@ -19,9 +19,7 @@
package audio.broadcast.icecast;
import audio.broadcast.IBroadcastMetadataUpdater;
import audio.metadata.AudioMetadata;
import audio.metadata.Metadata;
import audio.metadata.MetadataType;
import channel.metadata.Metadata;
import controller.ThreadPoolManager;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
@@ -58,7 +56,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
private NioSocketConnector mSocketConnector;
private AtomicBoolean mUpdating = new AtomicBoolean();
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
private Map<String, String> mHTTPHeaders;
private Map<String,String> mHTTPHeaders;
private boolean mStackTraceLoggingSuppressed;
/**
@@ -78,7 +76,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
*/
private NioSocketConnector getSocketConnector()
{
if (mSocketConnector == null)
if(mSocketConnector == null)
{
mSocketConnector = new NioSocketConnector();
// mSocketConnector.getFilterChain().addLast("logger", new LoggingFilter(IcecastBroadcastMetadataUpdater.class));
@@ -116,19 +114,19 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
* and will remain in the update queue until the next metadata update is requested. However, this is a design
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
*/
public void update(AudioMetadata audioMetadata)
public void update(Metadata metadata)
{
mMetadataQueue.offer(getSong(audioMetadata));
mMetadataQueue.offer(getSong(metadata));
if (mUpdating.compareAndSet(false, true))
if(mUpdating.compareAndSet(false, true))
{
String song = mMetadataQueue.poll();
while (song != null)
while(song != null)
{
HttpRequest updateRequest = createUpdateRequest(song);
if (updateRequest != null)
if(updateRequest != null)
{
mThreadPoolManager.scheduleOnce(new Runnable()
{
@@ -143,22 +141,22 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
connectFuture.awaitUninterruptibly();
IoSession session = connectFuture.getSession();
if (session != null)
if(session != null)
{
session.write(updateRequest);
}
}
catch (Exception e)
catch(Exception e)
{
Throwable throwableCause = e.getCause();
if (throwableCause instanceof ConnectException)
if(throwableCause instanceof ConnectException)
{
//Do nothing, the server is unavailable
}
else
{
if (!mStackTraceLoggingSuppressed)
if(!mStackTraceLoggingSuppressed)
{
mLog.error("Error sending metadata update. Future errors will " +
"be suppressed", e);
@@ -182,52 +180,45 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
/**
* Creates the song information for a metadata update
*/
private static String getSong(AudioMetadata audioMetadata)
private static String getSong(Metadata metadata)
{
StringBuilder sb = new StringBuilder();
if(audioMetadata != null)
if(metadata != null)
{
Metadata to = audioMetadata.getMetadata(MetadataType.TO);
String to = metadata.getPrimaryAddressTo().getIdentifier();
sb.append("TO:");
if(to != null)
if(metadata.getPrimaryAddressTo().hasAlias())
{
if(to.hasAlias())
{
sb.append(to.getAlias().getName());
}
else
{
sb.append(to.getValue());
}
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
}
else if(metadata.getPrimaryAddressTo().hasIdentifier())
{
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
}
else
{
sb.append("UNKNOWN");
}
Metadata from = audioMetadata.getMetadata(MetadataType.FROM);
sb.append(" FROM:");
if(from != null)
if(metadata.getPrimaryAddressFrom().hasAlias())
{
if(from.hasAlias())
{
sb.append(from.getAlias().getName());
}
else
{
sb.append(from.getValue());
}
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
}
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
{
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
}
else
{
sb.append("UNKNOWN");
}
}
else
{
@@ -255,7 +246,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
return request;
}
catch (UnsupportedEncodingException e)
catch(UnsupportedEncodingException e)
{
//This should never happen
mLog.error("UTF-8 encoding is not supported - can't update song metadata");

View File

@@ -19,9 +19,7 @@
package audio.broadcast.shoutcast.v1;
import audio.broadcast.IBroadcastMetadataUpdater;
import audio.metadata.AudioMetadata;
import audio.metadata.Metadata;
import audio.metadata.MetadataType;
import channel.metadata.Metadata;
import controller.ThreadPoolManager;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
@@ -57,7 +55,6 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
private NioSocketConnector mSocketConnector;
private AtomicBoolean mUpdating = new AtomicBoolean();
private Queue<String> mMetadataQueue = new LinkedTransferQueue<>();
private Map<String, String> mHTTPHeaders;
private boolean mStackTraceLoggingSuppressed;
/**
@@ -77,7 +74,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
*/
private NioSocketConnector getSocketConnector()
{
if (mSocketConnector == null)
if(mSocketConnector == null)
{
mSocketConnector = new NioSocketConnector();
@@ -116,19 +113,19 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
* and will remain in the update queue until the next metadata update is requested. However, this is a design
* trade-off to avoid having a scheduled runnable repeatedly processing the update queue.
*/
public void update(AudioMetadata audioMetadata)
public void update(Metadata metadata)
{
mMetadataQueue.offer(getSong(audioMetadata));
mMetadataQueue.offer(getSong(metadata));
if (mUpdating.compareAndSet(false, true))
if(mUpdating.compareAndSet(false, true))
{
String song = mMetadataQueue.poll();
while (song != null)
while(song != null)
{
HttpRequest updateRequest = createUpdateRequest(song);
if (updateRequest != null)
if(updateRequest != null)
{
mThreadPoolManager.scheduleOnce(new Runnable()
{
@@ -143,22 +140,22 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
connectFuture.awaitUninterruptibly();
IoSession session = connectFuture.getSession();
if (session != null)
if(session != null)
{
session.write(updateRequest);
}
}
catch (Exception e)
catch(Exception e)
{
Throwable throwableCause = e.getCause();
if (throwableCause instanceof ConnectException)
if(throwableCause instanceof ConnectException)
{
//Do nothing, the server is unavailable
}
else
{
if (!mStackTraceLoggingSuppressed)
if(!mStackTraceLoggingSuppressed)
{
mLog.error("Error sending metadata update. Future errors will " +
"be suppressed", e);
@@ -182,52 +179,45 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
/**
* Creates the song information for a metadata update
*/
private static String getSong(AudioMetadata audioMetadata)
private static String getSong(Metadata metadata)
{
StringBuilder sb = new StringBuilder();
if(audioMetadata != null)
if(metadata != null)
{
Metadata to = audioMetadata.getMetadata(MetadataType.TO);
String to = metadata.getPrimaryAddressTo().getIdentifier();
sb.append("TO:");
if(to != null)
if(metadata.getPrimaryAddressTo().hasAlias())
{
if(to.hasAlias())
{
sb.append(to.getAlias().getName());
}
else
{
sb.append(to.getValue());
}
sb.append(metadata.getPrimaryAddressTo().getAlias().getName());
}
else if(metadata.getPrimaryAddressTo().hasIdentifier())
{
sb.append(metadata.getPrimaryAddressTo().getIdentifier());
}
else
{
sb.append("UNKNOWN");
}
Metadata from = audioMetadata.getMetadata(MetadataType.FROM);
sb.append(" FROM:");
if(from != null)
if(metadata.getPrimaryAddressFrom().hasAlias())
{
if(from.hasAlias())
{
sb.append(from.getAlias().getName());
}
else
{
sb.append(from.getValue());
}
sb.append(metadata.getPrimaryAddressFrom().getAlias().getName());
}
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
{
sb.append(metadata.getPrimaryAddressFrom().getIdentifier());
}
else
{
sb.append("UNKNOWN");
}
}
else
{
@@ -256,7 +246,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
return request;
}
catch (UnsupportedEncodingException e)
catch(UnsupportedEncodingException e)
{
//This should never happen
mLog.error("UTF-8 encoding is not supported - can't update song metadata");

View File

@@ -37,9 +37,7 @@ import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageFactory;
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
import audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
import audio.metadata.AudioMetadata;
import audio.metadata.Metadata;
import audio.metadata.MetadataType;
import channel.metadata.Metadata;
import controller.ThreadPoolManager;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
@@ -62,7 +60,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBroadcastMetadataUpdater
{
private final static Logger mLog = LoggerFactory.getLogger( ShoutcastV2AudioBroadcaster.class );
private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV2AudioBroadcaster.class);
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
private int mMaxPayloadSize = 16377;
@@ -93,7 +91,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
public ShoutcastV2Configuration getConfiguration()
{
return (ShoutcastV2Configuration)getBroadcastConfiguration();
return (ShoutcastV2Configuration) getBroadcastConfiguration();
}
/**
@@ -122,7 +120,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
}
@Override
public void update(AudioMetadata metadata)
public void update(Metadata metadata)
{
List<UltravoxMessage> metadataMessages = getMetadataMessages(metadata);
@@ -149,7 +147,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
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();
@@ -242,7 +240,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
* @param metadata containing audio metadata tags and attributes
* @return a sequence of CacheableXMLMetadata messages sufficient to carry the complete set of metadata
*/
private List<UltravoxMessage> getMetadataMessages(AudioMetadata metadata)
private List<UltravoxMessage> getMetadataMessages(Metadata metadata)
{
StringBuilder sb = new StringBuilder();
@@ -264,30 +262,22 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
if(metadata != null)
{
Metadata to = metadata.getMetadata(MetadataType.TO);
if(to != null)
if(metadata.getPrimaryAddressTo().hasAlias())
{
if(to.hasAlias())
{
sb.append(UltravoxMetadata.TITLE_2.asXML(to.getAlias().toString()));
}
else
{
sb.append(UltravoxMetadata.TITLE_2.asXML(to.getValue()));
}
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getAlias().getName()));
}
else if(metadata.getPrimaryAddressTo().hasIdentifier())
{
sb.append(UltravoxMetadata.TITLE_2.asXML(metadata.getPrimaryAddressTo().getIdentifier()));
}
Metadata from = metadata.getMetadata(MetadataType.FROM);
if(from != null)
if(metadata.getPrimaryAddressFrom().hasAlias())
{
if(from.hasAlias())
{
sb.append(UltravoxMetadata.TITLE_3.asXML("From: " + from.getAlias().toString()));
}
else
{
sb.append(UltravoxMetadata.TITLE_3.asXML("From: " + from.getValue()));
}
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getAlias().getName()));
}
else if(metadata.getPrimaryAddressFrom().hasIdentifier())
{
sb.append(UltravoxMetadata.TITLE_3.asXML("From:" + metadata.getPrimaryAddressFrom().getIdentifier()));
}
}
else
@@ -301,7 +291,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
int pointer = 0;
int messageCounter = 1;
int messageCount = (int)Math.ceil((double)xml.length / (double)(mMaxPayloadSize - 6));
int messageCount = (int) Math.ceil((double) xml.length / (double) (mMaxPayloadSize - 6));
if(messageCount > 32)
{
@@ -317,9 +307,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
byte[] payload = new byte[payloadSize + 6];
payload[1] = (byte)(0x01);
payload[3] = (byte)(messageCount & 0xFF);
payload[5] = (byte)(messageCounter & 0xFF);
payload[1] = (byte) (0x01);
payload[3] = (byte) (messageCount & 0xFF);
payload[5] = (byte) (messageCounter & 0xFF);
System.arraycopy(xml, pointer, payload, 6, payloadSize);
@@ -368,9 +358,9 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
@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"))
{
@@ -398,12 +388,12 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
{
if(object instanceof UltravoxMessage)
{
UltravoxMessage ultravoxMessage = (UltravoxMessage)object;
UltravoxMessage ultravoxMessage = (UltravoxMessage) object;
switch (ultravoxMessage.getMessageType())
switch(ultravoxMessage.getMessageType())
{
case REQUEST_CIPHER:
String cipherKey = ((RequestCipher)ultravoxMessage).getCipher();
String cipherKey = ((RequestCipher) ultravoxMessage).getCipher();
AuthenticateBroadcast authenticateBroadcast = new AuthenticateBroadcast();
@@ -476,7 +466,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
}
else
{
mMaxPayloadSize = ((NegotiateMaxPayloadSize)ultravoxMessage).getMaximumPayloadSize();
mMaxPayloadSize = ((NegotiateMaxPayloadSize) ultravoxMessage).getMaximumPayloadSize();
ConfigureIcyPublic configureIcyPublic = new ConfigureIcyPublic();
configureIcyPublic.setPublic(getConfiguration().isPublic());