Remove class name from log messages.
[sonitus.git] / src / main / java / net / pterodactylus / sonitus / data / sink / Icecast2Sink.java
index 30801c6..0b55049 100644 (file)
@@ -24,15 +24,22 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.Socket;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.pterodactylus.sonitus.data.ConnectException;
 import net.pterodactylus.sonitus.data.Connection;
-import net.pterodactylus.sonitus.data.Format;
+import net.pterodactylus.sonitus.data.Metadata;
 import net.pterodactylus.sonitus.data.Sink;
 import net.pterodactylus.sonitus.data.Source;
 import net.pterodactylus.sonitus.io.InputStreamDrainer;
 
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
 import com.google.common.io.BaseEncoding;
 import com.google.common.io.Closeables;
 
@@ -71,6 +78,9 @@ public class Icecast2Sink implements Sink {
        /** Whether to publish the server. */
        private final boolean publishServer;
 
+       /** The connected source. */
+       private Source source;
+
        /**
         * Creates a new Icecast2 sink.
         *
@@ -111,16 +121,17 @@ public class Icecast2Sink implements Sink {
        public void connect(Source source) throws ConnectException {
                checkNotNull(source, "source must not be null");
 
+               this.source = source;
                try {
-                       logger.info(String.format("Icecast2Sink: Connecting to %s:%d...", server, port));
+                       logger.info(String.format("Connecting to %s:%d...", server, port));
                        final Socket socket = new Socket(server, port);
-                       logger.info("Icecast2Sink: Connected.");
+                       logger.info("Connected.");
                        final OutputStream socketOutputStream = socket.getOutputStream();
                        final InputStream socketInputStream = socket.getInputStream();
 
                        sendLine(socketOutputStream, String.format("SOURCE /%s ICE/1.0", mountPoint));
                        sendLine(socketOutputStream, String.format("Authorization: Basic %s", generatePassword(password)));
-                       sendLine(socketOutputStream, String.format("Content-Type: %s", getContentType(source.format())));
+                       sendLine(socketOutputStream, String.format("Content-Type: %s", getContentType(source.metadata())));
                        sendLine(socketOutputStream, String.format("ICE-Name: %s", serverName));
                        sendLine(socketOutputStream, String.format("ICE-Description: %s", serverDescription));
                        sendLine(socketOutputStream, String.format("ICE-Genre: %s", genre));
@@ -149,14 +160,57 @@ public class Icecast2Sink implements Sink {
                                @Override
                                protected void finish() throws IOException {
                                        Closeables.close(socketOutputStream, true);
-                                       Closeables.close(socket, true);
+                                       if (socket != null) {
+                                               socket.close();
+                                       }
                                }
                        }).start();
+
+                       metadataUpdated();
                } catch (IOException ioe1) {
                        throw new ConnectException(ioe1);
                }
        }
 
+       @Override
+       public void metadataUpdated() {
+               Metadata metadata = source.metadata();
+               String metadataString = String.format("%s (%s)", Joiner.on(" - ").skipNulls().join(FluentIterable.from(Arrays.asList(metadata.artist(), metadata.name())).transform(new Function<Optional<String>, Object>() {
+
+                       @Override
+                       public Object apply(Optional<String> input) {
+                               return input.orNull();
+                       }
+               })), "Sonitus");
+               logger.info(String.format("Updating metadata to %s", metadataString));
+
+               Socket socket = null;
+               OutputStream socketOutputStream = null;
+               try {
+                       socket = new Socket(server, port);
+                       socketOutputStream = socket.getOutputStream();
+
+                       sendLine(socketOutputStream, String.format("GET /admin/metadata?pass=%s&mode=updinfo&mount=/%s&song=%s HTTP/1.0", password, mountPoint, URLEncoder.encode(metadataString, "UTF-8")));
+                       sendLine(socketOutputStream, String.format("Authorization: Basic %s", generatePassword(password)));
+                       sendLine(socketOutputStream, String.format("User-Agent: Mozilla/Sonitus"));
+                       sendLine(socketOutputStream, "");
+                       socketOutputStream.flush();
+
+                       new InputStreamDrainer(socket.getInputStream()).run();
+               } catch (IOException ioe1) {
+                       logger.log(Level.WARNING, "Could not update metadata!", ioe1);
+               } finally {
+                       try {
+                               Closeables.close(socketOutputStream, true);
+                               if (socket != null) {
+                                       socket.close();
+                               }
+                       } catch (IOException ioe1) {
+                               /* ignore. */
+                       }
+               }
+       }
+
        //
        // PRIVATE METHODS
        //
@@ -191,15 +245,15 @@ public class Icecast2Sink implements Sink {
        }
 
        /**
-        * Returns a MIME type for the given format. Currently only Vorbis, MP3, and
+        * Returns a MIME type for the given metadata. Currently only Vorbis, MP3, and
         * PCM formats are recognized.
         *
-        * @param format
-        *              The format to get a MIME type for
-        * @return The MIME type of the format
+        * @param metadata
+        *              The metadata to get a MIME type for
+        * @return The MIME type of the metadata
         */
-       private static String getContentType(Format format) {
-               String encoding = format.encoding();
+       private static String getContentType(Metadata metadata) {
+               String encoding = metadata.encoding();
                if ("Vorbis".equalsIgnoreCase(encoding)) {
                        return "audio/ogg";
                }