- feature: new module 98_Text2Speech.pm added (Tobias Faust)
Google Translator Engine or ESpeak can be used git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@4655 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- SVN
|
||||
- feature: new module 98_Text2Speech.pm added (Tobias Faust)
|
||||
Google Translator Engine or ESpeak can be used
|
||||
- feature: YAMAHA_AVR: define separate on and off status intervals for
|
||||
cyclic status updates
|
||||
- feature: Visualizations (Plots) for SYSMON added
|
||||
|
||||
821
fhem/FHEM/98_Text2Speech.pm
Normal file
821
fhem/FHEM/98_Text2Speech.pm
Normal file
@@ -0,0 +1,821 @@
|
||||
##############################################
|
||||
|
||||
# $Id$
|
||||
|
||||
#
|
||||
|
||||
# 98_Text2Speech.pm
|
||||
|
||||
#
|
||||
|
||||
# written by Tobias Faust 2013-10-23
|
||||
|
||||
# e-mail: tobias dot faust at online dot de
|
||||
|
||||
#
|
||||
|
||||
##############################################
|
||||
|
||||
|
||||
|
||||
##############################################
|
||||
|
||||
# EDITOR=nano
|
||||
|
||||
# visudo
|
||||
|
||||
# ALL ALL = NOPASSWD: /usr/bin/mplayer
|
||||
|
||||
##############################################
|
||||
|
||||
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
|
||||
use warnings;
|
||||
|
||||
use Blocking;
|
||||
|
||||
use IO::File;
|
||||
|
||||
use HttpUtils;
|
||||
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
|
||||
use URI::Escape;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
|
||||
|
||||
sub Text2Speech_OpenDev($);
|
||||
|
||||
sub Text2Speech_CloseDev($);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# SetParamName -> Anzahl Paramter
|
||||
|
||||
my %sets = (
|
||||
|
||||
"tts" => "1",
|
||||
|
||||
"volume" => "1"
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
# path to mplayer
|
||||
|
||||
my $mplayer = 'sudo /usr/bin/mplayer';
|
||||
|
||||
#my $mplayerOpts = '-nolirc -noconsolecontrols -http-header-fields "User-Agent:Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22m"';
|
||||
|
||||
my $mplayerOpts = '-nolirc -noconsolecontrols';
|
||||
|
||||
my $mplayerNoDebug = '-really-quiet';
|
||||
|
||||
my $mplayerAudioOpts = '-ao alsa:device=';
|
||||
|
||||
#my $ttsAddr = 'http://translate.google.com/translate_tts?tl=de&q=';
|
||||
|
||||
my $ttsHost = 'translate.google.com';
|
||||
|
||||
my $ttsPath = '/translate_tts?tl=de&q=';
|
||||
|
||||
|
||||
|
||||
##########################
|
||||
|
||||
sub Text2Speech_Initialize($)
|
||||
|
||||
{
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{WriteFn} = "Text2Speech_Write";
|
||||
|
||||
$hash->{ReadyFn} = "Text2Speech_Ready";
|
||||
|
||||
$hash->{DefFn} = "Text2Speech_Define";
|
||||
|
||||
$hash->{SetFn} = "Text2Speech_Set";
|
||||
|
||||
$hash->{UndefFn} = "Text2Speech_Undefine";
|
||||
|
||||
$hash->{AttrFn} = "Text2Speech_Attr";
|
||||
|
||||
$hash->{AttrList} = "disable:0,1".
|
||||
|
||||
" TTS_Delemiter".
|
||||
|
||||
" TTS_Ressource:Google,ESpeak".
|
||||
|
||||
" TTS_CacheFileDir".
|
||||
|
||||
" TTS_UseMP3Wrap:0,1".
|
||||
|
||||
" TTS_MplayerCall".
|
||||
|
||||
" ".$readingFnAttributes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##########################
|
||||
|
||||
# Define <tts> Text2Speech <alsa-device>
|
||||
|
||||
# Define <tts> Text2Speech host[:port][:SSL] [portpassword]
|
||||
|
||||
##########################
|
||||
|
||||
sub Text2Speech_Define($$)
|
||||
|
||||
{
|
||||
|
||||
my ($hash, $def) = @_;
|
||||
|
||||
my @a = split("[ \t]+", $def);
|
||||
|
||||
|
||||
|
||||
#$a[0]: Name
|
||||
|
||||
#$a[1]: Type/Alias -> Text2Speech
|
||||
|
||||
#$a[2]: definition
|
||||
|
||||
#$a[3]: optional: portpasswd
|
||||
|
||||
if(int(@a) < 3) {
|
||||
|
||||
my $msg = "wrong syntax: define <name> Text2Speech <alsa-device>\n".
|
||||
|
||||
"see at /etc/asound.conf\n".
|
||||
|
||||
"or remote syntax: define <name> Text2Speech host[:port][:SSL] [portpassword]";
|
||||
|
||||
Log3 $hash, 2, $msg;
|
||||
|
||||
return $msg;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
my $dev = $a[2];
|
||||
|
||||
if($dev =~ m/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/ ) {
|
||||
|
||||
# Ein RemoteDevice ist angegeben
|
||||
|
||||
# zb: 192.168.10.24:7272:SSL mypasswd
|
||||
|
||||
|
||||
|
||||
if($dev =~ m/^(.*):SSL$/) {
|
||||
|
||||
$dev = $1;
|
||||
|
||||
$hash->{SSL} = 1;
|
||||
|
||||
}
|
||||
|
||||
if($dev !~ m/^.+:[0-9]+$/) { # host:port
|
||||
|
||||
$dev = "$dev:7072";
|
||||
|
||||
}
|
||||
|
||||
$hash->{Host} = $dev;
|
||||
|
||||
$hash->{portpassword} = $a[3] if(@a == 4);
|
||||
|
||||
|
||||
|
||||
$hash->{MODE} = "REMOTE";
|
||||
|
||||
} else {
|
||||
|
||||
# Ein Alsadevice ist angegeben
|
||||
|
||||
# pruefen, ob Alsa-Device in /etc/asound.conf definiert ist
|
||||
|
||||
$hash->{MODE} = "DIRECT";
|
||||
|
||||
$hash->{ALSADEVICE} = $a[2];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
|
||||
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
|
||||
|
||||
|
||||
$hash->{STATE} = "Initialized";
|
||||
|
||||
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
sub Text2Speech_Undefine($$)
|
||||
|
||||
{
|
||||
|
||||
my ($hash, $arg) = @_;
|
||||
|
||||
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
|
||||
|
||||
Text2Speech_CloseDev($hash);
|
||||
|
||||
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
###################################
|
||||
|
||||
# Angabe des Delemiters: zb.: +af~
|
||||
|
||||
# + -> erzwinge das Trennen, auch wenn Textbaustein < 100Zeichen
|
||||
|
||||
# - -> Trenne nur wenn Textbaustein > 100Zeichen
|
||||
|
||||
# af -> add first -> füge den Delemiter am Satzanfang wieder hinzu
|
||||
|
||||
# al -> add last -> füge den Delemiter am Satzende wieder hinzu
|
||||
|
||||
# an -> add nothing -> Delemiter nicht wieder hinzufügen
|
||||
|
||||
# ~ -> der Delemiter
|
||||
|
||||
###################################
|
||||
|
||||
sub Text2Speech_Attr(@) {
|
||||
|
||||
my @a = @_;
|
||||
|
||||
my $do = 0;
|
||||
|
||||
my $hash = $defs{$a[1]};
|
||||
|
||||
|
||||
|
||||
if($a[0] eq "set" && $a[2] eq "disable") {
|
||||
|
||||
$do = (!defined($a[3]) || $a[3]) ? 1 : 2;
|
||||
|
||||
}
|
||||
|
||||
$do = 2 if($a[0] eq "del" && (!$a[2] || $a[2] eq "disable"));
|
||||
|
||||
return if(!$do);
|
||||
|
||||
|
||||
|
||||
$hash->{STATE} = ($do == 1 ? "disabled" : "Initialized");
|
||||
|
||||
|
||||
|
||||
if($a[2] eq "TTS_Delemiter") {
|
||||
|
||||
my $TTS_Delemiter = $a[3];
|
||||
|
||||
return "wrong delemiter syntax: [+-]a[lfn]. \n".
|
||||
|
||||
" Example 1: +an~\n".
|
||||
|
||||
" Example 2: +al." if($TTS_Delemiter =~ m/^([+-]a[lfn]){0,1}(.){1}$/i);
|
||||
|
||||
return "This Attribute is only available in direct mode" if($hash->{MODE} ne "DIRECT");
|
||||
|
||||
} elsif ($a[2] eq "TTS_Ressource") {
|
||||
|
||||
return "This Attribute is only available in direct mode" if($hash->{MODE} ne "DIRECT");
|
||||
|
||||
} elsif ($a[2] eq "TTS_CacheFileDir") {
|
||||
|
||||
return "This Attribute is only available in direct mode" if($hash->{MODE} ne "DIRECT");
|
||||
|
||||
} elsif ($a[2] eq "TTS_UseMP3Wrap") {
|
||||
|
||||
return "This Attribute is only available in direct mode" if($hash->{MODE} ne "DIRECT");
|
||||
|
||||
}
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
sub Text2Speech_Ready($)
|
||||
|
||||
{
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
return Text2speech_OpenDev($hash, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
########################
|
||||
|
||||
sub Text2Speech_OpenDev($) {
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
my $dev = $hash->{Host};
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
|
||||
|
||||
Log3 $name, 4, "Text2Speech opening $name at $dev";
|
||||
|
||||
|
||||
|
||||
my $conn;
|
||||
|
||||
if($hash->{SSL}) {
|
||||
|
||||
eval "use IO::Socket::SSL";
|
||||
|
||||
Log3 $name, 1, $@ if($@);
|
||||
|
||||
$conn = IO::Socket::SSL->new(PeerAddr => "$dev") if(!$@);
|
||||
|
||||
} else {
|
||||
|
||||
$conn = IO::Socket::INET->new(PeerAddr => $dev);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(!$conn) {
|
||||
|
||||
Log3($name, 3, "Text2Speech: Can't connect to $dev: $!");
|
||||
|
||||
$hash->{STATE} = "disconnected";
|
||||
|
||||
return "";
|
||||
|
||||
} else {
|
||||
|
||||
$hash->{STATE} = "Initialized";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$hash->{TCPDev} = $conn;
|
||||
|
||||
$hash->{FD} = $conn->fileno();
|
||||
|
||||
|
||||
|
||||
Log3 $name, 4, "Text2Speech device opened ($name)";
|
||||
|
||||
|
||||
|
||||
syswrite($hash->{TCPDev}, $hash->{portpassword} . "\n")
|
||||
|
||||
if($hash->{portpassword});
|
||||
|
||||
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
########################
|
||||
|
||||
sub Text2Speech_CloseDev($) {
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $dev = $hash->{Host};
|
||||
|
||||
return if(!$dev);
|
||||
|
||||
|
||||
|
||||
if($hash->{TCPDev}) {
|
||||
|
||||
$hash->{TCPDev}->close();
|
||||
|
||||
Log3 $hash, 4, "Text2speech Device closed ($name)";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
delete($hash->{TCPDev});
|
||||
|
||||
delete($hash->{FD});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
########################
|
||||
|
||||
sub Text2Speech_Write($$) {
|
||||
|
||||
my ($hash,$msg) = @_;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $dev = $hash->{Host};
|
||||
|
||||
|
||||
|
||||
#my $call = "set tts tts Das ist ein Test.";
|
||||
|
||||
my $call = "set $name tts $msg";
|
||||
|
||||
|
||||
|
||||
Text2Speech_OpenDev($hash) if(!$hash->{TCPDev});
|
||||
|
||||
#lets try again
|
||||
|
||||
Text2Speech_OpenDev($hash) if(!$hash->{TCPDev});
|
||||
|
||||
|
||||
|
||||
if($hash->{TCPDev}) {
|
||||
|
||||
Log3 $hash, 4, "Text2Speech: Write remote message to $dev: $call";
|
||||
|
||||
Log3 $hash, 3, "Text2Speech: Could not write remote message ($call) at " .$hash->{Host} if(!defined(syswrite($hash->{TCPDev}, "$call\n")));
|
||||
|
||||
Text2Speech_CloseDev($hash);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
###########################################################################
|
||||
|
||||
|
||||
|
||||
sub Text2Speech_Set($@)
|
||||
|
||||
{
|
||||
|
||||
my ($hash, @a) = @_;
|
||||
|
||||
my $me = $hash->{NAME};
|
||||
|
||||
|
||||
|
||||
return "no set argument specified" if(int(@a) < 2);
|
||||
|
||||
|
||||
|
||||
my $cmd = shift(@a); # Dummy
|
||||
|
||||
$cmd = shift(@a); # DevName
|
||||
|
||||
|
||||
|
||||
if(!defined($sets{$cmd})) {
|
||||
|
||||
my $r = "Unknown argument $cmd, choose one of ".join(" ",sort keys %sets);
|
||||
|
||||
return $r;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($cmd ne "tts") {
|
||||
|
||||
return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Abbruch falls Disabled
|
||||
|
||||
return undef if(AttrVal($hash->{NAME}, "disable", "0") eq "1");
|
||||
|
||||
|
||||
|
||||
if($cmd eq "tts") {
|
||||
|
||||
if($hash->{MODE} eq "DIRECT") {
|
||||
|
||||
Text2Speech_PrepareSpeech($hash, join(" ", @a));
|
||||
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("Text2Speech_DoIt", $hash, "Text2Speech_Done", 60, "Text2Speech_AbortFn", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
|
||||
} elsif ($hash->{MODE} eq "REMOTE") {
|
||||
|
||||
Text2Speech_Write($hash, join(" ", @a));
|
||||
|
||||
} else {return undef;}
|
||||
|
||||
} elsif($cmd eq "volume") {
|
||||
|
||||
my $vol = join(" ", @a);
|
||||
|
||||
return "volume adjusting only available in direct mode" if($hash->{MODE} ne "DIRECT");
|
||||
|
||||
return "volume level expects 0..100 percent" if($vol !~ m/^([0-9]{1,2})$/);
|
||||
|
||||
$hash->{VOLUME} = $vol if($vol ne 100);
|
||||
|
||||
delete($hash->{VOLUME}) if($vol eq 100);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
# Bereitet den gesamten String vor.
|
||||
|
||||
# Bei Nutzung Google wird dieser in ein Array
|
||||
|
||||
# zerlegt mit jeweils einer maximalen
|
||||
|
||||
# Stringlänge von 100Chars
|
||||
|
||||
#
|
||||
|
||||
# param1: $hash
|
||||
|
||||
# param2: string to speech
|
||||
|
||||
#
|
||||
|
||||
#####################################
|
||||
|
||||
sub Text2Speech_PrepareSpeech($$) {
|
||||
|
||||
my ($hash, $t) = @_;
|
||||
|
||||
|
||||
|
||||
my $TTS_Ressource = AttrVal($hash->{NAME}, "TTS_Ressource", "Google");
|
||||
|
||||
my $TTS_Delemiter = AttrVal($hash->{NAME}, "TTS_Delemiter", undef);
|
||||
|
||||
|
||||
|
||||
my $TTS_ForceSplit = 0;
|
||||
|
||||
my $TTS_AddDelemiter;
|
||||
|
||||
|
||||
|
||||
if($TTS_Delemiter && $TTS_Delemiter =~ m/^[+-]a[lfn]/i) {
|
||||
|
||||
$TTS_ForceSplit = 1 if(substr($TTS_Delemiter,0,1) eq "+");
|
||||
|
||||
$TTS_ForceSplit = 0 if(substr($TTS_Delemiter,0,1) eq "-");
|
||||
|
||||
|
||||
|
||||
$TTS_AddDelemiter = substr($TTS_Delemiter,1,2); # af, al oder an
|
||||
|
||||
|
||||
|
||||
$TTS_Delemiter = substr($TTS_Delemiter,3);
|
||||
|
||||
|
||||
|
||||
} elsif (!$TTS_Delemiter) { # Default wenn Attr nicht gesetzt
|
||||
|
||||
$TTS_Delemiter = "(?<=[\\.!?])\\s*";
|
||||
|
||||
$TTS_ForceSplit = 1;
|
||||
|
||||
$TTS_AddDelemiter = "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($TTS_Ressource eq "Google") {
|
||||
|
||||
my @text;
|
||||
|
||||
|
||||
|
||||
$t =~ s/ä/ae/g;
|
||||
|
||||
$t =~ s/ö/oe/g;
|
||||
|
||||
$t =~ s/ü/ue/g;
|
||||
|
||||
$t =~ s/Ä/Ae/g;
|
||||
|
||||
$t =~ s/Ö/Oe/g;
|
||||
|
||||
$t =~ s/Ü/Ue/g;
|
||||
|
||||
$t =~ s/ß/sz/g;
|
||||
|
||||
|
||||
|
||||
@text = $hash->{helper}{Text2Speech} if($hash->{helper}{Text2Speech}[0]);
|
||||
|
||||
push(@text, $t);
|
||||
|
||||
|
||||
|
||||
@text = Text2Speech_SplitString(\@text, 100, $TTS_Delemiter, $TTS_ForceSplit, $TTS_AddDelemiter);
|
||||
|
||||
@text = Text2Speech_SplitString(\@text, 100, "(?<=[\\.!?])\\s*", 0, "");
|
||||
|
||||
@text = Text2Speech_SplitString(\@text, 100, ",", 0, "al");
|
||||
|
||||
@text = Text2Speech_SplitString(\@text, 100, ";", 0, "al");
|
||||
|
||||
@text = Text2Speech_SplitString(\@text, 100, "und", 0, "af");
|
||||
|
||||
|
||||
|
||||
@{$hash->{helper}{Text2Speech}} = @text;
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
push(@{$hash->{helper}{Text2Speech}}, $t);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
# param1: array : Text 2 Speech
|
||||
|
||||
# param2: string: MaxChar
|
||||
|
||||
# param3: string: Delemiter
|
||||
|
||||
# param4: int : 1 -> es wird am Delemiter gesplittet
|
||||
|
||||
# 0 -> es wird nur gesplittet, wenn Stringlänge länger als MaxChar
|
||||
|
||||
# param5: string: Add Delemiter to String? [pre|past|<empty>]
|
||||
|
||||
#
|
||||
|
||||
# Splittet die Texte aus $hash->{helper}->{Text2Speech} anhand des
|
||||
|
||||
# Delemiters, wenn die Stringlänge MaxChars übersteigt.
|
||||
|
||||
# Ist "AddDelemiter" angegeben, so wird der Delemiter an den
|
||||
|
||||
# String wieder angefügt
|
||||
|
||||
#####################################
|
||||
|
||||
sub Text2Speech_SplitString(@$$$$){
|
||||
|
||||
my @text = @{$_[0]};
|
||||
|
||||
my $MaxChar = $_[1];
|
||||
|
||||
my $Delemiter = $_[2];
|
||||
|
||||
my $ForceSplit = $_[3];
|
||||
|
||||
my $AddDelemiter = $_[4];
|
||||
|
||||
my @newText;
|
||||
|
||||
|
||||
|
||||
for(my $i=0; $i<(@text); $i++) {
|
||||
|
||||
if((length($text[$i]) <= 100) && (!$ForceSplit)) { #Google kann nur 100zeichen
|
||||
|
||||
push(@newText, $text[$i]);
|
||||
|
||||
next;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
my @b = split(/$Delemiter/, $text[$i]);
|
||||
|
||||
for(my $j=0; $j<(@b); $j++) {
|
||||
|
||||
$b[$j] = $b[$j] . $Delemiter if($AddDelemiter eq "al"); # Am Satzende wieder hinzufügen.
|
||||
|
||||
$b[$j+1] = $Delemiter . $b[$j+1] if(($AddDelemiter eq "af") && ($b[$j+1])); # Am Satzanfang des nächsten Satzes wieder hinzufügen.
|
||||
|
||||
|
||||
|
||||
push(@newText, $b[$j]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return @newText;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
# param1: hash : Hash
|
||||
|
||||
# param2: string: Typ (mplayer oder mp3wrap oder ....)
|
||||
|
||||
# param3: string: Datei
|
||||
|
||||
#
|
||||
|
||||
# Erstellt den Commandstring für den Systemaufruf
|
||||
|
||||
#####################################
|
||||
|
||||
sub Text2Speech_BuildMplayerCmdString($$) {
|
||||
|
||||
my ($hash, $file) = @_;
|
||||
|
||||
my $cmd;
|
||||
|
||||
|
||||
|
||||
my $TTS_MplayerCall = AttrVal($hash->{NAME}, "TTS_MplayerCall", $mplayer);
|
||||
|
||||
my $verbose = AttrVal($hash->{NAME}, "verbose", 3);
|
||||
|
||||
|
||||
|
||||
if($hash->{VOLUME}) { # per: set <name> volume <..>
|
||||
|
||||
$mplayerOpts .= " -softvol -softvol-max 110 -volume " . $hash->{VOLUME};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
my $AlsaDevice = $hash->{ALSADEVICE};
|
||||
|
||||
if($AlsaDevice eq "none") {
|
||||
|
||||
$AlsaDevice = "";
|
||||
|
||||
$mplayerAudioOpts = "";
|
||||
@@ -173,6 +173,7 @@ FHEM/95_Dashboard.pm svenson08 http://forum.fhem.de Frontends
|
||||
FHEM/95_PachLog.pm rudolfkoenig/orphan http://forum.fhem.de Sonstiges
|
||||
FHEM/95_holiday.pm rudolfkoenig http://forum.fhem.de Sonstiges
|
||||
FHEM/95_remotecontrol.pm ulimaass http://forum.fhem.de Frontends
|
||||
FHEM/98_Text2Speech.pm tobiasfaust http://forum.fhem.de Unterstuetzende Dienste
|
||||
FHEM/98_apptime.pm martinp876 http://forum.fhem.de Sonstiges
|
||||
FHEM/98_CULflash.pm rudolfkoenig http://forum.fhem.de Sonstiges
|
||||
FHEM/98_GEOFANCY.pm loredo http://forum.fhem.de Unterstuetzende Dienste
|
||||
|
||||
Reference in New Issue
Block a user