mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 19:24:08 +00:00
opt: pronounce audio rewrite (#922)
* opt: pronounce audio rewrite
* 🎨 apply clang-format changes
* fix:use javscript Map to hold the dictionary audio url
* Update mainwindow.cc
---------
Co-authored-by: xiaoyifang <xiaoyifang@users.noreply.github.com>
This commit is contained in:
parent
2b1d91638e
commit
2ed7990531
|
@ -369,6 +369,7 @@ HEADERS += \
|
|||
src/metadata.hh \
|
||||
src/multimediaaudioplayer.hh \
|
||||
src/parsecmdline.hh \
|
||||
src/pronounceengine.hh \
|
||||
src/resourceschemehandler.hh \
|
||||
src/splitfile.hh \
|
||||
src/termination.hh \
|
||||
|
@ -492,6 +493,7 @@ SOURCES += \
|
|||
src/metadata.cc \
|
||||
src/multimediaaudioplayer.cc \
|
||||
src/parsecmdline.cc \
|
||||
src/pronounceengine.cc \
|
||||
src/resourceschemehandler.cc \
|
||||
src/splitfile.cc \
|
||||
src/termination.cc \
|
||||
|
|
|
@ -2,13 +2,17 @@
|
|||
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
||||
|
||||
#include "audiolink.hh"
|
||||
#include "globalbroadcaster.hh"
|
||||
|
||||
std::string addAudioLink( std::string const & url,
|
||||
std::string const & dictionaryId )
|
||||
{
|
||||
return std::string( "<script type=\"text/javascript\">" +
|
||||
makeAudioLinkScript( url, dictionaryId ) +
|
||||
"</script>" );
|
||||
if ( url.empty() || url.length() < 2 )
|
||||
return {};
|
||||
GlobalBroadcaster::instance()->pronounce_engine.sendAudio(
|
||||
QString::fromStdString( url.substr( 1, url.length() - 2 ) ) );
|
||||
|
||||
return std::string( "<script type=\"text/javascript\">" + makeAudioLinkScript( url, dictionaryId ) + "</script>" );
|
||||
}
|
||||
|
||||
std::string makeAudioLinkScript( std::string const & url,
|
||||
|
@ -18,9 +22,7 @@ std::string makeAudioLinkScript( std::string const & url,
|
|||
|
||||
std::string ref;
|
||||
bool escaped = false;
|
||||
for( unsigned x = 0; x < url.size(); x++ )
|
||||
{
|
||||
char ch = url[ x ];
|
||||
for ( const char ch : url ) {
|
||||
if( escaped )
|
||||
{
|
||||
ref += ch;
|
||||
|
@ -33,7 +35,13 @@ std::string makeAudioLinkScript( std::string const & url,
|
|||
escaped = ( ch == '\\' );
|
||||
}
|
||||
|
||||
std::string audioLinkForDict = "gdAudioLinks['" + dictionaryId + "']";
|
||||
return "gdAudioLinks.first = gdAudioLinks.first || " + ref + ";" +
|
||||
audioLinkForDict + " = " + audioLinkForDict + " || " + ref + ";";
|
||||
const std::string audioLinkForDict = QString::fromStdString( R"(
|
||||
if(!gdAudioMap.has('%1')){
|
||||
gdAudioMap.set('%1',%2);
|
||||
}
|
||||
)" ).arg(
|
||||
QString::fromStdString( dictionaryId ),
|
||||
QString::fromStdString( url ) ).toStdString();
|
||||
return "gdAudioLinks.first = gdAudioLinks.first || " + ref + ";" +
|
||||
audioLinkForDict ;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QObject>
|
||||
#include <vector>
|
||||
#include "config.hh"
|
||||
#include "pronounceengine.hh"
|
||||
|
||||
struct ActiveDictIds
|
||||
{
|
||||
|
@ -17,10 +18,11 @@ struct ActiveDictIds
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class GlobalBroadcaster : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
Config::Preferences * preference;
|
||||
QSet<QString> whitelist;
|
||||
|
||||
|
@ -37,7 +39,7 @@ public:
|
|||
QSet< QString > collapsedDicts;
|
||||
QMap< QString, QSet< QString > > folderFavoritesMap;
|
||||
QMap< unsigned, QString > groupFolderMap;
|
||||
|
||||
PronounceEngine pronounce_engine;
|
||||
|
||||
signals:
|
||||
void dictionaryChanges( ActiveDictIds ad );
|
||||
|
|
22
src/pronounceengine.cc
Normal file
22
src/pronounceengine.cc
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "pronounceengine.hh"
|
||||
|
||||
PronounceEngine::PronounceEngine( QObject * parent ):
|
||||
QObject{ parent }
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PronounceEngine::reset()
|
||||
{
|
||||
QMutexLocker _( &mutex );
|
||||
state = PronounceState::AVAILABLE;
|
||||
}
|
||||
|
||||
void PronounceEngine::sendAudio( QString audioLink )
|
||||
{
|
||||
QMutexLocker _( &mutex );
|
||||
if ( state == PronounceState::OCCUPIED )
|
||||
return;
|
||||
state = PronounceState::OCCUPIED;
|
||||
emit emitAudio( audioLink );
|
||||
}
|
29
src/pronounceengine.hh
Normal file
29
src/pronounceengine.hh
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef PRONOUNCEENGINE_HH
|
||||
#define PRONOUNCEENGINE_HH
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutexLocker>
|
||||
#include <QMutex>
|
||||
|
||||
|
||||
enum class PronounceState {
|
||||
AVAILABLE,
|
||||
OCCUPIED
|
||||
};
|
||||
|
||||
class PronounceEngine: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
PronounceState state = PronounceState::AVAILABLE;
|
||||
QMutex mutex;
|
||||
|
||||
public:
|
||||
explicit PronounceEngine( QObject * parent = nullptr );
|
||||
void reset();
|
||||
void sendAudio( QString audioLink );
|
||||
|
||||
signals:
|
||||
void emitAudio( QString audioLink );
|
||||
};
|
||||
|
||||
#endif // PRONOUNCEENGINE_HH
|
|
@ -4,6 +4,9 @@ var gdAudioLinks = {
|
|||
"current": null
|
||||
};
|
||||
|
||||
//store dictionary audio link.
|
||||
var gdAudioMap= new Map();
|
||||
|
||||
function gdMakeArticleActive(newId,noEvent) {
|
||||
var gdCurrentArticle = $_$(".gdactivearticle").attr("id")
|
||||
if (gdCurrentArticle !== 'gdfrom-' + newId) {
|
||||
|
|
|
@ -294,6 +294,7 @@ void ArticleView::showDefinition( QString const & word, unsigned group,
|
|||
QString const & scrollTo,
|
||||
Contexts const & contexts_ )
|
||||
{
|
||||
GlobalBroadcaster::instance()->pronounce_engine.reset();
|
||||
currentWord = word.trimmed();
|
||||
if( currentWord.isEmpty() )
|
||||
return;
|
||||
|
@ -1479,7 +1480,7 @@ void ArticleView::reload() { webview->reload(); }
|
|||
|
||||
void ArticleView::hasSound( const std::function< void( bool ) > & callback )
|
||||
{
|
||||
webview->page()->runJavaScript( "if(typeof(gdAudioLinks)!=\"undefined\") gdAudioLinks.first",
|
||||
webview->page()->runJavaScript( R"(if(typeof(gdAudioLinks)!="undefined") gdAudioLinks.first)",
|
||||
[ callback ]( const QVariant & v ) {
|
||||
bool has = false;
|
||||
if( v.type() == QVariant::String )
|
||||
|
@ -1491,11 +1492,11 @@ void ArticleView::hasSound( const std::function< void( bool ) > & callback )
|
|||
//use webengine javascript to playsound
|
||||
void ArticleView::playSound()
|
||||
{
|
||||
QString variable = " (function(){ var link=gdAudioLinks[gdAudioLinks.current]; "
|
||||
" if(link==undefined){ "
|
||||
" link=gdAudioLinks.first; "
|
||||
" } "
|
||||
" return link;})(); ";
|
||||
QString variable = R"( (function(){ var link=gdAudioMap.get(gdAudioLinks.current);
|
||||
if(link==undefined){
|
||||
link=gdAudioLinks.first;
|
||||
}
|
||||
return link;})(); )";
|
||||
|
||||
webview->page()->runJavaScript( variable, [ this ]( const QVariant & result ) {
|
||||
if( result.type() == QVariant::String ) {
|
||||
|
|
|
@ -685,6 +685,15 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
|||
this,
|
||||
&MainWindow::showFTSIndexingName );
|
||||
|
||||
connect( &GlobalBroadcaster::instance()->pronounce_engine,
|
||||
&PronounceEngine::emitAudio,
|
||||
this,
|
||||
[ this ]( auto audioUrl ) {
|
||||
auto view = getCurrentArticleView();
|
||||
if ( cfg.preferences.pronounceOnLoadMain && view != nullptr ) {
|
||||
view->openLink( QUrl::fromEncoded( audioUrl.toUtf8() ), {} );
|
||||
}
|
||||
} );
|
||||
applyProxySettings();
|
||||
|
||||
//set webengineview font
|
||||
|
@ -1915,12 +1924,7 @@ void MainWindow::pageLoaded( ArticleView * view )
|
|||
return; // It was background action
|
||||
|
||||
updateBackForwardButtons();
|
||||
|
||||
updatePronounceAvailability();
|
||||
|
||||
if ( cfg.preferences.pronounceOnLoadMain && view != nullptr ) {
|
||||
view->playSound();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showStatusBarMessage( QString const & message, int timeout, QPixmap const & icon )
|
||||
|
|
Loading…
Reference in a new issue