Merge pull request #182 from DSheirer/176-streaming-handle-additional-io-exceptions

Resolves #176 - resolves 2 streaming related issues
This commit is contained in:
Denny Sheirer
2017-02-10 22:06:32 +00:00
committed by GitHub
4 changed files with 115 additions and 71 deletions

View File

@@ -25,76 +25,99 @@ import javax.xml.bind.annotation.XmlAttribute;
public class BroadcastChannel extends AliasID implements Comparable<BroadcastChannel> public class BroadcastChannel extends AliasID implements Comparable<BroadcastChannel>
{ {
private String mChannelName; private String mChannelName;
public BroadcastChannel() public BroadcastChannel()
{ {
//JAXB Constructor //JAXB Constructor
} }
@Override @Override
public int compareTo(BroadcastChannel other) public int compareTo(BroadcastChannel other)
{ {
if(mChannelName != null && other.getChannelName() != null) if(mChannelName != null && other.getChannelName() != null)
{ {
return mChannelName.compareTo(other.getChannelName()); return mChannelName.compareTo(other.getChannelName());
} }
else if(mChannelName != null) else if(mChannelName != null)
{ {
return -1; return -1;
} }
else else
{ {
return 1; return 1;
} }
} }
/** @Override
* Creates a named broadcast channel public boolean equals(Object o)
*/ {
public BroadcastChannel(String channelName) if(this == o)
{ {
mChannelName = channelName; return true;
} }
if(!(o instanceof BroadcastChannel))
{
return false;
}
/** BroadcastChannel that = (BroadcastChannel)o;
* Name of the broadcastAudio channel configuration
*/
@XmlAttribute(name="channel")
public String getChannelName()
{
return mChannelName;
}
/** return getChannelName() != null ? getChannelName().equals(that.getChannelName()) : that.getChannelName() == null;
* Sets the name of the broadcastAudio channel configuration }
*/
public void setChannelName(String channel)
{
mChannelName = channel;
}
@Override @Override
public AliasIDType getType() public int hashCode()
{ {
return AliasIDType.BROADCAST_CHANNEL; return getChannelName() != null ? getChannelName().hashCode() : 0;
} }
@Override /**
public boolean isValid() * Creates a named broadcast channel
{ */
return mChannelName != null; public BroadcastChannel(String channelName)
} {
mChannelName = channelName;
}
@Override /**
public boolean matches( AliasID id ) * Name of the broadcastAudio channel configuration
{ */
return false; @XmlAttribute(name = "channel")
} public String getChannelName()
{
@Override return mChannelName;
public String toString() }
{
/**
* Sets the name of the broadcastAudio channel configuration
*/
public void setChannelName(String channel)
{
mChannelName = channel;
}
@Override
public AliasIDType getType()
{
return AliasIDType.BROADCAST_CHANNEL;
}
@Override
public boolean isValid()
{
return mChannelName != null;
}
@Override
public boolean matches(AliasID id)
{
return false;
}
@Override
public String toString()
{
if(isValid()) if(isValid())
{ {
return "Broadcast Channel: " + mChannelName; return "Broadcast Channel: " + mChannelName;
@@ -103,5 +126,5 @@ public class BroadcastChannel extends AliasID implements Comparable<BroadcastCha
{ {
return "Broadcast Channel: None Selected"; return "Broadcast Channel: None Selected";
} }
} }
} }

View File

@@ -707,7 +707,9 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
if(metadata != null && metadata.isStreamable()) if(metadata != null && metadata.isStreamable())
{ {
for(BroadcastChannel broadcastChannel : metadata.getBroadcastChannels()) List<BroadcastChannel> broadcastChannels = metadata.getBroadcastChannels();
for(BroadcastChannel broadcastChannel : broadcastChannels)
{ {
String channelName = broadcastChannel.getChannelName(); String channelName = broadcastChannel.getChannelName();

View File

@@ -248,6 +248,12 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{ {
String reason = ioe.getMessage(); String reason = ioe.getMessage();
if(connected())
{
mLog.info("Streaming connection error detected - resetting connection - " + reason);
disconnect();
connect();
}
if(reason.startsWith("Connection reset")) if(reason.startsWith("Connection reset"))
{ {
mLog.info("Streaming connection reset by remote server - reestablishing connection"); mLog.info("Streaming connection reset by remote server - reestablishing connection");
@@ -264,14 +270,14 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{ {
setBroadcastState(BroadcastState.ERROR); setBroadcastState(BroadcastState.ERROR);
disconnect(); disconnect();
mLog.error("Unrecognized IO error: " + reason + ". Streaming halted."); mLog.error("Unrecognized IO error: " + reason + ". Streaming halted.", cause);
} }
} }
else else
{ {
setBroadcastState(BroadcastState.ERROR); setBroadcastState(BroadcastState.ERROR);
disconnect(); disconnect();
mLog.error("Unspecified IO error - streaming halted."); mLog.error("Unspecified IO error - streaming halted.", cause);
} }
} }
else else

View File

@@ -163,7 +163,10 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
/** /**
* Closes the recording file. Upon successful closing of the recording file, the listener is notified that the * Closes the recording file. Upon successful closing of the recording file, the listener is notified that the
* audio recorder is closed. * audio recorder is closed. There is potential for the calling thread (here) and the buffer processor thread to
* both inform the recording closed listener that the recording is ended. So, we synchronize on the listener and
* the first thread to get the lock informs the listener and then nullifies the listener pointer so that if the
* second thread attempts a duplicate notification the listener would be null at that point.
*/ */
public void close(Listener<AudioRecorder> listener) public void close(Listener<AudioRecorder> listener)
{ {
@@ -171,8 +174,14 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
if(!mRunning.compareAndSet(true, false)) if(!mRunning.compareAndSet(true, false))
{ {
//If this recorder has already been stopped/closed, immediately inform the listener synchronized(mRecordingClosedListener)
mRecordingClosedListener.receive(this); {
if(mRecordingClosedListener != null)
{
mRecordingClosedListener.receive(AudioRecorder.this);
mRecordingClosedListener = null;
}
}
} }
} }
@@ -303,9 +312,13 @@ public abstract class AudioRecorder extends Module implements Listener<AudioPack
} }
} }
if(mRecordingClosedListener != null) synchronized(mRecordingClosedListener)
{ {
mRecordingClosedListener.receive(AudioRecorder.this); if(mRecordingClosedListener != null)
{
mRecordingClosedListener.receive(AudioRecorder.this);
mRecordingClosedListener = null;
}
} }
if(mProcessorHandle != null) if(mProcessorHandle != null)