/**
* Copyright (c) 2010-2016 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.openhab.io.multimedia.internal.tts;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.openhab.io.multimedia.tts.TTSService;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is a pure Java TTS service implementation, based on SpeechDispatcher.
*
* @author Gaƫl L'hopital
* @since 1.6.0
*
*/
public class TTSServiceSpeechDispatcher implements TTSService, ManagedService {
private static final Logger logger = LoggerFactory.getLogger(TTSServiceSpeechDispatcher.class);
SpeechDispatcherConnection defaultOutput = null;
/** Map table to store all available speech dispatchers configured by the user */
protected Map<String, SpeechDispatcherConnection> deviceConfigCache = null;
/** RegEx to validate a config <code>'^(.*?)\\.(host|port)$'</code> */
private static final Pattern EXTRACT_CONFIG_PATTERN = Pattern.compile("^(.*?)\\.(host|port)$");
public void activate() {
logger.debug("Activate");
}
public void deactivate() {
logger.debug("Deactivate");
closeAllConnections();
}
private void closeAllConnections() {
for (Entry<String, SpeechDispatcherConnection> deviceConfig : deviceConfigCache.entrySet()) {
SpeechDispatcherConnection connection = deviceConfig.getValue();
connection.closeConnection();
}
}
/**
* {@inheritDoc}
*/
public void say(String text, String voiceName, String outputDevice) {
SpeechDispatcherConnection connection = null;
if (outputDevice != null) {
connection = deviceConfigCache.get(outputDevice);
} else {
connection = defaultOutput;
}
if (connection != null) {
connection.say(text, voiceName);
} else {
logger.error("Output device not configured [{}]", outputDevice);
}
}
public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
if (properties != null) {
Enumeration<String> keys = properties.keys();
if (deviceConfigCache == null) {
deviceConfigCache = new HashMap<String, SpeechDispatcherConnection>();
}
while (keys.hasMoreElements()) {
String key = keys.nextElement();
// the property-key enumeration can contain additional keys that we
// don't want to process here ...
if ("service.pid".equals(key) || "os".equals(key)) {
continue;
}
Matcher matcher = EXTRACT_CONFIG_PATTERN.matcher(key);
if (!matcher.matches()) {
logger.debug(
"Given config key '" + key + "' does not follow the expected pattern '<id>.<host|port>'");
continue;
}
matcher.reset();
matcher.find();
String deviceId = matcher.group(1);
SpeechDispatcherConnection deviceConfig = deviceConfigCache.get(deviceId);
if (deviceConfig == null) {
deviceConfig = new SpeechDispatcherConnection();
deviceConfigCache.put(deviceId, deviceConfig);
defaultOutput = deviceConfig;
}
String configKey = matcher.group(2);
String value = (String) properties.get(key);
if ("host".equals(configKey)) {
deviceConfig.host = value;
} else if ("port".equals(configKey)) {
deviceConfig.port = value;
} else {
throw new ConfigurationException(configKey, "the given configKey '" + configKey + "' is unknown");
}
}
}
}
}