Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
7abe60d1
Commit
7abe60d1
authored
Oct 21, 2015
by
Gus Grubba
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2070 from dogmaphobic/textToSpeech
Text to Speech Work
parents
fec16350
dd587ce2
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
261 additions
and
174 deletions
+261
-174
QGCExternalLibs.pri
QGCExternalLibs.pri
+85
-80
UsbDeviceJNI.java
android/src/org/qgroundcontrol/qgchelper/UsbDeviceJNI.java
+33
-1
GAudioOutput.cc
src/GAudioOutput.cc
+34
-11
GAudioOutput.h
src/GAudioOutput.h
+7
-4
QGCAudioWorker.cpp
src/audio/QGCAudioWorker.cpp
+66
-32
QGCAudioWorker.h
src/audio/QGCAudioWorker.h
+3
-9
UAS.cc
src/uas/UAS.cc
+33
-37
No files found.
QGCExternalLibs.pri
View file @
7abe60d1
...
...
@@ -270,6 +270,11 @@ else:WindowsBuild {
DEFINES += QGC_SPEECH_ENABLED
LIBS += -lOle32
}
# Android supports speech through native (Java) API.
else:AndroidBuild {
message("Including support for speech output")
DEFINES += QGC_SPEECH_ENABLED
}
#
# [OPTIONAL] Zeroconf for UDP links
...
...
android/src/org/qgroundcontrol/qgchelper/UsbDeviceJNI.java
View file @
7abe60d1
...
...
@@ -43,12 +43,15 @@ import android.content.IntentFilter;
import
android.hardware.usb.*
;
import
android.widget.Toast
;
import
android.util.Log
;
//-- Text To Speech
import
android.os.Bundle
;
import
android.speech.tts.TextToSpeech
;
import
com.hoho.android.usbserial.driver.*
;
import
org.qtproject.qt5.android.bindings.QtActivity
;
import
org.qtproject.qt5.android.bindings.QtApplication
;
public
class
UsbDeviceJNI
extends
QtActivity
public
class
UsbDeviceJNI
extends
QtActivity
implements
TextToSpeech
.
OnInitListener
{
public
static
int
BAD_PORT
=
0
;
private
static
UsbDeviceJNI
m_instance
;
...
...
@@ -61,6 +64,7 @@ public class UsbDeviceJNI extends QtActivity
private
BroadcastReceiver
m_UsbReceiver
=
null
;
private
final
static
ExecutorService
m_Executor
=
Executors
.
newSingleThreadExecutor
();
private
static
final
String
TAG
=
"QGC_UsbDeviceJNI"
;
private
static
TextToSpeech
m_tts
;
private
final
static
UsbIoManager
.
Listener
m_Listener
=
new
UsbIoManager
.
Listener
()
...
...
@@ -98,6 +102,34 @@ public class UsbDeviceJNI extends QtActivity
Log
.
i
(
TAG
,
"Instance created"
);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Text To Speech
// Pigback a ride for providing TTS to QGC
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
m_tts
=
new
TextToSpeech
(
this
,
this
);
}
@Override
protected
void
onDestroy
()
{
super
.
onDestroy
();
m_tts
.
shutdown
();
}
public
void
onInit
(
int
status
)
{
}
public
static
void
say
(
String
msg
)
{
Log
.
i
(
TAG
,
"Say: "
+
msg
);
m_tts
.
speak
(
msg
,
TextToSpeech
.
QUEUE_FLUSH
,
null
);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Find all current devices that match the device filter described in the androidmanifest.xml and the
...
...
src/GAudioOutput.cc
View file @
7abe60d1
...
...
@@ -38,42 +38,51 @@ This file is part of the QGROUNDCONTROL project
#include "QGCApplication.h"
#include "QGC.h"
#if defined __android__
#include <QtAndroidExtras/QtAndroidExtras>
#include <QtAndroidExtras/QAndroidJniObject>
#endif
IMPLEMENT_QGC_SINGLETON
(
GAudioOutput
,
GAudioOutput
)
const
char
*
GAudioOutput
::
_mutedKey
=
"AudioMuted"
;
GAudioOutput
::
GAudioOutput
(
QObject
*
parent
)
:
QGCSingleton
(
parent
),
muted
(
false
),
thread
(
new
QThread
()),
worker
(
new
QGCAudioWorker
())
GAudioOutput
::
GAudioOutput
(
QObject
*
parent
)
:
QGCSingleton
(
parent
)
,
muted
(
false
)
#ifndef __android__
,
thread
(
new
QThread
())
,
worker
(
new
QGCAudioWorker
())
#endif
{
QSettings
settings
;
muted
=
settings
.
value
(
_mutedKey
,
false
).
toBool
();
muted
|=
qgcApp
()
->
runningUnitTests
();
#ifndef __android__
worker
->
moveToThread
(
thread
);
connect
(
this
,
&
GAudioOutput
::
textToSpeak
,
worker
,
&
QGCAudioWorker
::
say
);
connect
(
thread
,
&
QThread
::
finished
,
thread
,
&
QObject
::
deleteLater
);
connect
(
thread
,
&
QThread
::
finished
,
worker
,
&
QObject
::
deleteLater
);
thread
->
start
();
#endif
}
GAudioOutput
::~
GAudioOutput
()
{
#ifndef __android__
thread
->
quit
();
#endif
}
void
GAudioOutput
::
mute
(
bool
mute
)
{
QSettings
settings
;
muted
=
mute
;
settings
.
setValue
(
_mutedKey
,
mute
);
#ifndef __android__
emit
mutedChanged
(
mute
);
#endif
}
bool
GAudioOutput
::
isMuted
()
...
...
@@ -81,10 +90,24 @@ bool GAudioOutput::isMuted()
return
muted
;
}
bool
GAudioOutput
::
say
(
const
QString
&
t
ext
,
int
severity
)
bool
GAudioOutput
::
say
(
const
QString
&
inT
ext
,
int
severity
)
{
if
(
!
muted
)
{
emit
textToSpeak
(
text
,
severity
);
#if defined __android__
#if defined QGC_SPEECH_ENABLED
static
const
char
V_jniClassName
[]
{
"org/qgroundcontrol/qgchelper/UsbDeviceJNI"
};
QAndroidJniEnvironment
env
;
if
(
env
->
ExceptionCheck
())
{
env
->
ExceptionDescribe
();
env
->
ExceptionClear
();
}
QString
text
=
QGCAudioWorker
::
fixTextMessageForAudio
(
inText
);
QAndroidJniObject
javaMessage
=
QAndroidJniObject
::
fromString
(
text
);
QAndroidJniObject
::
callStaticMethod
<
void
>
(
V_jniClassName
,
"say"
,
"(Ljava/lang/String;)V"
,
javaMessage
.
object
<
jstring
>
());
#endif
#else
emit
textToSpeak
(
inText
,
severity
);
#endif
}
return
true
;
}
src/GAudioOutput.h
View file @
7abe60d1
...
...
@@ -88,8 +88,11 @@ signals:
protected:
bool
muted
;
#if !defined __android__
QThread
*
thread
;
QGCAudioWorker
*
worker
;
#endif
private:
GAudioOutput
(
QObject
*
parent
=
NULL
);
...
...
src/audio/QGCAudioWorker.cpp
View file @
7abe60d1
...
...
@@ -10,6 +10,47 @@
#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
#include <ApplicationServices/ApplicationServices.h>
static
SpeechChannel
sc
;
static
Fixed
volume
;
static
void
speechDone
(
SpeechChannel
sc2
,
void
*
)
{
if
(
sc2
==
sc
)
{
DisposeSpeechChannel
(
sc
);
}
}
class
MacSpeech
{
public:
MacSpeech
()
{
setVolume
(
100
);
}
~
MacSpeech
()
{
}
void
say
(
const
char
*
words
)
{
while
(
SpeechBusy
())
{
QGC
::
SLEEP
::
msleep
(
100
);
}
NewSpeechChannel
(
NULL
,
&
sc
);
SetSpeechInfo
(
sc
,
soVolume
,
&
volume
);
SetSpeechInfo
(
sc
,
soSpeechDoneCallBack
,
reinterpret_cast
<
void
*>
(
speechDone
));
CFStringRef
cfstr
=
CFStringCreateWithCString
(
NULL
,
words
,
kCFStringEncodingUTF8
);
SpeakCFString
(
sc
,
cfstr
,
NULL
);
}
void
setVolume
(
int
v
)
{
volume
=
FixRatio
(
v
,
100
);
}
};
//-- Singleton
MacSpeech
macSpeech
;
#endif
// Speech synthesis is only supported with MSVC compiler
...
...
@@ -18,7 +59,7 @@
#include <sapi.h>
#endif
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
#if defined Q_OS_LINUX &&
!defined __android__ &&
defined QGC_SPEECH_ENABLED
// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
#include <espeak/speak_lib.h>
#endif
...
...
@@ -48,7 +89,7 @@ void QGCAudioWorker::init()
sound
=
new
QSound
(
":/res/Alert"
);
#endif
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
#if defined Q_OS_LINUX &&
!defined __android__ &&
defined QGC_SPEECH_ENABLED
espeak_Initialize
(
AUDIO_OUTPUT_SYNCH_PLAYBACK
,
500
,
NULL
,
0
);
// initialize for playback with 500ms buffer and no options (see speak_lib.h)
espeak_VOICE
*
espeak_voice
=
espeak_GetCurrentVoice
();
espeak_voice
->
languages
=
"en-uk"
;
// Default to British English
...
...
@@ -92,6 +133,10 @@ QGCAudioWorker::~QGCAudioWorker()
void
QGCAudioWorker
::
say
(
QString
inText
,
int
severity
)
{
#ifdef __android__
Q_UNUSED
(
inText
);
Q_UNUSED
(
severity
);
#else
static
bool
threadInit
=
false
;
if
(
!
threadInit
)
{
threadInit
=
true
;
...
...
@@ -100,7 +145,7 @@ void QGCAudioWorker::say(QString inText, int severity)
if
(
!
muted
)
{
QString
text
=
_
fixTextMessageForAudio
(
inText
);
QString
text
=
fixTextMessageForAudio
(
inText
);
// Prepend high priority text with alert beep
if
(
severity
<
GAudioOutput
::
AUDIO_SEVERITY_CRITICAL
)
{
beep
();
...
...
@@ -124,26 +169,13 @@ void QGCAudioWorker::say(QString inText, int severity)
espeak_Synth
(
text
.
toStdString
().
c_str
(),
espeak_size
,
0
,
POS_CHARACTER
,
0
,
espeakCHARS_AUTO
,
NULL
,
NULL
);
#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
// Slashes necessary to have the right start to the sentence
// copying data prevents SpeakString from reading additional chars
text
=
"
\\
"
+
text
;
std
::
wstring
str
=
text
.
toStdWString
();
unsigned
char
str2
[
1024
]
=
{};
memcpy
(
str2
,
text
.
toLatin1
().
data
(),
str
.
length
());
SpeakString
(
str2
);
// Block the thread while busy
// because we run in our own thread, this doesn't
// halt the main application
while
(
SpeechBusy
())
{
QGC
::
SLEEP
::
msleep
(
100
);
}
macSpeech
.
say
(
text
.
toStdString
().
c_str
());
#else
// Make sure there isn't an unused variable warning when speech output is disabled
Q_UNUSED
(
inText
);
#endif
}
#endif // __android__
}
void
QGCAudioWorker
::
mute
(
bool
mute
)
...
...
@@ -187,7 +219,7 @@ bool QGCAudioWorker::_getMillisecondString(const QString& string, QString& match
return
false
;
}
QString
QGCAudioWorker
::
_
fixTextMessageForAudio
(
const
QString
&
string
)
{
QString
QGCAudioWorker
::
fixTextMessageForAudio
(
const
QString
&
string
)
{
QString
match
;
QString
newNumber
;
QString
result
=
string
;
...
...
@@ -204,7 +236,9 @@ QString QGCAudioWorker::_fixTextMessageForAudio(const QString& string) {
if
(
result
.
contains
(
"ALTCTL"
,
Qt
::
CaseInsensitive
))
{
result
.
replace
(
"ALTCTL"
,
"Altitude Control"
,
Qt
::
CaseInsensitive
);
}
if
(
result
.
contains
(
"RTL"
,
Qt
::
CaseInsensitive
))
{
if
(
result
.
contains
(
"AUTO_RTL"
,
Qt
::
CaseInsensitive
))
{
result
.
replace
(
"AUTO_RTL"
,
"auto Return To Land"
,
Qt
::
CaseInsensitive
);
}
else
if
(
result
.
contains
(
"RTL"
,
Qt
::
CaseInsensitive
))
{
result
.
replace
(
"RTL"
,
"Return To Land"
,
Qt
::
CaseInsensitive
);
}
if
(
result
.
contains
(
"ACCEL "
,
Qt
::
CaseInsensitive
))
{
...
...
src/audio/QGCAudioWorker.h
View file @
7abe60d1
...
...
@@ -7,13 +7,6 @@
#include <QSound>
#endif
/* For Snow leopard and later
#if defined Q_OS_MAC & defined QGC_SPEECH_ENABLED
#include <NSSpeechSynthesizer.h>
#endif
*/
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
#include <basetyps.h>
...
...
@@ -31,6 +24,8 @@ public:
bool
isMuted
();
void
init
();
static
QString
fixTextMessageForAudio
(
const
QString
&
string
);
signals:
public
slots
:
...
...
@@ -52,8 +47,7 @@ protected:
QTimer
*
emergencyTimer
;
bool
muted
;
private:
QString
_fixTextMessageForAudio
(
const
QString
&
string
);
bool
_getMillisecondString
(
const
QString
&
string
,
QString
&
match
,
int
&
number
);
static
bool
_getMillisecondString
(
const
QString
&
string
,
QString
&
match
,
int
&
number
);
};
#endif // QGCAUDIOWORKER_H
src/uas/UAS.cc
View file @
7abe60d1
...
...
@@ -422,7 +422,7 @@ void UAS::receiveMessage(mavlink_message_t message)
modechanged
=
true
;
this
->
base_mode
=
state
.
base_mode
;
this
->
custom_mode
=
state
.
custom_mode
;
modeAudio
=
" is now in "
+
audiomodeText
+
"flight mode"
;
modeAudio
=
" is now in "
+
audiomodeText
+
"
flight mode"
;
}
// We got the mode
...
...
@@ -2470,10 +2470,6 @@ void UAS::unsetRCToParameterMap()
void
UAS
::
_say
(
const
QString
&
text
,
int
severity
)
{
#ifndef UNITTEST_BUILD
if
(
!
qgcApp
()
->
runningUnitTests
())
GAudioOutput
::
instance
()
->
say
(
text
,
severity
);
#else
Q_UNUSED
(
text
)
Q_UNUSED
(
severity
)
#endif
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment