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:
xiaoyifang 2023-07-13 14:49:41 +08:00 committed by GitHub
parent 2b1d91638e
commit 2ed7990531
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 93 additions and 22 deletions

View file

@ -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 \

View file

@ -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 ;
}

View file

@ -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
View 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
View 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

View file

@ -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) {

View file

@ -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 ) {

View file

@ -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 )