added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.voice.picotts-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-voice-picotts" description="Pico Text-to-Speech" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.voice.picotts/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,128 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.voice.picotts.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.openhab.core.audio.AudioException;
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioStream;
import org.openhab.core.audio.FixedLengthAudioStream;
import org.openhab.core.voice.Voice;
/**
* Implementation of {@link AudioStream} for {@link PicoTTSService}
*
* @author Florian Schmidt - Initial Contribution
*/
class PicoTTSAudioStream extends FixedLengthAudioStream {
private final Voice voice;
private final String text;
private final AudioFormat audioFormat;
private final InputStream inputStream;
private long length;
private File file;
public PicoTTSAudioStream(String text, Voice voice, AudioFormat audioFormat) throws AudioException {
this.text = text;
this.voice = voice;
this.audioFormat = audioFormat;
this.inputStream = createInputStream();
}
@Override
public AudioFormat getFormat() {
return audioFormat;
}
private InputStream createInputStream() throws AudioException {
String outputFile = generateOutputFilename();
String[] command = getCommand(outputFile);
try {
Process process = Runtime.getRuntime().exec(command);
process.waitFor();
file = new File(outputFile);
this.length = file.length();
return getFileInputStream(file);
} catch (IOException e) {
throw new AudioException("Error while executing '" + command + "'", e);
} catch (InterruptedException e) {
throw new AudioException("The '" + command + "' has been interrupted", e);
}
}
private InputStream getFileInputStream(File file) throws AudioException {
if (file == null) {
throw new IllegalArgumentException("file must not be null");
}
if (file.exists()) {
try {
return new FileInputStream(file);
} catch (FileNotFoundException e) {
throw new AudioException("Cannot open temporary audio file '" + file.getName() + ".");
}
} else {
throw new AudioException("Temporary file '" + file.getName() + "' not found!");
}
}
/**
* Generates a unique, absolute output filename
*
* @return Unique, absolute output filename
*/
private String generateOutputFilename() throws AudioException {
try {
File tempFile = File.createTempFile(Integer.toString(text.hashCode()), ".wav");
tempFile.deleteOnExit();
return tempFile.getAbsolutePath();
} catch (IOException e) {
throw new AudioException("Unable to create temp file.", e);
}
}
/**
* Gets the command used to generate an audio file {@code outputFile}
*
* @param outputFile The absolute filename of the command's output
* @return The command used to generate the audio file {@code outputFile}
*/
private String[] getCommand(String outputFile) {
return new String[] { "pico2wave", "-l=" + this.voice.getLabel(), "-w=" + outputFile, this.text };
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public long length() {
return length;
}
@Override
public InputStream getClonedStream() throws AudioException {
if (file != null) {
return getFileInputStream(file);
} else {
throw new AudioException("No temporary audio file available.");
}
}
}

View File

@@ -0,0 +1,86 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.voice.picotts.internal;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openhab.core.audio.AudioException;
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioStream;
import org.openhab.core.voice.TTSException;
import org.openhab.core.voice.TTSService;
import org.openhab.core.voice.Voice;
import org.osgi.service.component.annotations.Component;
/**
* @author Florian Schmidt - Initial Contribution
*/
@Component
public class PicoTTSService implements TTSService {
private final Set<Voice> voices = Stream
.of(new PicoTTSVoice("de-DE"), new PicoTTSVoice("en-US"), new PicoTTSVoice("en-GB"),
new PicoTTSVoice("es-ES"), new PicoTTSVoice("fr-FR"), new PicoTTSVoice("it-IT"))
.collect(Collectors.toSet());
private final Set<AudioFormat> audioFormats = Collections.singleton(
new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, 16000L));
@Override
public Set<Voice> getAvailableVoices() {
return this.voices;
}
@Override
public Set<AudioFormat> getSupportedFormats() {
return this.audioFormats;
}
@Override
public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException {
if (text == null || text.isEmpty()) {
throw new TTSException("The passed text can not be null or empty");
}
if (!this.voices.contains(voice)) {
throw new TTSException("The passed voice is unsupported");
}
boolean isAudioFormatSupported = this.audioFormats.stream().anyMatch(audioFormat -> {
return audioFormat.isCompatible(requestedFormat);
});
if (!isAudioFormatSupported) {
throw new TTSException("The passed AudioFormat is unsupported");
}
try {
return new PicoTTSAudioStream(text, voice, requestedFormat);
} catch (AudioException e) {
throw new TTSException(e);
}
}
@Override
public String getId() {
return "picotts";
}
@Override
public String getLabel(Locale locale) {
return "PicoTTS";
}
}

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.voice.picotts.internal;
import java.util.Locale;
import org.openhab.core.voice.Voice;
/**
* Implementation of the Voice interface for PicoTTS
*
* @author Florian Schmidt - Initial Contribution
*/
public class PicoTTSVoice implements Voice {
private final String languageTag;
public PicoTTSVoice(String languageTag) {
this.languageTag = languageTag;
}
@Override
public String getUID() {
return "picotts:" + languageTag.replaceAll("[^a-zA-Z0-9_]", "");
}
@Override
public String getLabel() {
return languageTag;
}
@Override
public Locale getLocale() {
return Locale.forLanguageTag(languageTag);
}
}