GoldenDict 简单插件化「转」--- 适配macos(顺手解决了下macos的划词问题)

抽丝剥茧,由外及内 — 合久必分,分久必合 — 按需加载,资源不浪费,问题不易出

插件测试程序: GoldenDict_plugins_test.7z (19.8 MB)

内置fmodex插件、ffmpeg插件、bass插件、qtmediaplayer插件各一个,ocr插件两个,测试用mp3音频和图片文件文件各一个。
xmqg0-uyi4s

1. 插件公共接口

class GDCORE_EXPORT GDPObject : public QObject
{
    Q_OBJECT
public:
    explicit GDPObject(QObject *parent = nullptr) : QObject(parent), owner(nullptr)
    {}
    virtual ~GDPObject()
    {}

    virtual int type() const = 0; /*GDO_Type*/
    virtual QString name() const = 0;
    virtual QString author() const = 0;

    virtual bool init() = 0;

    int version() const;
    QString fileName() const;

    static QList<QPair<QString/*iid*/, QString/*path*/> > metaInfo(const QString &dir, const QString filter);
    static GDPObject* loadObject(const QString &file, QObject *parent = nullptr);

    void unload();/* owner deletelater */

signals:
  void error( const QString& );

private:
    class GDPObjOwner;
    GDPObjOwner *owner;
};

2. AudioPlayer公共接口

class GDPAudioPlayer : public GDPObject
{
public:
    explicit GDPAudioPlayer(QObject *parent = nullptr) : GDPObject(parent)
    {}
    virtual ~GDPAudioPlayer()
    {}


    int type() const {  return GDOT_AudioPlayer;  }

    /// Initialize audio device and playback environment
    //virtual bool init() = 0;
    /// Stops current playback if any, copies the audio buffer, then plays the duplication.
    /// Returns an error message in case of immediate failure; an empty string in case of success.
    virtual QString play( const QByteArray &audioBuffer ) = 0;
    virtual QString playFile( const QString &file ) = 0;
    /// Stops current playback if any.
    virtual void stop() = 0;

};
#define GDPAudioPlayer_iid "gdp.AudioPlayer"
Q_DECLARE_INTERFACE(GDPAudioPlayer, GDPAudioPlayer_iid)

AudioPlayer插件实例:

class QtMediaplayer : public GDPAudioPlayer
{
    Q_OBJECT
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    Q_PLUGIN_METADATA(IID "adp/Qt Multimedia")
    Q_INTERFACES(GDPAudioPlayer)
#endif
public:
    QtMediaplayer();
    ~QtMediaplayer();

    bool init() override;

    QString name() const {  return tr("Qt Multimedia");  }
    QString author() const {  return "GoldenDict Official";  }

    QString play( const QByteArray &_audioBuffer ) override;
    QString playFile( const QString &file ) override;
    void stop() override;

private slots:
  void onMediaPlayerError(QMediaPlayer::Error);

private:
    QMediaPlayer *player; ///< Depends on audioBuffer.
    QBuffer audioBuffer;

};
QtMediaplayer::QtMediaplayer() : GDPAudioPlayer(),
  player(0)
{
}

QtMediaplayer::~QtMediaplayer()
{
    if(player)
        delete player;
}

bool QtMediaplayer::init()
{
    player = new QMediaPlayer(nullptr, QMediaPlayer::StreamPlayback );
    connect( player, SIGNAL(error(QMediaPlayer::Error)),
             this, SLOT(onMediaPlayerError(QMediaPlayer::Error)) );
    return true;
}

QString QtMediaplayer::play(const QByteArray &_audioBuffer)
{
    if(player)
    {
        stop();
        audioBuffer.setData( _audioBuffer );
        if( !audioBuffer.open( QIODevice::ReadOnly ) )
            return tr( "Couldn't open audio buffer for reading." );

        player->setMedia( QMediaContent(), &audioBuffer );
        player->play();
    }
    return QString();
}

QString QtMediaplayer::playFile( const QString &file )
{
    if(player)
    {
        stop();
        player->setMedia( QMediaContent(QUrl::fromLocalFile(file)) );
        player->play();
    }
    return QString();
}

void QtMediaplayer::stop()
{
    if(player)
    {
        player->setMedia( QMediaContent() ); // Forget about audioBuffer.
        if(audioBuffer.isOpen()) {
            audioBuffer.close();
            audioBuffer.setData( QByteArray() ); // Free memory.
        }
    }
}

void QtMediaplayer::onMediaPlayerError(QMediaPlayer::Error err)
{
  QString errstr = player->errorString();
  if(errstr.isEmpty())
    errstr = tr("Error==%1").arg(err);
  emit error( errstr );
}

#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
Q_EXPORT_PLUGIN(QtMediaplayer)
#endif

3. OCR划词共接口

class GDPOcrText : public GDPObject
{
public:
    typedef QList<QPair<QString/*id*/, QString/*name*/> > OCR_LAN;
    typedef QMap<QString /*area*/, OCR_LAN > OCR_LANS;
public:
    explicit GDPOcrText(QObject *parent = nullptr) : GDPObject(parent)
    {}
    virtual ~GDPOcrText()
    {}

    int type() const {    return GDOT_OcrWords;    }

    virtual void enableLans(const QStringList &lans, const QString &area) = 0;
    virtual OCR_LANS getAreaLans() const = 0;
    virtual void setDataPath(const QString &datadir) = 0;
    virtual QString dataPath() const = 0;

    virtual void ocrScreen() = 0;
    virtual void ocrMemory(const QByteArray &bmpdata) = 0; /* bmp data */
    virtual void ocrFile(const QString &file) = 0;

    virtual bool isWorking() const = 0;
    virtual void stop() = 0;
};
#define GDPOcrObject_iid "gdp.OcrText"
Q_DECLARE_INTERFACE(GDPOcrText, GDPOcrObject_iid)
3 个赞

能更新一下Github上的源码吗,我在Linux下试一试