mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 09:37:36 -05:00
#30 WIP - adds support for Icecast 2 (v2.4+) audio streams. Adds additional fields (genre, description, public) to Icecast 1 configuration editors. Adds audio broadcast delay to Broadcastify and Icecast editors.
This commit is contained in:
@@ -22,6 +22,7 @@ import alias.id.broadcast.BroadcastChannel;
|
|||||||
import audio.AudioPacket;
|
import audio.AudioPacket;
|
||||||
import controller.ThreadPoolManager;
|
import controller.ThreadPoolManager;
|
||||||
import org.asynchttpclient.DefaultAsyncHttpClient;
|
import org.asynchttpclient.DefaultAsyncHttpClient;
|
||||||
|
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import properties.SystemProperties;
|
import properties.SystemProperties;
|
||||||
@@ -360,7 +361,13 @@ public class BroadcastModel extends AbstractTableModel implements Listener<Audio
|
|||||||
{
|
{
|
||||||
if (mDefaultAsyncHttpClient == null)
|
if (mDefaultAsyncHttpClient == null)
|
||||||
{
|
{
|
||||||
mDefaultAsyncHttpClient = new DefaultAsyncHttpClient();
|
//Set read timeout to never expire so that our streams don't get interrupted
|
||||||
|
DefaultAsyncHttpClientConfig config =
|
||||||
|
new DefaultAsyncHttpClientConfig.Builder()
|
||||||
|
.setReadTimeout(-1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mDefaultAsyncHttpClient = new DefaultAsyncHttpClient(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mDefaultAsyncHttpClient;
|
return mDefaultAsyncHttpClient;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import sample.Listener;
|
|||||||
import settings.SettingsManager;
|
import settings.SettingsManager;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@@ -41,15 +43,19 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger( BroadcastifyConfigurationEditor.class );
|
private final static Logger mLog = LoggerFactory.getLogger( BroadcastifyConfigurationEditor.class );
|
||||||
|
|
||||||
|
private static final int ONE_MINUTE_MS = 60000;
|
||||||
|
|
||||||
private JTextField mName;
|
private JTextField mName;
|
||||||
private JTextField mServer;
|
private JTextField mServer;
|
||||||
private JTextField mPort;
|
private JTextField mPort;
|
||||||
private JTextField mMountPoint;
|
private JTextField mMountPoint;
|
||||||
private JTextField mPassword;
|
private JTextField mPassword;
|
||||||
private JTextField mFeedID;
|
private JTextField mFeedID;
|
||||||
|
private JSlider mDelay;
|
||||||
|
private JLabel mDelayValue;
|
||||||
|
private JCheckBox mEnabled;
|
||||||
private JButton mSaveButton;
|
private JButton mSaveButton;
|
||||||
private JButton mResetButton;
|
private JButton mResetButton;
|
||||||
private JCheckBox mEnabled;
|
|
||||||
|
|
||||||
public BroadcastifyConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
public BroadcastifyConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
||||||
SettingsManager settingsManager)
|
SettingsManager settingsManager)
|
||||||
@@ -61,7 +67,8 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]", "[][][][][][][][][][][grow,fill]" ) );
|
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]",
|
||||||
|
"[][][][][][][][][][][][][grow,fill]" ) );
|
||||||
setPreferredSize(new Dimension(150,400));
|
setPreferredSize(new Dimension(150,400));
|
||||||
|
|
||||||
|
|
||||||
@@ -130,6 +137,27 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
mFeedID.setToolTipText("Feed ID (optional). See MyBCFY feed details");
|
mFeedID.setToolTipText("Feed ID (optional). See MyBCFY feed details");
|
||||||
add(mFeedID);
|
add(mFeedID);
|
||||||
|
|
||||||
|
|
||||||
|
add(new JLabel());
|
||||||
|
mDelayValue = new JLabel("0 Minutes");
|
||||||
|
add(mDelayValue);
|
||||||
|
|
||||||
|
add(new JLabel("Delay:"));
|
||||||
|
mDelay = new JSlider(0,60,0);
|
||||||
|
mDelay.setMajorTickSpacing(10);
|
||||||
|
mDelay.setMinorTickSpacing(5);
|
||||||
|
mDelay.addChangeListener(new ChangeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e)
|
||||||
|
{
|
||||||
|
mDelayValue.setText(mDelay.getValue() + " Minutes");
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mDelay.setToolTipText("Audio broadcast delay in minutes");
|
||||||
|
add(mDelay);
|
||||||
|
|
||||||
mEnabled = new JCheckBox("Enabled");
|
mEnabled = new JCheckBox("Enabled");
|
||||||
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
||||||
mEnabled.addActionListener(new ActionListener()
|
mEnabled.addActionListener(new ActionListener()
|
||||||
@@ -195,6 +223,7 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
mMountPoint.setText(config.getMountPoint());
|
mMountPoint.setText(config.getMountPoint());
|
||||||
mPassword.setText(config.getPassword());
|
mPassword.setText(config.getPassword());
|
||||||
mFeedID.setText(String.valueOf(config.getFeedID()));
|
mFeedID.setText(String.valueOf(config.getFeedID()));
|
||||||
|
mDelay.setValue((int)(config.getDelay() / ONE_MINUTE_MS));
|
||||||
mEnabled.setSelected(config.isEnabled());
|
mEnabled.setSelected(config.isEnabled());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -205,6 +234,7 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
mMountPoint.setText(null);
|
mMountPoint.setText(null);
|
||||||
mPassword.setText(null);
|
mPassword.setText(null);
|
||||||
mFeedID.setText(null);
|
mFeedID.setText(null);
|
||||||
|
mDelay.setValue(0);
|
||||||
mEnabled.setSelected(false);
|
mEnabled.setSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,6 +254,7 @@ public class BroadcastifyConfigurationEditor extends BroadcastConfigurationEdito
|
|||||||
config.setMountPoint(mMountPoint.getText());
|
config.setMountPoint(mMountPoint.getText());
|
||||||
config.setPassword(mPassword.getText());
|
config.setPassword(mPassword.getText());
|
||||||
config.setFeedID(getFeedID());
|
config.setFeedID(getFeedID());
|
||||||
|
config.setDelay(mDelay.getValue() * ONE_MINUTE_MS);
|
||||||
config.setEnabled(mEnabled.isSelected());
|
config.setEnabled(mEnabled.isSelected());
|
||||||
|
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ import audio.AudioPacket;
|
|||||||
import audio.broadcast.AudioBroadcaster;
|
import audio.broadcast.AudioBroadcaster;
|
||||||
import audio.broadcast.BroadcastState;
|
import audio.broadcast.BroadcastState;
|
||||||
import audio.metadata.AudioMetadata;
|
import audio.metadata.AudioMetadata;
|
||||||
|
import audio.metadata.Metadata;
|
||||||
|
import audio.metadata.MetadataType;
|
||||||
import controller.ThreadPoolManager;
|
import controller.ThreadPoolManager;
|
||||||
import org.asynchttpclient.AsyncHandler;
|
import org.asynchttpclient.AsyncHandler;
|
||||||
import org.asynchttpclient.BoundRequestBuilder;
|
import org.asynchttpclient.BoundRequestBuilder;
|
||||||
import org.asynchttpclient.DefaultAsyncHttpClient;
|
import org.asynchttpclient.DefaultAsyncHttpClient;
|
||||||
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
|
|
||||||
import org.asynchttpclient.HttpResponseBodyPart;
|
import org.asynchttpclient.HttpResponseBodyPart;
|
||||||
import org.asynchttpclient.HttpResponseHeaders;
|
import org.asynchttpclient.HttpResponseHeaders;
|
||||||
import org.asynchttpclient.HttpResponseStatus;
|
import org.asynchttpclient.HttpResponseStatus;
|
||||||
@@ -41,6 +42,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import properties.SystemProperties;
|
import properties.SystemProperties;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -51,6 +53,7 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger( IcecastHTTPAudioBroadcaster.class );
|
private final static Logger mLog = LoggerFactory.getLogger( IcecastHTTPAudioBroadcaster.class );
|
||||||
|
|
||||||
|
private static final String UTF8 = "UTF-8";
|
||||||
private static final String HTTP_100_CONTINUE = "100-continue";
|
private static final String HTTP_100_CONTINUE = "100-continue";
|
||||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 15000; //15 seconds
|
private static final long RECONNECT_INTERVAL_MILLISECONDS = 15000; //15 seconds
|
||||||
private long mLastConnectionAttempt = 0;
|
private long mLastConnectionAttempt = 0;
|
||||||
@@ -59,6 +62,7 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
private List<AudioPacket> mPacketsToBroadcast = new ArrayList<>();
|
private List<AudioPacket> mPacketsToBroadcast = new ArrayList<>();
|
||||||
private ConvertedAudioStreamSubscription mSubscription;
|
private ConvertedAudioStreamSubscription mSubscription;
|
||||||
private AtomicBoolean mConnecting = new AtomicBoolean();
|
private AtomicBoolean mConnecting = new AtomicBoolean();
|
||||||
|
private boolean mFirstMetadataUpdateSuppressed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Icecast 2 (v2.4.x or newer) compatible broadcaster using HTTP 1.1 protocol
|
* Creates an Icecast 2 (v2.4.x or newer) compatible broadcaster using HTTP 1.1 protocol
|
||||||
@@ -89,7 +93,95 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
@Override
|
@Override
|
||||||
protected void broadcastMetadata(AudioMetadata metadata)
|
protected void broadcastMetadata(AudioMetadata metadata)
|
||||||
{
|
{
|
||||||
mLog.debug("Request to send metadata to Icecast HTTP server - needs code!");
|
if(connected() && mFirstMetadataUpdateSuppressed)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if(metadata != null)
|
||||||
|
{
|
||||||
|
Metadata to = metadata.getMetadata(MetadataType.TO);
|
||||||
|
|
||||||
|
sb.append("TO:");
|
||||||
|
|
||||||
|
if(to != null)
|
||||||
|
{
|
||||||
|
if(to.hasAlias())
|
||||||
|
{
|
||||||
|
sb.append(to.getAlias().getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(to.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata from = metadata.getMetadata(MetadataType.FROM);
|
||||||
|
|
||||||
|
sb.append(" FROM:");
|
||||||
|
|
||||||
|
if(from != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(from.hasAlias())
|
||||||
|
{
|
||||||
|
sb.append(from.getAlias().getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(from.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("UNKNOWN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append("Scanning ....");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(mDefaultAsyncHttpClient == null)
|
||||||
|
{
|
||||||
|
mDefaultAsyncHttpClient = new DefaultAsyncHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
String songEncoded = URLEncoder.encode(sb.toString(), UTF8);
|
||||||
|
|
||||||
|
StringBuilder query = new StringBuilder();
|
||||||
|
query.append("/admin/metadata?mode=updinfo");
|
||||||
|
query.append("&mount=").append(getConfiguration().getMountPoint());
|
||||||
|
query.append("&charset=UTF%2d8");
|
||||||
|
query.append("&song=").append(songEncoded);
|
||||||
|
|
||||||
|
Uri uri = new Uri(Uri.HTTP, null, getConfiguration().getHost(), getConfiguration().getPort(),
|
||||||
|
query.toString(), null);
|
||||||
|
|
||||||
|
BoundRequestBuilder builder = mDefaultAsyncHttpClient.prepareGet(uri.toUrl());
|
||||||
|
|
||||||
|
//Use Basic (base64) authentication
|
||||||
|
Realm realm = new Realm.Builder(getConfiguration().getUserName(), getConfiguration().getPassword())
|
||||||
|
.setScheme(Realm.AuthScheme.BASIC).setUsePreemptiveAuth(true).build();
|
||||||
|
builder.setRealm(realm);
|
||||||
|
builder.addHeader(IcecastHeader.USER_AGENT.getValue(), SystemProperties.getInstance().getApplicationName());
|
||||||
|
|
||||||
|
mDefaultAsyncHttpClient.executeRequest(builder.build());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
mLog.debug("Error while updating metadata", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(connected())
|
||||||
|
{
|
||||||
|
mFirstMetadataUpdateSuppressed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,58 +253,53 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
Uri uri = new Uri(Uri.HTTP, null, getConfiguration().getHost(), getConfiguration().getPort(),
|
Uri uri = new Uri(Uri.HTTP, null, getConfiguration().getHost(), getConfiguration().getPort(),
|
||||||
getConfiguration().getMountPoint(), null);
|
getConfiguration().getMountPoint(), null);
|
||||||
|
|
||||||
mLog.debug("URL:" + uri.toUrl());
|
BoundRequestBuilder requestBuilder = mDefaultAsyncHttpClient.preparePut(uri.toUrl());
|
||||||
|
|
||||||
BoundRequestBuilder builder = mDefaultAsyncHttpClient.preparePut(uri.toUrl());
|
|
||||||
|
|
||||||
mLog.debug("Setting security realm");
|
|
||||||
//Use Basic (base64) authentication
|
//Use Basic (base64) authentication
|
||||||
Realm realm = new Realm.Builder(getConfiguration().getUserName(), getConfiguration().getPassword())
|
Realm realm = new Realm.Builder(getConfiguration().getUserName(), getConfiguration().getPassword())
|
||||||
.setScheme(Realm.AuthScheme.BASIC).setUsePreemptiveAuth(true).build();
|
.setScheme(Realm.AuthScheme.BASIC).setUsePreemptiveAuth(true).build();
|
||||||
builder.setRealm(realm);
|
requestBuilder.setRealm(realm);
|
||||||
builder.setBody(this);
|
requestBuilder.setBody(this);
|
||||||
|
|
||||||
mLog.debug("Adding headers");
|
//We don't want this request to timeout since it will exist while we are streaming
|
||||||
builder.addHeader(IcecastHeader.ACCEPT.getValue(), "*/*");
|
requestBuilder.setRequestTimeout(-1);
|
||||||
builder.addHeader(IcecastHeader.CONTENT_TYPE.getValue(), getConfiguration().getBroadcastFormat().getValue());
|
|
||||||
builder.addHeader(IcecastHeader.PUBLIC.getValue(), getConfiguration().isPublic() ? "1" : "0");
|
requestBuilder.addHeader(IcecastHeader.ACCEPT.getValue(), "*/*");
|
||||||
|
requestBuilder.addHeader(IcecastHeader.CONTENT_TYPE.getValue(), getConfiguration().getBroadcastFormat().getValue());
|
||||||
|
requestBuilder.addHeader(IcecastHeader.PUBLIC.getValue(), getConfiguration().isPublic() ? "1" : "0");
|
||||||
|
|
||||||
if(getConfiguration().hasName())
|
if(getConfiguration().hasName())
|
||||||
{
|
{
|
||||||
builder.addHeader(IcecastHeader.NAME.getValue(), getConfiguration().getName());
|
requestBuilder.addHeader(IcecastHeader.NAME.getValue(), getConfiguration().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConfiguration().hasDescription())
|
if(getConfiguration().hasDescription())
|
||||||
{
|
{
|
||||||
builder.addHeader(IcecastHeader.DESCRIPTION.getValue(), getConfiguration().getDescription());
|
requestBuilder.addHeader(IcecastHeader.DESCRIPTION.getValue(), getConfiguration().getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConfiguration().hasURL())
|
if(getConfiguration().hasURL())
|
||||||
{
|
{
|
||||||
builder.addHeader(IcecastHeader.URL.getValue(), getConfiguration().getURL());
|
requestBuilder.addHeader(IcecastHeader.URL.getValue(), getConfiguration().getURL());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConfiguration().hasGenre())
|
if(getConfiguration().hasGenre())
|
||||||
{
|
{
|
||||||
builder.addHeader(IcecastHeader.GENRE.getValue(), getConfiguration().getGenre());
|
requestBuilder.addHeader(IcecastHeader.GENRE.getValue(), getConfiguration().getGenre());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(getConfiguration().hasBitRate())
|
if(getConfiguration().hasBitRate())
|
||||||
{
|
{
|
||||||
builder.addHeader(IcecastHeader.BITRATE.getValue(), String.valueOf(getConfiguration().getBitRate()));
|
requestBuilder.addHeader(IcecastHeader.BITRATE.getValue(), String.valueOf(getConfiguration().getBitRate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.addHeader(IcecastHeader.USER_AGENT.getValue(),
|
requestBuilder.addHeader(IcecastHeader.USER_AGENT.getValue(),
|
||||||
SystemProperties.getInstance().getApplicationName());
|
SystemProperties.getInstance().getApplicationName());
|
||||||
|
|
||||||
builder.addHeader(IcecastHeader.EXPECT.getValue(), HTTP_100_CONTINUE);
|
requestBuilder.addHeader(IcecastHeader.EXPECT.getValue(), HTTP_100_CONTINUE);
|
||||||
|
|
||||||
mLog.debug("executing connection with http client");
|
ListenableFuture<Response> future = requestBuilder.execute(new AsyncHttpConnectionResponseHandler());
|
||||||
|
|
||||||
ListenableFuture<Response> future = builder.execute(new AsyncHttpConnectionResponseHandler());
|
|
||||||
|
|
||||||
mLog.debug("Create connection was submitted asynchronously");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -306,7 +393,6 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
@Override
|
@Override
|
||||||
public State onHeadersReceived(HttpResponseHeaders httpResponseHeaders) throws Exception
|
public State onHeadersReceived(HttpResponseHeaders httpResponseHeaders) throws Exception
|
||||||
{
|
{
|
||||||
mLog.debug("Got response headers!");
|
|
||||||
return State.CONTINUE;
|
return State.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,8 +431,6 @@ public class IcecastHTTPAudioBroadcaster extends AudioBroadcaster implements Pub
|
|||||||
public void request(long requestedBufferCount)
|
public void request(long requestedBufferCount)
|
||||||
{
|
{
|
||||||
mDemand.getAndAdd(requestedBufferCount);
|
mDemand.getAndAdd(requestedBufferCount);
|
||||||
|
|
||||||
mLog.debug("Subscriber request:" + requestedBufferCount + " outstanding demand: " + mDemand.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import settings.SettingsManager;
|
import settings.SettingsManager;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@@ -38,15 +40,22 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger( IcecastHTTPConfigurationEditor.class );
|
private final static Logger mLog = LoggerFactory.getLogger( IcecastHTTPConfigurationEditor.class );
|
||||||
|
|
||||||
|
private static final int ONE_MINUTE_MS = 60000;
|
||||||
|
|
||||||
private JTextField mName;
|
private JTextField mName;
|
||||||
private JTextField mServer;
|
private JTextField mServer;
|
||||||
private JTextField mPort;
|
private JTextField mPort;
|
||||||
private JTextField mMountPoint;
|
private JTextField mMountPoint;
|
||||||
private JTextField mUsername;
|
private JTextField mUsername;
|
||||||
private JTextField mPassword;
|
private JTextField mPassword;
|
||||||
|
private JTextField mDescription;
|
||||||
|
private JTextField mGenre;
|
||||||
|
private JCheckBox mPublic;
|
||||||
|
private JSlider mDelay;
|
||||||
|
private JLabel mDelayValue;
|
||||||
|
private JCheckBox mEnabled;
|
||||||
private JButton mSaveButton;
|
private JButton mSaveButton;
|
||||||
private JButton mResetButton;
|
private JButton mResetButton;
|
||||||
private JCheckBox mEnabled;
|
|
||||||
|
|
||||||
public IcecastHTTPConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
public IcecastHTTPConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
||||||
SettingsManager settingsManager)
|
SettingsManager settingsManager)
|
||||||
@@ -57,7 +66,8 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]", "[][][][][][][][][][grow,fill]" ) );
|
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]",
|
||||||
|
"[][][][][][][][][][][][][][][grow,fill]" ) );
|
||||||
setPreferredSize(new Dimension(150,400));
|
setPreferredSize(new Dimension(150,400));
|
||||||
|
|
||||||
JLabel channelLabel = new JLabel("Icecast 2 (v2.4+) Stream");
|
JLabel channelLabel = new JLabel("Icecast 2 (v2.4+) Stream");
|
||||||
@@ -103,7 +113,53 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mPassword.setToolTipText("Password for the stream");
|
mPassword.setToolTipText("Password for the stream");
|
||||||
add(mPassword);
|
add(mPassword);
|
||||||
|
|
||||||
mEnabled = new JCheckBox("Enabled");
|
add(new JLabel("Description:"));
|
||||||
|
mDescription = new JTextField();
|
||||||
|
mDescription.getDocument().addDocumentListener(this);
|
||||||
|
mDescription.setToolTipText("Description of the stream contents");
|
||||||
|
add(mDescription);
|
||||||
|
|
||||||
|
add(new JLabel("Genre:"));
|
||||||
|
mGenre = new JTextField();
|
||||||
|
mGenre.getDocument().addDocumentListener(this);
|
||||||
|
mGenre.setToolTipText("Genre (e.g. public safety)");
|
||||||
|
add(mGenre);
|
||||||
|
|
||||||
|
add(new JLabel("Public:"));
|
||||||
|
mPublic = new JCheckBox();
|
||||||
|
mPublic.addActionListener(new ActionListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mPublic.setToolTipText("Designate stream as public (checked) or private");
|
||||||
|
add(mPublic);
|
||||||
|
|
||||||
|
add(new JLabel());
|
||||||
|
mDelayValue = new JLabel("0 Minutes");
|
||||||
|
add(mDelayValue);
|
||||||
|
|
||||||
|
add(new JLabel("Delay:"));
|
||||||
|
mDelay = new JSlider(0,60,0);
|
||||||
|
mDelay.setMajorTickSpacing(10);
|
||||||
|
mDelay.setMinorTickSpacing(5);
|
||||||
|
mDelay.addChangeListener(new ChangeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e)
|
||||||
|
{
|
||||||
|
mDelayValue.setText(mDelay.getValue() + " Minutes");
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mDelay.setToolTipText("Audio broadcast delay in minutes");
|
||||||
|
add(mDelay);
|
||||||
|
|
||||||
|
add(new JLabel("Enabled:"));
|
||||||
|
mEnabled = new JCheckBox();
|
||||||
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
||||||
mEnabled.addActionListener(new ActionListener()
|
mEnabled.addActionListener(new ActionListener()
|
||||||
{
|
{
|
||||||
@@ -113,7 +169,7 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(mEnabled, "span");
|
add(mEnabled);
|
||||||
|
|
||||||
mSaveButton = new JButton("Save");
|
mSaveButton = new JButton("Save");
|
||||||
mSaveButton.setEnabled(false);
|
mSaveButton.setEnabled(false);
|
||||||
@@ -167,6 +223,10 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mMountPoint.setText(config.getMountPoint());
|
mMountPoint.setText(config.getMountPoint());
|
||||||
mUsername.setText(config.getUserName());
|
mUsername.setText(config.getUserName());
|
||||||
mPassword.setText(config.getPassword());
|
mPassword.setText(config.getPassword());
|
||||||
|
mDescription.setText(config.getDescription());
|
||||||
|
mGenre.setText(config.getGenre());
|
||||||
|
mPublic.setSelected(config.isPublic());
|
||||||
|
mDelay.setValue((int)(config.getDelay() / ONE_MINUTE_MS));
|
||||||
mEnabled.setSelected(config.isEnabled());
|
mEnabled.setSelected(config.isEnabled());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -177,6 +237,10 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mMountPoint.setText(null);
|
mMountPoint.setText(null);
|
||||||
mUsername.setText(null);
|
mUsername.setText(null);
|
||||||
mPassword.setText(null);
|
mPassword.setText(null);
|
||||||
|
mDescription.setText(null);
|
||||||
|
mGenre.setText(null);
|
||||||
|
mPublic.setSelected(true);
|
||||||
|
mDelay.setValue(0);
|
||||||
mEnabled.setSelected(false);
|
mEnabled.setSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +260,10 @@ public class IcecastHTTPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
config.setMountPoint(mMountPoint.getText());
|
config.setMountPoint(mMountPoint.getText());
|
||||||
config.setUserName(mUsername.getText());
|
config.setUserName(mUsername.getText());
|
||||||
config.setPassword(mPassword.getText());
|
config.setPassword(mPassword.getText());
|
||||||
|
config.setDescription(mDescription.getText());
|
||||||
|
config.setGenre(mGenre.getText());
|
||||||
|
config.setPublic(mPublic.isSelected());
|
||||||
|
config.setDelay(mDelay.getValue() * ONE_MINUTE_MS);
|
||||||
config.setEnabled(mEnabled.isSelected());
|
config.setEnabled(mEnabled.isSelected());
|
||||||
|
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class IcecastTCPConfiguration extends BroadcastConfiguration
|
|||||||
private String mDescription;
|
private String mDescription;
|
||||||
private String mGenre;
|
private String mGenre;
|
||||||
private boolean mPublic;
|
private boolean mPublic;
|
||||||
private int mBitRate;
|
private int mBitRate = 16;
|
||||||
private int mChannels = 1;
|
private int mChannels = 1;
|
||||||
private int mSampleRate = 8000;
|
private int mSampleRate = 8000;
|
||||||
private String mURL;
|
private String mURL;
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import settings.SettingsManager;
|
import settings.SettingsManager;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@@ -40,14 +42,21 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger( IcecastTCPConfigurationEditor.class );
|
private final static Logger mLog = LoggerFactory.getLogger( IcecastTCPConfigurationEditor.class );
|
||||||
|
|
||||||
|
private static final int ONE_MINUTE_MS = 60000;
|
||||||
|
|
||||||
private JTextField mName;
|
private JTextField mName;
|
||||||
private JTextField mServer;
|
private JTextField mServer;
|
||||||
private JTextField mPort;
|
private JTextField mPort;
|
||||||
private JTextField mMountPoint;
|
private JTextField mMountPoint;
|
||||||
private JTextField mPassword;
|
private JTextField mPassword;
|
||||||
|
private JTextField mDescription;
|
||||||
|
private JTextField mGenre;
|
||||||
|
private JCheckBox mPublic;
|
||||||
|
private JSlider mDelay;
|
||||||
|
private JLabel mDelayValue;
|
||||||
|
private JCheckBox mEnabled;
|
||||||
private JButton mSaveButton;
|
private JButton mSaveButton;
|
||||||
private JButton mResetButton;
|
private JButton mResetButton;
|
||||||
private JCheckBox mEnabled;
|
|
||||||
|
|
||||||
public IcecastTCPConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
public IcecastTCPConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel,
|
||||||
SettingsManager settingsManager)
|
SettingsManager settingsManager)
|
||||||
@@ -58,7 +67,8 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]", "[][][][][][][][][][grow,fill]" ) );
|
setLayout( new MigLayout( "fill,wrap 2", "[align right][grow,fill]",
|
||||||
|
"[][][][][][][][][][][][][][grow,fill]" ) );
|
||||||
setPreferredSize(new Dimension(150,400));
|
setPreferredSize(new Dimension(150,400));
|
||||||
|
|
||||||
JLabel channelLabel = new JLabel("Icecast (v2.3) Stream");
|
JLabel channelLabel = new JLabel("Icecast (v2.3) Stream");
|
||||||
@@ -98,7 +108,53 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mPassword.setToolTipText("Password for the stream");
|
mPassword.setToolTipText("Password for the stream");
|
||||||
add(mPassword);
|
add(mPassword);
|
||||||
|
|
||||||
mEnabled = new JCheckBox("Enabled");
|
add(new JLabel("Description:"));
|
||||||
|
mDescription = new JTextField();
|
||||||
|
mDescription.getDocument().addDocumentListener(this);
|
||||||
|
mDescription.setToolTipText("Description of the stream contents");
|
||||||
|
add(mDescription);
|
||||||
|
|
||||||
|
add(new JLabel("Genre:"));
|
||||||
|
mGenre = new JTextField();
|
||||||
|
mGenre.getDocument().addDocumentListener(this);
|
||||||
|
mGenre.setToolTipText("Genre (e.g. public safety)");
|
||||||
|
add(mGenre);
|
||||||
|
|
||||||
|
add(new JLabel("Public:"));
|
||||||
|
mPublic = new JCheckBox();
|
||||||
|
mPublic.addActionListener(new ActionListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mPublic.setToolTipText("Designate stream as public (checked) or private");
|
||||||
|
add(mPublic);
|
||||||
|
|
||||||
|
add(new JLabel());
|
||||||
|
mDelayValue = new JLabel("0 Minutes");
|
||||||
|
add(mDelayValue);
|
||||||
|
|
||||||
|
add(new JLabel("Delay:"));
|
||||||
|
mDelay = new JSlider(0,60,0);
|
||||||
|
mDelay.setMajorTickSpacing(10);
|
||||||
|
mDelay.setMinorTickSpacing(5);
|
||||||
|
mDelay.addChangeListener(new ChangeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e)
|
||||||
|
{
|
||||||
|
mDelayValue.setText(mDelay.getValue() + " Minutes");
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mDelay.setToolTipText("Audio broadcast delay in minutes");
|
||||||
|
add(mDelay);
|
||||||
|
|
||||||
|
add(new JLabel("Enabled:")); //Empty
|
||||||
|
mEnabled = new JCheckBox();
|
||||||
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
mEnabled.setToolTipText("Enable (checked) or disable this stream");
|
||||||
mEnabled.addActionListener(new ActionListener()
|
mEnabled.addActionListener(new ActionListener()
|
||||||
{
|
{
|
||||||
@@ -108,7 +164,7 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(mEnabled, "span");
|
add(mEnabled);
|
||||||
|
|
||||||
mSaveButton = new JButton("Save");
|
mSaveButton = new JButton("Save");
|
||||||
mSaveButton.setEnabled(false);
|
mSaveButton.setEnabled(false);
|
||||||
@@ -161,6 +217,10 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mPort.setText(config.getPort() != 0 ? String.valueOf(config.getPort()) : null);
|
mPort.setText(config.getPort() != 0 ? String.valueOf(config.getPort()) : null);
|
||||||
mMountPoint.setText(config.getMountPoint());
|
mMountPoint.setText(config.getMountPoint());
|
||||||
mPassword.setText(config.getPassword());
|
mPassword.setText(config.getPassword());
|
||||||
|
mDescription.setText(config.getDescription());
|
||||||
|
mGenre.setText(config.getGenre());
|
||||||
|
mPublic.setSelected(config.isPublic());
|
||||||
|
mDelay.setValue((int)(config.getDelay() / ONE_MINUTE_MS));
|
||||||
mEnabled.setSelected(config.isEnabled());
|
mEnabled.setSelected(config.isEnabled());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -170,6 +230,10 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
mPort.setText(null);
|
mPort.setText(null);
|
||||||
mMountPoint.setText(null);
|
mMountPoint.setText(null);
|
||||||
mPassword.setText(null);
|
mPassword.setText(null);
|
||||||
|
mDescription.setText(null);
|
||||||
|
mGenre.setText(null);
|
||||||
|
mPublic.setSelected(true);
|
||||||
|
mDelay.setValue(0);
|
||||||
mEnabled.setSelected(false);
|
mEnabled.setSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +252,10 @@ public class IcecastTCPConfigurationEditor extends BroadcastConfigurationEditor
|
|||||||
config.setPort(getPort());
|
config.setPort(getPort());
|
||||||
config.setMountPoint(mMountPoint.getText());
|
config.setMountPoint(mMountPoint.getText());
|
||||||
config.setPassword(mPassword.getText());
|
config.setPassword(mPassword.getText());
|
||||||
|
config.setDescription(mDescription.getText());
|
||||||
|
config.setGenre(mGenre.getText());
|
||||||
|
config.setPublic(mPublic.isSelected());
|
||||||
|
config.setDelay(mDelay.getValue() * ONE_MINUTE_MS);
|
||||||
config.setEnabled(mEnabled.isSelected());
|
config.setEnabled(mEnabled.isSelected());
|
||||||
|
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user