Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSoundEffect() Play a .wav on Rasperry pi: I hear nothing. (sound generator example does work)



  • Hi All,

    I'm trying to play a wav file on a rasperry pi. I can't get it to work, I hear nothing. The same program works on windows 10.

    I've also tried the example program "oudio output". This works, i do hear a beep, when I select "default:CARD=ALSA".

    What did I miss?
    Cheers,
    Cedric

    Here's my program:
    soundloop.h

    #ifndef SOUNDLOOP_H
    #define SOUNDLOOP_H
    
    #include <QObject>
    
    #include <QAudioDeviceInfo> //needs QT += multimedia in the .pro file
    #include <QSoundEffect>
    
    class SoundLoop : public QObject
    {
        Q_OBJECT //marker for moc
    public:
        SoundLoop();
    public slots:
        void slotStart(void);
        void slotLastLoop(void);
    signals:
    private:
        QString getFilenameFromSettings(void);
        void getAudioDeviceFromSettings(void);
    };
    
    #endif // SOUNDLOOP_H
    

    soundloop.cpp

    #include "soundloop.h"
    #include <QSettings>
    #include <QDir>
    #include <QDebug>
    
    
    
    QSoundEffect *myEffect;
    QAudioDeviceInfo *myDevice;
    
    
    #define KEY_FILENAME "filename"
    #define DEFAULT_FILENAME "sound.wav"
    #define KEY_AUDIODEVICE "audiodevice"
    #define DEFAULT_AUDIODEVICE "non_existing_audiocard_name" //is replaced to be the default audio device
    
    SoundLoop::SoundLoop()
    {
        qDebug()<<Q_FUNC_INFO;
    
        QString filename;
        filename = getFilenameFromSettings();
        QFile file;
        if (file.exists(filename))
        {
            qDebug()<<"loading " <<filename;
        }
        else
        {
            qDebug()<< filename << " not found";
        }
        myDevice = new QAudioDeviceInfo();
    
        getAudioDeviceFromSettings(); //updates *myDevice
        myEffect = new QSoundEffect();
        myEffect->setSource(QUrl::fromLocalFile(filename));
        myEffect->setLoopCount(QSoundEffect::Infinite);
        myEffect->setVolume(1.00f);
        myEffect->play();
        qDebug()<<myEffect->isPlaying();
    }
    
    void SoundLoop::slotStart()
    {
        qDebug()<<Q_FUNC_INFO;
        if (myEffect)
        {
            myEffect->play();
        }
        else
        {
            qDebug()<<"no sound loaded";
        }
    }
    
    void SoundLoop::slotLastLoop()
    {
        qDebug()<<Q_FUNC_INFO;
        if (myEffect)
        {
            myEffect->setLoopCount(1);
        }
        else
        {
            qDebug()<<"no sound loaded";
        }
    }
    
    QString SoundLoop::getFilenameFromSettings()
    {
        QSettings * settings = new QSettings;
        QString filename;
        settings->beginGroup("Soundloop");
        if (settings->contains(KEY_FILENAME))
        {
            filename=settings->value(KEY_FILENAME,DEFAULT_FILENAME).toString();
        }
        else
        {
            filename=QDir::homePath();
            filename.append("/");
            filename.append(DEFAULT_FILENAME);
            settings->setValue(KEY_FILENAME,filename);
        }
        settings->endGroup();
        delete settings;
        return filename;
    }
    
    void SoundLoop::getAudioDeviceFromSettings()
    {
        QAudioDeviceInfo deviceinfos;
        QList<QAudioDeviceInfo> devicelist = deviceinfos.availableDevices(QAudio::AudioOutput);
        QStringList list;
        qDebug()<<"Available sound devices:";
        for (int i=0;i<devicelist.size();i++)
        {
            list.append(devicelist.at(i).deviceName());
            qDebug()<<devicelist.at(i).deviceName();
        }
    
        QSettings * settings = new QSettings;
        QString nameinsettings;
        settings->beginGroup("Soundloop");
        if (settings->contains(KEY_AUDIODEVICE))
        {
            nameinsettings=settings->value(KEY_AUDIODEVICE,DEFAULT_AUDIODEVICE).toString();
            int index = list.indexOf(nameinsettings);
            if (index == -1) //sound card not found in settings
            {
                qDebug()<<"soundcard from settings: "<<nameinsettings<<" not found, choosing default soundcard";
                *myDevice = QAudioDeviceInfo::defaultOutputDevice();
                settings->setValue(KEY_AUDIODEVICE,myDevice->deviceName());
            }
            else
            {
                qDebug()<<"soundcard from settings: "<<nameinsettings<<"found";
                *myDevice = devicelist.at(index);
            }
        }
        else
        {
            qDebug()<<"no soundcard specified in settings, choosing default soundcard";
            *myDevice = QAudioDeviceInfo::defaultOutputDevice();
            settings->setValue(KEY_AUDIODEVICE,myDevice->deviceName());
        }
        qDebug()<<"using soundcard: " << myDevice->deviceName();
    }
    

    And the output of my program:

    Debugging starts
    [..]
    SoundLoop::SoundLoop()
    loading  "/home/pi/untitled.wav"
    PulseAudioService: pa_context_connect() failed
    Available sound devices:
    "default"
    "default:CARD=ALSA"
    "sysdefault:CARD=ALSA"
    "dmix:CARD=ALSA,DEV=0"
    "dmix:CARD=ALSA,DEV=1"
    "dmix:CARD=ALSA,DEV=2"
    "dsnoop:CARD=ALSA,DEV=0"
    "dsnoop:CARD=ALSA,DEV=1"
    "dsnoop:CARD=ALSA,DEV=2"
    "hw:CARD=ALSA,DEV=0"
    "hw:CARD=ALSA,DEV=1"
    "hw:CARD=ALSA,DEV=2"
    "plughw:CARD=ALSA,DEV=0"
    "plughw:CARD=ALSA,DEV=1"
    "plughw:CARD=ALSA,DEV=2"
    ""
    soundcard from settings:  "default:CARD=ALSA" found
    using soundcard:  "default:CARD=ALSA"
    PulseAudioService: pa_context_connect() failed
    true
    [..]
    

    Here's the working example program:
    audiooutput.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #include <QAudioDeviceInfo>
    #include <QAudioOutput>
    #include <QDebug>
    #include <QVBoxLayout>
    #include <qmath.h>
    #include <qendian.h>
    
    #include "audiooutput.h"
    
    #define PUSH_MODE_LABEL "Enable push mode"
    #define PULL_MODE_LABEL "Enable pull mode"
    #define SUSPEND_LABEL   "Suspend playback"
    #define RESUME_LABEL    "Resume playback"
    #define VOLUME_LABEL    "Volume:"
    
    const int DurationSeconds = 1;
    const int ToneSampleRateHz = 600;
    const int DataSampleRateHz = 44100;
    const int BufferSize      = 32768;
    
    
    Generator::Generator(const QAudioFormat &format,
                         qint64 durationUs,
                         int sampleRate,
                         QObject *parent)
        :   QIODevice(parent)
        ,   m_pos(0)
    {
        if (format.isValid())
            generateData(format, durationUs, sampleRate);
    }
    
    Generator::~Generator()
    {
    
    }
    
    void Generator::start()
    {
        open(QIODevice::ReadOnly);
    }
    
    void Generator::stop()
    {
        m_pos = 0;
        close();
    }
    
    void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate)
    {
        const int channelBytes = format.sampleSize() / 8;
        const int sampleBytes = format.channelCount() * channelBytes;
    
        qint64 length = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8))
                            * durationUs / 100000;
    
        Q_ASSERT(length % sampleBytes == 0);
        Q_UNUSED(sampleBytes) // suppress warning in release builds
    
        m_buffer.resize(length);
        unsigned char *ptr = reinterpret_cast<unsigned char *>(m_buffer.data());
        int sampleIndex = 0;
    
        while (length) {
            const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex % format.sampleRate()) / format.sampleRate());
            for (int i=0; i<format.channelCount(); ++i) {
                if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
                    const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
                    *reinterpret_cast<quint8*>(ptr) = value;
                } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
                    const qint8 value = static_cast<qint8>(x * 127);
                    *reinterpret_cast<quint8*>(ptr) = value;
                } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
                    quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
                    if (format.byteOrder() == QAudioFormat::LittleEndian)
                        qToLittleEndian<quint16>(value, ptr);
                    else
                        qToBigEndian<quint16>(value, ptr);
                } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
                    qint16 value = static_cast<qint16>(x * 32767);
                    if (format.byteOrder() == QAudioFormat::LittleEndian)
                        qToLittleEndian<qint16>(value, ptr);
                    else
                        qToBigEndian<qint16>(value, ptr);
                }
    
                ptr += channelBytes;
                length -= channelBytes;
            }
            ++sampleIndex;
        }
    }
    
    qint64 Generator::readData(char *data, qint64 len)
    {
        qint64 total = 0;
        if (!m_buffer.isEmpty()) {
            while (len - total > 0) {
                const qint64 chunk = qMin((m_buffer.size() - m_pos), len - total);
                memcpy(data + total, m_buffer.constData() + m_pos, chunk);
                m_pos = (m_pos + chunk) % m_buffer.size();
                total += chunk;
            }
        }
        return total;
    }
    
    qint64 Generator::writeData(const char *data, qint64 len)
    {
        Q_UNUSED(data);
        Q_UNUSED(len);
    
        return 0;
    }
    
    qint64 Generator::bytesAvailable() const
    {
        return m_buffer.size() + QIODevice::bytesAvailable();
    }
    
    AudioTest::AudioTest()
        :   m_pushTimer(new QTimer(this))
        ,   m_modeButton(0)
        ,   m_suspendResumeButton(0)
        ,   m_deviceBox(0)
        ,   m_device(QAudioDeviceInfo::defaultOutputDevice())
        ,   m_generator(0)
        ,   m_audioOutput(0)
        ,   m_output(0)
        ,   m_pullMode(true)
        ,   m_buffer(BufferSize, 0)
    {
        initializeWindow();
        initializeAudio();
    }
    
    void AudioTest::initializeWindow()
    {
        QScopedPointer<QWidget> window(new QWidget);
        QScopedPointer<QVBoxLayout> layout(new QVBoxLayout);
    
        m_deviceBox = new QComboBox(this);
        const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultOutputDevice();
        m_deviceBox->addItem(defaultDeviceInfo.deviceName(), qVariantFromValue(defaultDeviceInfo));
        foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
            if (deviceInfo != defaultDeviceInfo)
                m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo));
        }
        connect(m_deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
        layout->addWidget(m_deviceBox);
    
        m_modeButton = new QPushButton(this);
        m_modeButton->setText(tr(PUSH_MODE_LABEL));
        connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode()));
        layout->addWidget(m_modeButton);
    
        m_suspendResumeButton = new QPushButton(this);
        m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
        connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume()));
        layout->addWidget(m_suspendResumeButton);
    
        QHBoxLayout *volumeBox = new QHBoxLayout;
        m_volumeLabel = new QLabel;
        m_volumeLabel->setText(tr(VOLUME_LABEL));
        m_volumeSlider = new QSlider(Qt::Horizontal);
        m_volumeSlider->setMinimum(0);
        m_volumeSlider->setMaximum(100);
        m_volumeSlider->setSingleStep(10);
        connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
        volumeBox->addWidget(m_volumeLabel);
        volumeBox->addWidget(m_volumeSlider);
        layout->addLayout(volumeBox);
    
        window->setLayout(layout.data());
        layout.take(); // ownership transferred
    
        setCentralWidget(window.data());
        QWidget *const windowPtr = window.take(); // ownership transferred
        windowPtr->show();
    }
    
    void AudioTest::initializeAudio()
    {
        connect(m_pushTimer, SIGNAL(timeout()), SLOT(pushTimerExpired()));
    
        m_format.setSampleRate(DataSampleRateHz);
        m_format.setChannelCount(1);
        m_format.setSampleSize(16);
        m_format.setCodec("audio/pcm");
        m_format.setByteOrder(QAudioFormat::LittleEndian);
        m_format.setSampleType(QAudioFormat::SignedInt);
    
        QAudioDeviceInfo info(m_device);
        if (!info.isFormatSupported(m_format)) {
            qWarning() << "Default format not supported - trying to use nearest";
            m_format = info.nearestFormat(m_format);
        }
    
        if (m_generator)
            delete m_generator;
        m_generator = new Generator(m_format, DurationSeconds*1000000, ToneSampleRateHz, this);
    
        createAudioOutput();
    }
    
    void AudioTest::createAudioOutput()
    {
        delete m_audioOutput;
        m_audioOutput = 0;
        m_audioOutput = new QAudioOutput(m_device, m_format, this);
        m_generator->start();
        m_audioOutput->start(m_generator);
        m_volumeSlider->setValue(int(m_audioOutput->volume()*100.0f));
    }
    
    AudioTest::~AudioTest()
    {
    
    }
    
    void AudioTest::deviceChanged(int index)
    {
        m_pushTimer->stop();
        m_generator->stop();
        m_audioOutput->stop();
        m_audioOutput->disconnect(this);
        m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>();
        initializeAudio();
    }
    
    void AudioTest::volumeChanged(int value)
    {
        if (m_audioOutput)
            m_audioOutput->setVolume(qreal(value/100.0f));
    }
    
    void AudioTest::pushTimerExpired()
    {
        if (m_audioOutput && m_audioOutput->state() != QAudio::StoppedState) {
            int chunks = m_audioOutput->bytesFree()/m_audioOutput->periodSize();
            while (chunks) {
               const qint64 len = m_generator->read(m_buffer.data(), m_audioOutput->periodSize());
               if (len)
                   m_output->write(m_buffer.data(), len);
               if (len != m_audioOutput->periodSize())
                   break;
               --chunks;
            }
        }
    }
    
    void AudioTest::toggleMode()
    {
    /*    m_pushTimer->stop();
        m_audioOutput->stop();*/
    
        mySound = new QSound("/home/pi/untitled.wav");
        mySound->setLoops(QSound::Infinite);
        mySound->play();
    
    
    /*
        if (m_pullMode) {
            //switch to push mode (periodically push to QAudioOutput using a timer)
            m_modeButton->setText(tr(PULL_MODE_LABEL));
            m_output = m_audioOutput->start();
            m_pullMode = false;
            m_pushTimer->start(20);
        } else {
            //switch to pull mode (QAudioOutput pulls from Generator as needed)
            m_modeButton->setText(tr(PUSH_MODE_LABEL));
            m_pullMode = true;
            m_audioOutput->start(m_generator);
        }
    */
        m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
    }
    
    void AudioTest::toggleSuspendResume()
    {
        if (m_audioOutput->state() == QAudio::SuspendedState) {
            m_audioOutput->resume();
            m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
        } else if (m_audioOutput->state() == QAudio::ActiveState) {
            m_audioOutput->suspend();
            m_suspendResumeButton->setText(tr(RESUME_LABEL));
        } else if (m_audioOutput->state() == QAudio::StoppedState) {
            m_audioOutput->resume();
            m_suspendResumeButton->setText(tr(SUSPEND_LABEL));
        } else if (m_audioOutput->state() == QAudio::IdleState) {
            // no-op
        }
    }
    
    

    audiooutput.h

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #ifndef AUDIOOUTPUT_H
    #define AUDIOOUTPUT_H
    
    #include <math.h>
    
    #include <QAudioOutput>
    #include <QByteArray>
    #include <QComboBox>
    #include <QIODevice>
    #include <QLabel>
    #include <QMainWindow>
    #include <QObject>
    #include <QPushButton>
    #include <QSlider>
    #include <QTimer>
    #include <QSound>
    
    class Generator : public QIODevice
    {
        Q_OBJECT
    
    public:
        Generator(const QAudioFormat &format, qint64 durationUs, int sampleRate, QObject *parent);
        ~Generator();
    
        void start();
        void stop();
    
        qint64 readData(char *data, qint64 maxlen);
        qint64 writeData(const char *data, qint64 len);
        qint64 bytesAvailable() const;
    
    private:
        void generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate);
    
    private:
        qint64 m_pos;
        QByteArray m_buffer;
    };
    
    class AudioTest : public QMainWindow
    {
        Q_OBJECT
    
    public:
        AudioTest();
        ~AudioTest();
    
    private:
        void initializeWindow();
        void initializeAudio();
        void createAudioOutput();
    
    private:
        QTimer *m_pushTimer;
        QSound *mySound;
        // Owned by layout
        QPushButton *m_modeButton;
        QPushButton *m_suspendResumeButton;
        QComboBox *m_deviceBox;
        QLabel *m_volumeLabel;
        QSlider *m_volumeSlider;
    
        QAudioDeviceInfo m_device;
        Generator *m_generator;
        QAudioOutput *m_audioOutput;
        QIODevice *m_output; // not owned
        QAudioFormat m_format;
    
        bool m_pullMode;
        QByteArray m_buffer;
    
    private slots:
        void pushTimerExpired();
        void toggleMode();
        void toggleSuspendResume();
        void deviceChanged(int index);
        void volumeChanged(int);
    };
    
    #endif // AUDIOOUTPUT_H
    
    

    output from the example program:

    Debugging starts
    libEGL warning: DRI2: failed to authenticate
    PulseAudioService: pa_context_connect() failed
    Default format not supported - trying to use nearest
    using null output device, none available
    

    Here are my versions:

    $ uname -a
    Linux raspberrypi 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux
    
    $ qtcreator -version
    libEGL warning: DRI2: failed to authenticate
    
    Qt Creator 4.2.0 based on Qt 5.7.1
    
      Android 4.2.0 Support for deployment to and execution on Android Devices.
      AutoTest 4.2.0 Auto Test plugin.
      AutotoolsProjectManager 4.2.0 Autotools project integration.
      BareMetal 4.2.0 This plugin adds a target for bare metal development.
      Bazaar 4.2.0 Bazaar integration.
      Beautifier 4.2.0 Format source files with the help of beautifiers like AStyle, uncrustify or clang-format.
      BinEditor 4.2.0 Binary editor component.
      Bookmarks 4.2.0 Bookmarks in text editors.
      CMakeProjectManager 4.2.0 CMake support.
      CVS 4.2.0 CVS integration.
      ClangStaticAnalyzer 4.2.0 ClangStaticAnalyzer Plugin.
      ClassView 4.2.0 Class View component.
      ClearCase 4.2.0 ClearCase integration.
      CodePaster 4.2.0 Codepaster plugin for pushing/fetching diff from server.
      Core 4.2.0 The core plugin for the Qt IDE.
      CppEditor 4.2.0 C/C++ editor component.
      CppTools 4.2.0 Tools for analyzing C/C++ code.
      Debugger 4.2.0 Debugger integration.
      Designer 4.2.0 Qt Designer integration.
      DiffEditor 4.2.0 Diff editor component.
      EmacsKeys 4.2.0 The main idea behind this plugin is to provide additional actions a typical emacs user would expect. It doesn't claim to provide full emacs emulation. The following actions are available:
     - Movement [C-f, C-b, C-n, C-p, M-f, M-b, C-a, C-e, M-<, M->]
     - Mark-based selection [C-SPC, C-x C-x]
     - Cut/copy/yank (doesn't provide kill ring feature) [M-w, C-w, C-y]
     - Kill actions, which interact properly with clipboard [C-k, M-d, C-d]
     - Scrolling (half of the screen, keeps cursor visible) [C-v, M-v]
     - Insert new line and indent [C-j]
    
    IMPORTANT: Actions are not bound to any key combinations by default. You can find them under 'EmacsKeys' section in keyboard shortcuts settings.
    
    Also it's worth mentioning that EmacsKeys plugin forces disabling of menu mnemonics by calling Qt's qt_set_sequence_auto_mnemonic function with false argument. Many of the english menu mnemonics get into the way of typical emacs keys, this includes: Alt+F (File), Alt+B (Build), Alt+W (Window). It's a temporary solution, it remains until there is a better one.
      FakeVim 4.2.0 VI-style keyboard navigation.
      GLSLEditor 4.2.0 Editor for GLSL.
      GenericProjectManager 4.2.0 Generic support.
      Git 4.2.0 Git integration.
      Help 4.2.0 Help system.
      ImageViewer 4.2.0 Image Viewer component.
      Ios 4.2.0 Support for deployment to and execution on iOS Devices.
      Macros 4.2.0 Macros in text editors.
      Mercurial 4.2.0 Mercurial integration.
      ModelEditor 4.2.0 Graphical modeling with structured diagrams.
      Nim 4.2.0 Plugin for supporting the Nim programming language.
      Perforce 4.2.0 Perforce integration.
      ProjectExplorer 4.2.0 ProjectExplorer framework that can be extended with different kind of project types.
      PythonEditor 4.2.0 Editor and file creation wizards for Python. Example plugin for QtCreator API demonstration.
      QbsProjectManager 4.2.0 QBS support.
      QmakeAndroidSupport 4.2.0 Android support for qmake project manager.
      QmakeProjectManager 4.2.0 Provides project type for Qt/QMake .pro files and tools.
      QmlDesigner 4.2.0 Visual Designer for QML files.
      QmlJSEditor 4.2.0 Editor for QML and JavaScript.
      QmlJSTools 4.2.0 Tools for analyzing Qml/JS code.
      QmlProfiler 4.2.0 Qml Profiler Plugin.
      QmlProjectManager 4.2.0 Qt Quick support
      Qnx 4.2.0 Adds support for QNX to Qt Creator.
      QtSupport 4.2.0 Provides support code for build systems.
      RemoteLinux 4.2.0 Support for deployment to and execution on a remote Linux host.
      ResourceEditor 4.2.0 Editor for qrc files.
      ScxmlEditor 4.2.0 Visual Editor for SCXML (State Chart XML) files.
      Subversion 4.2.0 Subversion integration.
      TaskList 4.2.0 Use .tasks-files to populate the Issues view.
      TextEditor 4.2.0 Text editor framework and the implementation of the basic text editor.
      Todo 4.2.0 Adds pane that lists all TODO, FIXME, etc. entries in comments.
      UpdateInfo 4.2.0 Displays Update-Infos for Qt Installer Framework-based Updaters.
      Valgrind 4.2.0 Valgrind Plugin.
      VcsBase 4.2.0 Version Control System Base Plugin.
      Welcome 4.2.0 Default Welcome Screen Plugin.
      WinRt 4.2.0 Helper for Windows Runtime projects.
    
    (C) 2016 The Qt Company Ltd
    
    

Log in to reply