Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
[audio] Refactored use of filename, filename extension and separator (#…
Browse files Browse the repository at this point in the history
…3837)

* Refactored use of filename, filename extension and separator

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
  • Loading branch information
cweitkamp authored and maggu2810 committed Jul 24, 2017
1 parent af2344e commit bea7bd7
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 48 deletions.
Expand Up @@ -25,6 +25,7 @@ Import-Package: javax.servlet,
org.osgi.framework,
org.osgi.service.http,
org.slf4j
Export-Package: org.eclipse.smarthome.core.audio
Export-Package: org.eclipse.smarthome.core.audio,
org.eclipse.smarthome.core.audio.utils
Service-Component: OSGI-INF/*.xml
Bundle-ActivationPolicy: lazy
Expand Up @@ -14,19 +14,22 @@
import java.io.InputStream;

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.core.audio.utils.AudioStreamUtils;

/**
* This is an AudioStream from an audio file
*
* @author Karel Goderis - Initial contribution and API
* @author Kai Kreuzer - Refactored to take a file as input
* @author Christoph Weitkamp - Refactored use of filename extension
*
*/
public class FileAudioStream extends FixedLengthAudioStream {

public static String WAV_EXTENSION = ".wav";
public static String MP3_EXTENSION = ".mp3";
public static String OGG_EXTENSION = ".ogg";
public static String AAC_EXTENSION = ".aac";
public static final String WAV_EXTENSION = "wav";
public static final String MP3_EXTENSION = "mp3";
public static final String OGG_EXTENSION = "ogg";
public static final String AAC_EXTENSION = "aac";

private File file;
private AudioFormat audioFormat;
Expand All @@ -45,16 +48,20 @@ public FileAudioStream(File file, AudioFormat format) throws AudioException {
}

private static AudioFormat getAudioFormat(File file) throws AudioException {
if (file.getName().toLowerCase().endsWith(WAV_EXTENSION)) {
return new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, 705600, 44100L);
} else if (file.getName().toLowerCase().endsWith(MP3_EXTENSION)) {
return AudioFormat.MP3;
} else if (file.getName().toLowerCase().endsWith(OGG_EXTENSION)) {
return AudioFormat.OGG;
} else if (file.getName().toLowerCase().endsWith(AAC_EXTENSION)) {
return AudioFormat.AAC;
} else {
throw new AudioException("Unsupported file extension!");
final String filename = file.getName().toLowerCase();
final String extension = AudioStreamUtils.getExtension(filename);
switch (extension) {
case WAV_EXTENSION:
return new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, 705600,
44100L);
case MP3_EXTENSION:
return AudioFormat.MP3;
case OGG_EXTENSION:
return AudioFormat.OGG;
case AAC_EXTENSION:
return AudioFormat.AAC;
default:
throw new AudioException("Unsupported file extension!");
}
}

Expand Down
Expand Up @@ -18,6 +18,7 @@
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.core.audio.utils.AudioStreamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -27,15 +28,19 @@
*
* @author Karel Goderis - Initial contribution and API
* @author Kai Kreuzer - Refactored to not require a source
* @author Christoph Weitkamp - Refactored use of filename extension
*
*/
public class URLAudioStream extends org.eclipse.smarthome.core.audio.AudioStream {
public class URLAudioStream extends AudioStream {

private static final Pattern plsStreamPattern = Pattern.compile("^File[0-9]=(.+)$");
private static final Pattern PLS_STREAM_PATTERN = Pattern.compile("^File[0-9]=(.+)$");

public static final String M3U_EXTENSION = "m3u";
public static final String PLS_EXTENSION = "pls";

private final Logger logger = LoggerFactory.getLogger(URLAudioStream.class);

private AudioFormat audioFormat;
private final AudioFormat audioFormat;
private final InputStream inputStream;
private String url;

Expand All @@ -51,32 +56,38 @@ public URLAudioStream(String url) throws AudioException {
}

private InputStream createInputStream() throws AudioException {
final String filename = url.toLowerCase();
final String extension = AudioStreamUtils.getExtension(filename);
try {
if (url.toLowerCase().endsWith(".m3u")) {
InputStream is = new URL(url).openStream();
String urls = IOUtils.toString(is);
for (String line : urls.split("\n")) {
if (!line.isEmpty() && !line.startsWith("#")) {
url = line;
break;
switch (extension) {
case M3U_EXTENSION:
try (final InputStream isM3U = new URL(url).openStream()) {
for (final String line : IOUtils.readLines(isM3U)) {
if (!line.isEmpty() && !line.startsWith("#")) {
url = line;
break;
}
}
}
}
} else if (url.toLowerCase().endsWith(".pls")) {
InputStream is = new URL(url).openStream();
String urls = IOUtils.toString(is);
for (String line : urls.split("\n")) {
if (!line.isEmpty() && line.startsWith("File")) {
Matcher matcher = plsStreamPattern.matcher(line);
if (matcher.find()) {
url = matcher.group(1);
break;
break;
case PLS_EXTENSION:
try (final InputStream isPLS = new URL(url).openStream()) {
for (final String line : IOUtils.readLines(isPLS)) {
if (!line.isEmpty() && line.startsWith("File")) {
final Matcher matcher = PLS_STREAM_PATTERN.matcher(line);
if (matcher.find()) {
url = matcher.group(1);
break;
}
}
}
}
}
break;
default:
break;
}
URL streamUrl = new URL(url);
URLConnection connection = streamUrl.openConnection();
InputStream is = null;
if (connection.getContentType().equals("unknown/unknown")) {
// Java does not parse non-standard headers used by SHOUTCast
int port = streamUrl.getPort() > 0 ? streamUrl.getPort() : 80;
Expand All @@ -88,19 +99,18 @@ private InputStream createInputStream() throws AudioException {
String req = "GET / HTTP/1.0\r\nuser-agent: " + user_agent
+ "\r\nIcy-MetaData: 1\r\nConnection: keep-alive\r\n\r\n";
os.write(req.getBytes());
is = shoutCastSocket.getInputStream();
return shoutCastSocket.getInputStream();
} else {
// getInputStream() method is more error-proof than openStream(),
// because openStream() does openConnection().getInputStream(),
// which opens a new connection and does not reuse the old one.
is = connection.getInputStream();
return connection.getInputStream();
}
return is;
} catch (MalformedURLException e) {
logger.error("URL '{}' is not a valid url : '{}'", url, e.getMessage());
logger.error("URL '{}' is not a valid url: {}", url, e.getMessage(), e);
throw new AudioException("URL not valid");
} catch (IOException e) {
logger.error("Cannot set up stream '{}': {}", url, e);
logger.error("Cannot set up stream '{}': {}", url, e.getMessage(), e);
throw new AudioException("IO Error");
}
}
Expand Down
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.audio.utils;

/**
* Some general filename and extension utilities.
*
* @author Christoph Weitkamp - Initial contribution and API
*
*/
public class AudioStreamUtils {

public static final String EXTENSION_SEPARATOR = ".";

/**
* Gets the base name of a filename.
*
* @param filename the filename to query
* @return the base name of the file or an empty string if none exists or {@code null} if the filename is
* {@code null}
*/
public static String getBaseName(String filename) {
if (filename == null) {
return null;
}
final int index = filename.lastIndexOf(EXTENSION_SEPARATOR);
if (index == -1) {
return filename;
} else {
return filename.substring(0, index);
}
}

/**
* Gets the extension of a filename.
*
* @param filename the filename to retrieve the extension of
* @return the extension of the file or an empty string if none exists or {@code null} if the filename is
* {@code null}
*/
public static String getExtension(String filename) {
if (filename == null) {
return null;
}
final int index = filename.lastIndexOf(EXTENSION_SEPARATOR);
if (index == -1) {
return "";
} else {
return filename.substring(index + 1);
}
}

/**
* Checks if the extension of a filename matches the given.
*
* @param filename the filename to check the extension of
* @param extension the extension to check for
* @return {@code true} if the filename has the specified extension
*/
public static boolean isExtension(String filename, String extension) {
if (filename == null) {
return false;
}
if (extension == null || extension.isEmpty()) {
return false;
}
return getExtension(filename).equals(extension);
}

}
Expand Up @@ -15,7 +15,7 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
Expand All @@ -31,11 +31,10 @@
*
* @author Michael Grammling - Initial Contribution
* @author Martin Herbst - UTF-8 replaced by ISO-8859-1 to follow Java standards
*
*/
public class ResourceBundleClassLoader extends ClassLoader {

private static final Charset SUPPORTED_CHARSET = Charset.forName("ISO-8859-1");

private Bundle bundle;
private String path;
private String filePattern;
Expand Down Expand Up @@ -115,7 +114,7 @@ public InputStream getResourceAsStream(String name) {
if (resourceURL != null) {
try (InputStream resourceStream = resourceURL.openStream()) {
if (resourceStream != null) {
try (Reader resourceReader = new InputStreamReader(resourceStream, SUPPORTED_CHARSET)) {
try (Reader resourceReader = new InputStreamReader(resourceStream, StandardCharsets.ISO_8859_1)) {
Properties props = new Properties();
props.load(resourceReader);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Expand Down
Expand Up @@ -14,6 +14,7 @@ Import-Package: com.google.common.collect,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.config.discovery,
org.eclipse.smarthome.core.audio,
org.eclipse.smarthome.core.audio.utils,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.net,
Expand Down
Expand Up @@ -23,6 +23,7 @@
import org.eclipse.smarthome.core.audio.URLAudioStream;
import org.eclipse.smarthome.core.audio.UnsupportedAudioFormatException;
import org.eclipse.smarthome.core.audio.UnsupportedAudioStreamException;
import org.eclipse.smarthome.core.audio.utils.AudioStreamUtils;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.thing.util.ThingHandlerHelper;
Expand Down Expand Up @@ -95,9 +96,11 @@ public void process(AudioStream audioStream)
logger.warn("Sonos speaker '{}' is not initialized - status is {}", handler.getThing().getUID(),
handler.getThing().getStatus());
} else if (AudioFormat.WAV.isCompatible(format)) {
handler.playNotificationSoundURI(new StringType(url + FileAudioStream.WAV_EXTENSION));
handler.playNotificationSoundURI(
new StringType(url + AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.WAV_EXTENSION));
} else if (AudioFormat.MP3.isCompatible(format)) {
handler.playNotificationSoundURI(new StringType(url + FileAudioStream.MP3_EXTENSION));
handler.playNotificationSoundURI(
new StringType(url + AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.MP3_EXTENSION));
} else {
throw new UnsupportedAudioFormatException("Sonos only supports MP3 or WAV.", format);
}
Expand Down

0 comments on commit bea7bd7

Please sign in to comment.