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

[audio] Added getSupportedStreams() and UnsupportedAudioStreamException #3764

Merged
merged 5 commits into from Jun 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -99,6 +99,20 @@ public class AudioManagerTest extends AudioOSGiTest {
}
}

@Test
public void 'audio manager handles UnsupportedAudioStreamException'(){
registerSink()

audioStream = getFileAudioStream(MP3_FILE_PATH)

audioSinkFake.isUnsupportedAudioStreamExceptionExpected = true
try{
audioManager.playFile(audioStream.file.getName(), audioSinkFake.getId())
} catch (UnsupportedAudioStreamException e){
fail("An exception $e was thrown, while trying to process a stream")
}
}

@Test
public void 'audio manager sets the volume of a sink'(){
registerSink()
Expand Down Expand Up @@ -322,12 +336,12 @@ public class AudioManagerTest extends AudioOSGiTest {

Collection<ParameterOption> parameterOptions = audioManager.getParameterOptions(URI.create(AudioManagerImpl.CONFIG_URI), param, Locale.US)

boolean isParameterOptionAdded = parameterOptions.find { parameterOption ->
boolean isParameterOptionAdded = parameterOptions.find { parameterOption ->
if(parameterOption.getValue().equals(id) && parameterOption.getLabel().equals(label)){
return true
}
}

assertThat "$param was not added to the parameter options",
isParameterOptionAdded,
is(equalTo(true))
Expand Down
Expand Up @@ -7,19 +7,42 @@
*/
package org.eclipse.smarthome.core.audio.test.fake

import java.util.Set

import org.eclipse.smarthome.core.audio.AudioFormat
import org.eclipse.smarthome.core.audio.AudioSink
import org.eclipse.smarthome.core.audio.AudioStream
import org.eclipse.smarthome.core.audio.FixedLengthAudioStream
import org.eclipse.smarthome.core.audio.UnsupportedAudioFormatException
import org.eclipse.smarthome.core.audio.UnsupportedAudioStreamException
import org.eclipse.smarthome.core.audio.URLAudioStream
import org.eclipse.smarthome.core.library.types.PercentType

public class AudioSinkFake implements AudioSink{
/**
*
* @author Christoph Weitkamp - Added examples for getSupportedFormats() and getSupportedStreams()
*
*/
public class AudioSinkFake implements AudioSink {

public AudioStream audioStream
public AudioFormat audioFormat
public boolean isStreamProcessed = false
public PercentType volume
public boolean isIOExceptionExpected = false
public boolean isUnsupportedAudioFormatExceptionExpected = false
public boolean isUnsupportedAudioStreamExceptionExpected = false

private static final HashSet<AudioFormat> SUPPORTED_AUDIO_FORMATS = new HashSet<>();
private static final HashSet<Class<? extends AudioStream>> SUPPORTED_AUDIO_STREAMS = new HashSet<>();

static {
SUPPORTED_AUDIO_FORMATS.add(AudioFormat.WAV);
SUPPORTED_AUDIO_FORMATS.add(AudioFormat.MP3);

SUPPORTED_AUDIO_STREAMS.add(URLAudioStream.class);
SUPPORTED_AUDIO_STREAMS.add(FixedLengthAudioStream.class);
}

@Override
public String getId() {
Expand All @@ -32,18 +55,26 @@ public class AudioSinkFake implements AudioSink{
}

@Override
public void process(AudioStream audioStream) throws UnsupportedAudioFormatException {
public void process(AudioStream audioStream) throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
if(isUnsupportedAudioFormatExceptionExpected){
throw new UnsupportedAudioFormatException("Expected audio format exception", null)
}
if(isUnsupportedAudioStreamExceptionExpected){
throw new UnsupportedAudioStreamException("Expected audio stream exception", null)
}
this.audioStream = audioStream
audioFormat = audioStream.getFormat()
isStreamProcessed = true
}

@Override
public Set<AudioFormat> getSupportedFormats() {
return null;
return SUPPORTED_AUDIO_FORMATS;
}

@Override
public Set<Class<? extends AudioStream>> getSupportedStreams() {
return SUPPORTED_AUDIO_STREAMS;
}

@Override
Expand Down
Expand Up @@ -19,6 +19,8 @@
*
* @author Harald Kuhn - Initial API
* @author Kelly Davis - Modified to match discussion in #584
* @author Christoph Weitkamp - Added getSupportedStreams() and UnsupportedAudioStreamException
*
*/
public interface AudioSink {

Expand All @@ -40,15 +42,19 @@ public interface AudioSink {
/**
* Processes the passed {@link AudioStream}
*
* If the passed {@link AudioStream} is not supported by this instance, an {@link UnsupportedAudioStreamException}
* is thrown.
*
* If the passed {@link AudioStream} has a {@link AudioFormat} not supported by this instance,
* an {@link UnsupportedAudioFormatException} is thrown. In case the audioStream is null, this should be interpreted
* as a request to end any currently playing stream.
*
* @param audioStream the audio stream to play or null to keep quiet
*
* @throws UnsupportedAudioFormatException If audioStream format is not supported
* @throws UnsupportedAudioStreamException If audioStream is not supported
*/
void process(AudioStream audioStream) throws UnsupportedAudioFormatException;
void process(AudioStream audioStream) throws UnsupportedAudioFormatException, UnsupportedAudioStreamException;

/**
* Gets a set containing all supported audio formats
Expand All @@ -57,6 +63,13 @@ public interface AudioSink {
*/
public Set<AudioFormat> getSupportedFormats();

/**
* Gets a set containing all supported audio stream formats
*
* @return A Set containing all supported audio stream formats
*/
public Set<Class<? extends AudioStream>> getSupportedStreams();

/**
* Gets the volume
*
Expand Down
@@ -0,0 +1,57 @@
/**
* 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;

/**
* Thrown when a requested {@link AudioStream} is not supported by an {@link AudioSource} or {@link AudioSink}
* implementation
*
* @author Christoph Weitkamp - Initial contribution and API
*
*/
public class UnsupportedAudioStreamException extends AudioException {

private static final long serialVersionUID = 1L;

/**
* Unsupported {@link AudioStream}
*/
private Class<? extends AudioStream> unsupportedAudioStreamClass;

/**
* Constructs a new exception with the specified detail message, unsupported format, and cause.
*
* @param message The message
* @param unsupportedAudioStreamClass The unsupported audio stream class
* @param cause The cause
*/
public UnsupportedAudioStreamException(String message, Class<? extends AudioStream> unsupportedAudioStreamClass,
Throwable cause) {
super(message, cause);
this.unsupportedAudioStreamClass = unsupportedAudioStreamClass;
}

/**
* Constructs a new exception with the specified detail message and unsupported format.
*
* @param message The message
* @param unsupportedAudioStreamClass The unsupported audio stream class
*/
public UnsupportedAudioStreamException(String message, Class<? extends AudioStream> unsupportedAudioStreamClass) {
this(message, unsupportedAudioStreamClass, null);
}

/**
* Gets the unsupported audio stream class.
*
* @return The unsupported audio stream class
*/
public Class<? extends AudioStream> getUnsupportedAudioStreamClass() {
return unsupportedAudioStreamClass;
}
}
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.smarthome.core.audio.FileAudioStream;
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.library.types.PercentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -39,6 +40,8 @@
*
* @author Karel Goderis - Initial contribution and API
* @author Kai Kreuzer - removed unwanted dependencies
* @author Christoph Weitkamp - Added getSupportedStreams() and UnsupportedAudioStreamException
*
*/
public class AudioManagerImpl implements AudioManager, ConfigOptionProvider {

Expand Down Expand Up @@ -88,7 +91,7 @@ public void play(AudioStream audioStream, String sinkId) {
if (sink != null) {
try {
sink.process(audioStream);
} catch (UnsupportedAudioFormatException e) {
} catch (UnsupportedAudioFormatException | UnsupportedAudioStreamException e) {
logger.error("Error playing '{}': {}", audioStream.toString(), e.getMessage());
}
} else {
Expand Down Expand Up @@ -123,7 +126,7 @@ public void stream(String url, String sinkId) throws AudioException {
if (sink != null) {
try {
sink.process(audioStream);
} catch (UnsupportedAudioFormatException e) {
} catch (UnsupportedAudioFormatException | UnsupportedAudioStreamException e) {
logger.error("Error playing '{}': {}", url, e.getMessage());
}
}
Expand Down
Expand Up @@ -16,6 +16,7 @@
import org.eclipse.smarthome.core.audio.AudioSource;
import org.eclipse.smarthome.core.audio.AudioStream;
import org.eclipse.smarthome.core.audio.UnsupportedAudioFormatException;
import org.eclipse.smarthome.core.audio.UnsupportedAudioStreamException;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.ItemUtil;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
Expand Down Expand Up @@ -48,6 +49,7 @@
*
* @author Kai Kreuzer - Initial contribution and API
* @author Yannick Schaus - Send commands to an item to indicate the keyword has been spotted
* @author Christoph Weitkamp - Added getSupportedStreams() and UnsupportedAudioStreamException
*/
public class DialogProcessor implements KSListener, STTListener {

Expand Down Expand Up @@ -187,9 +189,14 @@ protected void say(String text) {
throw new TTSException("Unable to find a suitable voice");
}
AudioStream audioStream = tts.synthesize(text, voice, null);
sink.process(audioStream);
} catch (TTSException | UnsupportedAudioFormatException e) {
logger.error("Error saying '{}'", text);

try {
sink.process(audioStream);
} catch (UnsupportedAudioFormatException | UnsupportedAudioStreamException e) {
logger.error("Error saying '{}': {}", text, e.getMessage());
}
} catch (TTSException e) {
logger.error("Error saying '{}': {}", text, e.getMessage());
}
}

Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.smarthome.core.audio.AudioSource;
import org.eclipse.smarthome.core.audio.AudioStream;
import org.eclipse.smarthome.core.audio.UnsupportedAudioFormatException;
import org.eclipse.smarthome.core.audio.UnsupportedAudioStreamException;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.i18n.LocaleProvider;
import org.eclipse.smarthome.core.voice.KSService;
Expand All @@ -43,6 +44,7 @@
*
* @author Kai Kreuzer - Initial contribution and API
* @author Yannick Schaus - Added ability to provide a item for feedback during listening phases
* @author Christoph Weitkamp - Added getSupportedStreams() and UnsupportedAudioStreamException
*/
public class VoiceManagerImpl implements VoiceManager, ConfigOptionProvider {

Expand Down Expand Up @@ -139,20 +141,24 @@ public void say(String text, String voiceId, String sinkId) {
} else if (voiceId.contains(":")) {
// it is a fully qualified unique id
String[] segments = voiceId.split(":");
tts = ttsServices.get(segments[0]);
voice = getVoice(tts.getAvailableVoices(), segments[1]);
tts = getTTS(segments[0]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change this? This potentially returns you the default tts instead of the one specified in segments[0], so it unnecessarily complicates things here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it for readability and to prevent NPE (in case of segment[0] contains a not suitable value). Have a look at https://github.com/eclipse/smarthome/pull/3764/files#diff-2bdbf6176fb6bd9b1af9a6cb230b6293R472. The getTTS(String) method returns exaclty the same like before (ttsServices.get(id)).

if (tts != null) {
voice = getVoice(tts.getAvailableVoices(), segments[1]);
}
} else {
// voiceId is not fully qualified
tts = getTTS();
voice = getVoice(tts.getAvailableVoices(), voiceId);
if (tts != null) {
voice = getVoice(tts.getAvailableVoices(), voiceId);
}
}
if (tts == null) {
throw new TTSException("No TTS service can be found for voice " + voiceId);
}
if (voice == null) {
throw new TTSException(
"Unable to find a voice for language " + localeProvider.getLocale().getLanguage());
}
if (tts == null) {
throw new TTSException("No TTS service can be found for voice " + voiceId);
}
Set<AudioFormat> audioFormats = tts.getSupportedFormats();
AudioSink sink = null;
if (sinkId == null) {
Expand All @@ -167,7 +173,7 @@ public void say(String text, String voiceId, String sinkId) {

try {
sink.process(audioStream);
} catch (UnsupportedAudioFormatException e) {
} catch (UnsupportedAudioFormatException | UnsupportedAudioStreamException e) {
logger.error("Error saying '{}': {}", text, e.getMessage());
}
} else {
Expand Down
Expand Up @@ -7,6 +7,7 @@ Bundle-Version: 0.9.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ClassPath: .
Import-Package: com.google.common.collect,
org.apache.commons.io,
org.apache.commons.lang,
org.eclipse.smarthome.binding.sonos,
org.eclipse.smarthome.binding.sonos.handler,
Expand Down