QThreads & qml question

I’m building an audio synthesizer which needs to place audio playing in a thread that isn’t blocking the GUI. I was assuming I’d need to do something like have a worker and controller like the following. Does this work if the controller (Synthesizer) class is used like qmlRegisterType(“de.poetaster.sailsynth”, 1, 0, “Synthesizer”);

class Player : public QObject {
    Q_OBJECT
  public slots:
    void play() {
     SoundGenerator::play(m_g);
     result(true);
    }
  signals:
    void result(bool r);
};

class Synthesizer : public QObject {
    Q_OBJECT
  public:
    Synth() {
      w = new Player;
      t = new QThread;
      w->moveToThread(t);
      connect(this, SIGNAL(start()), w, SLOT(play()));
      connect(w, SIGNAL(result(bool)), this, SIGNAL(result(bool)));
      t->start();
    }
  private:
    Player * w;
    QThread * t;
  signals:
    void start();
    void result(bool r);
};

To answer my own question, yes it does work.

With a ‘thread worker’ like so

class Player : public QObject {
    Q_OBJECT
  public slots:
    void setGenerator(QString generator) {
        m_voiceDesc = generator;
    }
    void setDuration(long time) {
        m_duration  = time;
    }
    void play() {
        SoundGenerator::setVolume(0);   // Avoid sound clicks at start
        SoundGenerator::fade_in(10);
        SoundGenerator::setVolume(0.6);   // Avoid sound clicks at start
        // remove old instance first
        SoundGenerator::remove(mg);
        mg = SoundGenerator::factory(qPrintable(m_voiceDesc));
        SoundGenerator::play(mg);
        const int fade_time=10; //m_fadeIn;
        long duration = m_duration;
        if (duration > fade_time) {
                SDL_Delay(duration-fade_time); 
                SoundGenerator::fade_out(fade_time);
                SDL_Delay(fade_time);
        } else {
                SoundGenerator::fade_out(fade_time);
                SDL_Delay(fade_time); 
        }
        SDL_Delay(10); 
     result(true);
    }
  signals:
    void result(bool r);
  private:
    SoundGenerator*  mg;
    QString m_voiceDesc;
    long m_duration;
};

I can call the the Synthesizer class ‘play()’ from QML like so:

void Synthesizer::play(){
    w = new Player;
    w->setDuration(m_duration);
    w->setGenerator(m_voiceDesc);
    t = new QThread;
    w->moveToThread(t);
    connect(this, SIGNAL(start()), w, SLOT(play()));
    connect(w, SIGNAL(result(bool)), this, SIGNAL(result(bool)));
    this->start();
    t->start();
}

And the gui remains responsive. So far, so good.

4 Likes