mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 00:14:06 +00:00
Win-specific: Add volume and rate tuning for TTS, fix some errors
This commit is contained in:
parent
58654a7423
commit
0fb8eed553
|
@ -973,7 +973,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
||||||
|
|
||||||
if ( itemMd5Id == md5Id )
|
if ( itemMd5Id == md5Id )
|
||||||
{
|
{
|
||||||
SpeechClient * speechClient = new SpeechClient( i->id, this );
|
SpeechClient * speechClient = new SpeechClient( *i, this );
|
||||||
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
||||||
speechClient->tell( text );
|
speechClient->tell( text );
|
||||||
break;
|
break;
|
||||||
|
|
16
config.cc
16
config.cc
|
@ -604,7 +604,7 @@ Class load() throw( exError )
|
||||||
|
|
||||||
QDomNode ves = root.namedItem( "voiceEngines" );
|
QDomNode ves = root.namedItem( "voiceEngines" );
|
||||||
|
|
||||||
if ( !wss.isNull() )
|
if ( !ves.isNull() )
|
||||||
{
|
{
|
||||||
QDomNodeList nl = ves.toElement().elementsByTagName( "voiceEngine" );
|
QDomNodeList nl = ves.toElement().elementsByTagName( "voiceEngine" );
|
||||||
|
|
||||||
|
@ -617,6 +617,12 @@ Class load() throw( exError )
|
||||||
v.id = ve.attribute( "id" );
|
v.id = ve.attribute( "id" );
|
||||||
v.name = ve.attribute( "name" );
|
v.name = ve.attribute( "name" );
|
||||||
v.iconFilename = ve.attribute( "icon" );
|
v.iconFilename = ve.attribute( "icon" );
|
||||||
|
v.volume = ve.attribute( "volume", "50" ).toInt();
|
||||||
|
if( v.volume < 0 || v.volume > 100 )
|
||||||
|
v.volume = 50;
|
||||||
|
v.rate = ve.attribute( "rate", "50" ).toInt();
|
||||||
|
if( v.rate < 0 || v.rate > 100 )
|
||||||
|
v.rate = 50;
|
||||||
c.voiceEngines.push_back( v );
|
c.voiceEngines.push_back( v );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1205,6 +1211,14 @@ void save( Class const & c ) throw( exError )
|
||||||
QDomAttr icon = dd.createAttribute( "icon" );
|
QDomAttr icon = dd.createAttribute( "icon" );
|
||||||
icon.setValue( i->iconFilename );
|
icon.setValue( i->iconFilename );
|
||||||
v.setAttributeNode( icon );
|
v.setAttributeNode( icon );
|
||||||
|
|
||||||
|
QDomAttr volume = dd.createAttribute( "volume" );
|
||||||
|
volume.setValue( QString::number( i->volume ) );
|
||||||
|
v.setAttributeNode( volume );
|
||||||
|
|
||||||
|
QDomAttr rate = dd.createAttribute( "rate" );
|
||||||
|
rate.setValue( QString::number( i->rate ) );
|
||||||
|
v.setAttributeNode( rate );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
config.hh
18
config.hh
|
@ -387,17 +387,29 @@ struct VoiceEngine
|
||||||
QString id;
|
QString id;
|
||||||
QString name;
|
QString name;
|
||||||
QString iconFilename;
|
QString iconFilename;
|
||||||
|
int volume; // 0-100 allowed
|
||||||
|
int rate; // 0-100 allowed
|
||||||
|
|
||||||
VoiceEngine(): enabled( false )
|
VoiceEngine(): enabled( false )
|
||||||
{
|
, volume( 50 )
|
||||||
}
|
, rate( 50 )
|
||||||
|
{}
|
||||||
|
VoiceEngine( QString id_, QString name_, int volume_, int rate_ ):
|
||||||
|
enabled( false )
|
||||||
|
, id( id_ )
|
||||||
|
, name( name_ )
|
||||||
|
, volume( volume_ )
|
||||||
|
, rate( rate_ )
|
||||||
|
{}
|
||||||
|
|
||||||
bool operator == ( VoiceEngine const & other ) const
|
bool operator == ( VoiceEngine const & other ) const
|
||||||
{
|
{
|
||||||
return enabled == other.enabled &&
|
return enabled == other.enabled &&
|
||||||
id == other.id &&
|
id == other.id &&
|
||||||
name == other.name &&
|
name == other.name &&
|
||||||
iconFilename == other.iconFilename;
|
iconFilename == other.iconFilename &&
|
||||||
|
volume == other.volume &&
|
||||||
|
rate == other.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator != ( VoiceEngine const & other ) const
|
bool operator != ( VoiceEngine const & other ) const
|
||||||
|
|
|
@ -348,7 +348,8 @@ win32 {
|
||||||
texttospeechsource.hh \
|
texttospeechsource.hh \
|
||||||
sapi.hh \
|
sapi.hh \
|
||||||
sphelper.hh \
|
sphelper.hh \
|
||||||
speechclient.hh
|
speechclient.hh \
|
||||||
|
speechhlp.hh
|
||||||
}
|
}
|
||||||
|
|
||||||
mac {
|
mac {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __SPEECHCLIENT_HH_INCLUDED__
|
#define __SPEECHCLIENT_HH_INCLUDED__
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include "config.hh"
|
||||||
|
|
||||||
class SpeechClient: public QObject
|
class SpeechClient: public QObject
|
||||||
{
|
{
|
||||||
|
@ -13,18 +14,28 @@ public:
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
QString name;
|
QString name;
|
||||||
|
// Volume and rate may vary from 0 to 100
|
||||||
|
int volume;
|
||||||
|
int rate;
|
||||||
|
Engine( Config::VoiceEngine const & e ) :
|
||||||
|
id( e.id )
|
||||||
|
, name( e.name )
|
||||||
|
, volume( e.volume )
|
||||||
|
, rate( e.rate )
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QList<Engine> Engines;
|
typedef QList<Engine> Engines;
|
||||||
|
|
||||||
SpeechClient( QString const & engineId, QObject * parent = 0L );
|
SpeechClient( Config::VoiceEngine const & e, QObject * parent = 0L );
|
||||||
virtual ~SpeechClient();
|
virtual ~SpeechClient();
|
||||||
|
|
||||||
static Engines availableEngines();
|
static Engines availableEngines();
|
||||||
|
|
||||||
const Engine & engine() const;
|
const Engine & engine() const;
|
||||||
bool tell( QString const & text );
|
|
||||||
bool say( QString const & text );
|
bool tell( QString const & text, int volume = -1, int rate = -1 );
|
||||||
|
bool say( QString const & text, int volume = -1, int rate = -1 );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void started( bool ok );
|
void started( bool ok );
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
struct SpeechClient::InternalData
|
struct SpeechClient::InternalData
|
||||||
{
|
{
|
||||||
InternalData( QString const & engineId ):
|
InternalData( Config::VoiceEngine const & e ):
|
||||||
waitingFinish( false )
|
waitingFinish( false )
|
||||||
|
, engine( e )
|
||||||
|
, oldVolume( -1 )
|
||||||
|
, oldRate( -1 )
|
||||||
{
|
{
|
||||||
sp = speechCreate( engineId.toStdWString().c_str() );
|
sp = speechCreate( e.id.toStdWString().c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
~InternalData()
|
~InternalData()
|
||||||
|
@ -19,13 +22,15 @@ struct SpeechClient::InternalData
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeechHelper sp;
|
SpeechHelper sp;
|
||||||
Engine engine;
|
|
||||||
bool waitingFinish;
|
bool waitingFinish;
|
||||||
|
Engine engine;
|
||||||
|
int oldVolume;
|
||||||
|
int oldRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
SpeechClient::SpeechClient( QString const & engineId, QObject * parent ):
|
SpeechClient::SpeechClient( Config::VoiceEngine const & e, QObject * parent ):
|
||||||
QObject( parent ),
|
QObject( parent ),
|
||||||
internalData( new InternalData( engineId ) )
|
internalData( new InternalData( e ) )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +45,10 @@ static bool enumEngines( void * /* token */,
|
||||||
void * userData )
|
void * userData )
|
||||||
{
|
{
|
||||||
SpeechClient::Engines * pEngines = ( SpeechClient::Engines * )userData;
|
SpeechClient::Engines * pEngines = ( SpeechClient::Engines * )userData;
|
||||||
SpeechClient::Engine engine =
|
SpeechClient::Engine engine( Config::VoiceEngine(
|
||||||
{
|
|
||||||
QString::fromWCharArray( id ),
|
QString::fromWCharArray( id ),
|
||||||
QString::fromWCharArray( name )
|
QString::fromWCharArray( name ),
|
||||||
};
|
50, 50 ) );
|
||||||
pEngines->push_back( engine );
|
pEngines->push_back( engine );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +65,7 @@ const SpeechClient::Engine & SpeechClient::engine() const
|
||||||
return internalData->engine;
|
return internalData->engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpeechClient::tell( QString const & text )
|
bool SpeechClient::tell( QString const & text, int volume, int rate )
|
||||||
{
|
{
|
||||||
if ( !speechAvailable( internalData->sp ) )
|
if ( !speechAvailable( internalData->sp ) )
|
||||||
return false;
|
return false;
|
||||||
|
@ -69,7 +73,16 @@ bool SpeechClient::tell( QString const & text )
|
||||||
if ( internalData->waitingFinish )
|
if ( internalData->waitingFinish )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if( volume < 0 )
|
||||||
|
volume = engine().volume;
|
||||||
|
if( rate < 0 )
|
||||||
|
rate = engine().rate;
|
||||||
|
|
||||||
|
internalData->oldVolume = setSpeechVolume( internalData->sp, volume );
|
||||||
|
internalData->oldRate = setSpeechRate( internalData->sp, rate );
|
||||||
|
|
||||||
bool ok = speechTell( internalData->sp, text.toStdWString().c_str() );
|
bool ok = speechTell( internalData->sp, text.toStdWString().c_str() );
|
||||||
|
|
||||||
emit started( ok );
|
emit started( ok );
|
||||||
|
|
||||||
if ( ok )
|
if ( ok )
|
||||||
|
@ -84,12 +97,27 @@ bool SpeechClient::tell( QString const & text )
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpeechClient::say( QString const & text )
|
bool SpeechClient::say( QString const & text, int volume, int rate )
|
||||||
{
|
{
|
||||||
if ( !speechAvailable( internalData->sp ) )
|
if ( !speechAvailable( internalData->sp ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return speechSay( internalData->sp, text.toStdWString().c_str() );
|
if( volume < 0 )
|
||||||
|
volume = engine().volume;
|
||||||
|
if( rate < 0 )
|
||||||
|
rate = engine().rate;
|
||||||
|
|
||||||
|
int oldVolume = setSpeechVolume( internalData->sp, volume );
|
||||||
|
int oldRate = setSpeechRate( internalData->sp, rate );
|
||||||
|
|
||||||
|
bool ok = speechSay( internalData->sp, text.toStdWString().c_str() );
|
||||||
|
|
||||||
|
if( oldVolume >=0 )
|
||||||
|
setSpeechVolume( internalData->sp, oldVolume );
|
||||||
|
if( oldRate >=0 )
|
||||||
|
setSpeechRate( internalData->sp, oldRate );
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeechClient::timerEvent( QTimerEvent * evt )
|
void SpeechClient::timerEvent( QTimerEvent * evt )
|
||||||
|
@ -103,6 +131,14 @@ void SpeechClient::timerEvent( QTimerEvent * evt )
|
||||||
{
|
{
|
||||||
killTimer( evt->timerId() ) ;
|
killTimer( evt->timerId() ) ;
|
||||||
internalData->waitingFinish = false;
|
internalData->waitingFinish = false;
|
||||||
|
|
||||||
|
if( internalData->oldVolume >=0 )
|
||||||
|
setSpeechVolume( internalData->sp, internalData->oldVolume );
|
||||||
|
if( internalData->oldRate >=0 )
|
||||||
|
setSpeechRate( internalData->sp, internalData->oldRate );
|
||||||
|
internalData->oldVolume = -1;
|
||||||
|
internalData->oldRate = -1;
|
||||||
|
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
speechhlp.cc
24
speechhlp.cc
|
@ -165,3 +165,27 @@ bool speechSay(SpeechHelper sp, const wchar_t *text)
|
||||||
HRESULT hr = sp->voice->Speak(text, SPF_IS_NOT_XML, 0);
|
HRESULT hr = sp->voice->Speak(text, SPF_IS_NOT_XML, 0);
|
||||||
return !!SUCCEEDED(hr);
|
return !!SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int setSpeechVolume( SpeechHelper sp, int newVolume )
|
||||||
|
{
|
||||||
|
if( !sp || !sp->voice || newVolume < 0 || newVolume > 100 )
|
||||||
|
return -1;
|
||||||
|
unsigned short oldVolume;
|
||||||
|
HRESULT hr = sp->voice->GetVolume( &oldVolume );
|
||||||
|
if( !SUCCEEDED( hr ) )
|
||||||
|
return -1;
|
||||||
|
sp->voice->SetVolume( (unsigned short) newVolume );
|
||||||
|
return oldVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setSpeechRate( SpeechHelper sp, int newRate )
|
||||||
|
{
|
||||||
|
if( !sp || !sp->voice || newRate < 0 || newRate > 100 )
|
||||||
|
return -1;
|
||||||
|
long oldRate;
|
||||||
|
HRESULT hr = sp->voice->GetRate( &oldRate );
|
||||||
|
if( !SUCCEEDED( hr ) )
|
||||||
|
return -1;
|
||||||
|
sp->voice->SetRate( ( newRate - 50 ) / 5 );
|
||||||
|
return oldRate * 5 + 50;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ const wchar_t * speechEngineName(SpeechHelper sp);
|
||||||
bool speechTell(SpeechHelper sp, const wchar_t *text);
|
bool speechTell(SpeechHelper sp, const wchar_t *text);
|
||||||
bool speechTellFinished(SpeechHelper sp);
|
bool speechTellFinished(SpeechHelper sp);
|
||||||
bool speechSay(SpeechHelper sp, const wchar_t *text);
|
bool speechSay(SpeechHelper sp, const wchar_t *text);
|
||||||
|
int setSpeechVolume( SpeechHelper sp, int newVolume );
|
||||||
|
int setSpeechRate( SpeechHelper sp, int newRate );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
#define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a)
|
#define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _SAPI_VER
|
||||||
|
#undef _SAPI_VER
|
||||||
|
#endif
|
||||||
|
#define _SAPI_VER 0503
|
||||||
|
|
||||||
inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
|
inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
|
||||||
{
|
{
|
||||||
// If for some reason we cannot convert a number, set it to 0
|
// If for some reason we cannot convert a number, set it to 0
|
||||||
|
|
|
@ -25,6 +25,30 @@ TextToSpeechSource::TextToSpeechSource( QWidget * parent,
|
||||||
{
|
{
|
||||||
ui.availableVoiceEngines->addItem( engine.name, engine.id );
|
ui.availableVoiceEngines->addItem( engine.name, engine.id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( voiceEngines.count() > 0 )
|
||||||
|
{
|
||||||
|
QModelIndex const &idx = ui.selectedVoiceEngines->model()->index( 0, 0 );
|
||||||
|
if( idx.isValid() )
|
||||||
|
ui.selectedVoiceEngines->setCurrentIndex( idx );
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustSliders();
|
||||||
|
|
||||||
|
connect( ui.volumeSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
connect( ui.rateSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
connect( ui.selectedVoiceEngines->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
|
||||||
|
this, SLOT( selectionChanged() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextToSpeechSource::slidersChanged()
|
||||||
|
{
|
||||||
|
if( ui.selectedVoiceEngines->selectionModel()->hasSelection() )
|
||||||
|
voiceEnginesModel.setEngineParams( ui.selectedVoiceEngines->currentIndex(),
|
||||||
|
ui.volumeSlider->value(),
|
||||||
|
ui.rateSlider->value()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToSpeechSource::on_addVoiceEngine_clicked()
|
void TextToSpeechSource::on_addVoiceEngine_clicked()
|
||||||
|
@ -37,12 +61,15 @@ void TextToSpeechSource::on_addVoiceEngine_clicked()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fake id and name
|
int idx = ui.availableVoiceEngines->currentIndex();
|
||||||
QString name = ui.availableVoiceEngines->itemText( 0 );
|
if( idx >= 0 )
|
||||||
QString id = ui.availableVoiceEngines->itemData( 0 ).toString();
|
{
|
||||||
voiceEnginesModel.addNewVoiceEngine( id, name );
|
QString name = ui.availableVoiceEngines->itemText( idx );
|
||||||
|
QString id = ui.availableVoiceEngines->itemData( idx ).toString();
|
||||||
|
voiceEnginesModel.addNewVoiceEngine( id, name, ui.volumeSlider->value(), ui.rateSlider->value() );
|
||||||
fitSelectedVoiceEnginesColumns();
|
fitSelectedVoiceEnginesColumns();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextToSpeechSource::on_removeVoiceEngine_clicked()
|
void TextToSpeechSource::on_removeVoiceEngine_clicked()
|
||||||
{
|
{
|
||||||
|
@ -66,8 +93,12 @@ void TextToSpeechSource::on_previewVoice_clicked()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString engineId = ui.availableVoiceEngines->itemData( idx ).toString();
|
QString engineId = ui.availableVoiceEngines->itemData( idx ).toString();
|
||||||
|
QString name = ui.availableVoiceEngines->itemText( idx );
|
||||||
QString text = ui.previewText->text();
|
QString text = ui.previewText->text();
|
||||||
SpeechClient * speechClient = new SpeechClient( engineId, this );
|
int volume = ui.volumeSlider->value();
|
||||||
|
int rate = ui.rateSlider->value();
|
||||||
|
|
||||||
|
SpeechClient * speechClient = new SpeechClient( Config::VoiceEngine( engineId, name, volume, rate ), this );
|
||||||
|
|
||||||
connect( speechClient, SIGNAL( started( bool ) ), ui.previewVoice, SLOT( setDisabled( bool ) ) );
|
connect( speechClient, SIGNAL( started( bool ) ), ui.previewVoice, SLOT( setDisabled( bool ) ) );
|
||||||
connect( speechClient, SIGNAL( finished() ), this, SLOT( previewVoiceFinished() ) );
|
connect( speechClient, SIGNAL( finished() ), this, SLOT( previewVoiceFinished() ) );
|
||||||
|
@ -87,6 +118,35 @@ void TextToSpeechSource::fitSelectedVoiceEnginesColumns()
|
||||||
ui.selectedVoiceEngines->resizeColumnToContents( VoiceEnginesModel::kColumnIcon );
|
ui.selectedVoiceEngines->resizeColumnToContents( VoiceEnginesModel::kColumnIcon );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextToSpeechSource::adjustSliders()
|
||||||
|
{
|
||||||
|
QModelIndex const & index = ui.selectedVoiceEngines->currentIndex();
|
||||||
|
if ( index.isValid() )
|
||||||
|
{
|
||||||
|
Config::VoiceEngines const &engines = voiceEnginesModel.getCurrentVoiceEngines();
|
||||||
|
ui.volumeSlider->setValue( engines[ index.row() ].volume );
|
||||||
|
ui.rateSlider->setValue( engines[ index.row() ].rate );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui.volumeSlider->setValue( 50 );
|
||||||
|
ui.rateSlider->setValue( 50 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextToSpeechSource::selectionChanged()
|
||||||
|
{
|
||||||
|
disconnect( ui.volumeSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
disconnect( ui.rateSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
|
||||||
|
adjustSliders();
|
||||||
|
|
||||||
|
connect( ui.volumeSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
connect( ui.rateSlider, SIGNAL( valueChanged( int ) ),
|
||||||
|
this, SLOT( slidersChanged() ) );
|
||||||
|
}
|
||||||
|
|
||||||
VoiceEnginesModel::VoiceEnginesModel( QWidget * parent,
|
VoiceEnginesModel::VoiceEnginesModel( QWidget * parent,
|
||||||
Config::VoiceEngines const & voiceEngines ):
|
Config::VoiceEngines const & voiceEngines ):
|
||||||
QAbstractItemModel( parent ), voiceEngines( voiceEngines )
|
QAbstractItemModel( parent ), voiceEngines( voiceEngines )
|
||||||
|
@ -100,7 +160,8 @@ void VoiceEnginesModel::removeVoiceEngine( int index )
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceEnginesModel::addNewVoiceEngine( QString const & id, QString const & name )
|
void VoiceEnginesModel::addNewVoiceEngine( QString const & id, QString const & name,
|
||||||
|
int volume, int rate )
|
||||||
{
|
{
|
||||||
if ( id.isEmpty() || name.isEmpty() )
|
if ( id.isEmpty() || name.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
@ -109,6 +170,8 @@ void VoiceEnginesModel::addNewVoiceEngine( QString const & id, QString const & n
|
||||||
v.enabled = true;
|
v.enabled = true;
|
||||||
v.id = id;
|
v.id = id;
|
||||||
v.name = name;
|
v.name = name;
|
||||||
|
v.volume = volume;
|
||||||
|
v.rate = rate;
|
||||||
|
|
||||||
beginInsertRows( QModelIndex(), voiceEngines.size(), voiceEngines.size() );
|
beginInsertRows( QModelIndex(), voiceEngines.size(), voiceEngines.size() );
|
||||||
voiceEngines.push_back( v );
|
voiceEngines.push_back( v );
|
||||||
|
@ -243,6 +306,15 @@ bool VoiceEnginesModel::setData( QModelIndex const & index, const QVariant & val
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoiceEnginesModel::setEngineParams( QModelIndex idx, int volume, int rate )
|
||||||
|
{
|
||||||
|
if ( idx.isValid() )
|
||||||
|
{
|
||||||
|
voiceEngines[ idx.row() ].volume = volume;
|
||||||
|
voiceEngines[ idx.row() ].rate = rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VoiceEngineEditor::VoiceEngineEditor( SpeechClient::Engines const & engines, QWidget * parent ):
|
VoiceEngineEditor::VoiceEngineEditor( SpeechClient::Engines const & engines, QWidget * parent ):
|
||||||
QComboBox( parent )
|
QComboBox( parent )
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,10 +29,12 @@ public:
|
||||||
VoiceEnginesModel( QWidget * parent, Config::VoiceEngines const & voiceEngines );
|
VoiceEnginesModel( QWidget * parent, Config::VoiceEngines const & voiceEngines );
|
||||||
|
|
||||||
void removeVoiceEngine( int index );
|
void removeVoiceEngine( int index );
|
||||||
void addNewVoiceEngine( QString const & id, QString const & name );
|
void addNewVoiceEngine( QString const & id, QString const & name,
|
||||||
|
int volume, int rate );
|
||||||
|
|
||||||
Config::VoiceEngines const & getCurrentVoiceEngines() const
|
Config::VoiceEngines const & getCurrentVoiceEngines() const
|
||||||
{ return voiceEngines; }
|
{ return voiceEngines; }
|
||||||
|
void setEngineParams( QModelIndex idx, int volume, int rate );
|
||||||
|
|
||||||
QModelIndex index( int row, int column, QModelIndex const & parent ) const;
|
QModelIndex index( int row, int column, QModelIndex const & parent ) const;
|
||||||
QModelIndex parent( QModelIndex const & parent ) const;
|
QModelIndex parent( QModelIndex const & parent ) const;
|
||||||
|
@ -94,12 +96,15 @@ private slots:
|
||||||
void on_removeVoiceEngine_clicked();
|
void on_removeVoiceEngine_clicked();
|
||||||
void on_previewVoice_clicked();
|
void on_previewVoice_clicked();
|
||||||
void previewVoiceFinished();
|
void previewVoiceFinished();
|
||||||
|
void slidersChanged();
|
||||||
|
void selectionChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::TextToSpeechSource ui;
|
Ui::TextToSpeechSource ui;
|
||||||
VoiceEnginesModel voiceEnginesModel;
|
VoiceEnginesModel voiceEnginesModel;
|
||||||
|
|
||||||
void fitSelectedVoiceEnginesColumns();
|
void fitSelectedVoiceEnginesColumns();
|
||||||
|
void adjustSliders();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __TEXTTOSPEECHSOURCE_HH_INCLUDED__
|
#endif // __TEXTTOSPEECHSOURCE_HH_INCLUDED__
|
||||||
|
|
|
@ -78,6 +78,73 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Preferences</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Volume:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="volumeSlider">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="sliderPosition">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="tracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::TicksAbove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickInterval">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rate:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="rateSlider">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="sliderPosition">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="tracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::TicksAbove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickInterval">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
Loading…
Reference in a new issue