diff options
Diffstat (limited to 'examples/multimedia/audiorecorder')
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.cpp | 319 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.h | 85 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.pro | 26 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.ui | 261 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder_small.ui | 266 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/doc/images/audiorecorder.png | bin | 0 -> 28212 bytes | |||
-rw-r--r-- | examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc | 104 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/main.cpp | 53 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/qaudiolevel.cpp | 68 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/qaudiolevel.h | 62 |
10 files changed, 1244 insertions, 0 deletions
diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp new file mode 100644 index 000000000..6c65f2e1d --- /dev/null +++ b/examples/multimedia/audiorecorder/audiorecorder.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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 <QAudioProbe> +#include <QAudioRecorder> +#include <QDir> +#include <QFileDialog> +#include <QMediaRecorder> + +#include "audiorecorder.h" + +#if defined(Q_WS_MAEMO_6) +#include "ui_audiorecorder_small.h" +#else +#include "ui_audiorecorder.h" +#endif + +static qreal getPeakValue(const QAudioFormat &format); +static qreal getBufferLevel(const QAudioBuffer &buffer); + +template <class T> +static qreal getBufferLevel(const T *buffer, int samples); + +AudioRecorder::AudioRecorder(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::AudioRecorder), + outputLocationSet(false) +{ + ui->setupUi(this); + + audioRecorder = new QAudioRecorder(this); + probe = new QAudioProbe; + connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)), this, SLOT(processBuffer(QAudioBuffer))); + probe->setSource(audioRecorder); + + //audio devices + ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString())); + foreach (const QString &device, audioRecorder->audioInputs()) { + ui->audioDeviceBox->addItem(device, QVariant(device)); + } + + //audio codecs + ui->audioCodecBox->addItem(tr("Default"), QVariant(QString())); + foreach (const QString &codecName, audioRecorder->supportedAudioCodecs()) { + ui->audioCodecBox->addItem(codecName, QVariant(codecName)); + } + + //containers + ui->containerBox->addItem(tr("Default"), QVariant(QString())); + foreach (const QString &containerName, audioRecorder->supportedContainers()) { + ui->containerBox->addItem(containerName, QVariant(containerName)); + } + + //sample rate: + ui->sampleRateBox->addItem(tr("Default"), QVariant(0)); + foreach (int sampleRate, audioRecorder->supportedAudioSampleRates()) { + ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant( + sampleRate)); + } + + ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality)); + ui->qualitySlider->setValue(int(QMultimedia::NormalQuality)); + + //bitrates: + ui->bitrateBox->addItem(QString("Default"), QVariant(0)); + ui->bitrateBox->addItem(QString("32000"), QVariant(32000)); + ui->bitrateBox->addItem(QString("64000"), QVariant(64000)); + ui->bitrateBox->addItem(QString("96000"), QVariant(96000)); + ui->bitrateBox->addItem(QString("128000"), QVariant(128000)); + + connect(audioRecorder, SIGNAL(durationChanged(qint64)), this, + SLOT(updateProgress(qint64))); + connect(audioRecorder, SIGNAL(stateChanged(QMediaRecorder::State)), this, + SLOT(updateState(QMediaRecorder::State))); + connect(audioRecorder, SIGNAL(error(QMediaRecorder::Error)), this, + SLOT(displayErrorMessage())); +} + +AudioRecorder::~AudioRecorder() +{ + delete audioRecorder; + delete probe; +} + +void AudioRecorder::updateProgress(qint64 duration) +{ + if (audioRecorder->error() != QMediaRecorder::NoError || duration < 2000) + return; + + ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000)); +} + +void AudioRecorder::updateState(QMediaRecorder::State state) +{ + QString statusMessage; + + switch (state) { + case QMediaRecorder::RecordingState: + ui->recordButton->setText(tr("Stop")); + ui->pauseButton->setText(tr("Pause")); + if (audioRecorder->outputLocation().isEmpty()) + statusMessage = tr("Recording"); + else + statusMessage = tr("Recording to %1").arg( + audioRecorder->outputLocation().toString()); + break; + case QMediaRecorder::PausedState: + ui->recordButton->setText(tr("Stop")); + ui->pauseButton->setText(tr("Resume")); + statusMessage = tr("Paused"); + break; + case QMediaRecorder::StoppedState: + ui->recordButton->setText(tr("Record")); + ui->pauseButton->setText(tr("Pause")); + statusMessage = tr("Stopped"); + } + + ui->pauseButton->setEnabled(state != QMediaRecorder::StoppedState); + + if (audioRecorder->error() == QMediaRecorder::NoError) + ui->statusbar->showMessage(statusMessage); +} + +static QVariant boxValue(const QComboBox *box) +{ + int idx = box->currentIndex(); + if (idx == -1) + return QVariant(); + + return box->itemData(idx); +} + +void AudioRecorder::toggleRecord() +{ + if (audioRecorder->state() == QMediaRecorder::StoppedState) { + audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString()); + + if (!outputLocationSet) + audioRecorder->setOutputLocation(generateAudioFilePath()); + + QAudioEncoderSettings settings; + settings.setCodec(boxValue(ui->audioCodecBox).toString()); + settings.setSampleRate(boxValue(ui->sampleRateBox).toInt()); + settings.setBitRate(boxValue(ui->bitrateBox).toInt()); + settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value())); + settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ? + QMultimedia::ConstantQualityEncoding : + QMultimedia::ConstantBitRateEncoding); + + QString container = boxValue(ui->containerBox).toString(); + + audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container); + audioRecorder->record(); + } + else { + audioRecorder->stop(); + } +} + +void AudioRecorder::togglePause() +{ + if (audioRecorder->state() != QMediaRecorder::PausedState) + audioRecorder->pause(); + else + audioRecorder->record(); +} + +void AudioRecorder::setOutputLocation() +{ + QString fileName = QFileDialog::getSaveFileName(); + audioRecorder->setOutputLocation(QUrl(fileName)); + outputLocationSet = true; +} + +void AudioRecorder::displayErrorMessage() +{ + ui->statusbar->showMessage(audioRecorder->errorString()); +} + +QUrl AudioRecorder::generateAudioFilePath() +{ + QDir outputDir(QDir::rootPath()); + + int lastImage = 0; + int fileCount = 0; + foreach (const QString &fileName, outputDir.entryList(QStringList(QString("testclip_*")))) { + int imgNumber = fileName.mid(5, fileName.size() - 9).toInt(); + lastImage = qMax(lastImage, imgNumber); + if (outputDir.exists(fileName)) + fileCount += 1; + } + lastImage += fileCount; + QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath() + + QString("/testclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0')))); + return location; +} + +// This function returns the maximum possible sample value for a given audio format +qreal getPeakValue(const QAudioFormat& format) +{ + // Note: Only the most common sample formats are supported + if (!format.isValid()) + return 0.0; + + if (format.codec() != "audio/pcm") + return 0.0; + + switch (format.sampleType()) { + case QAudioFormat::Unknown: + break; + case QAudioFormat::Float: + if (format.sampleSize() != 32) // other sample formats are not supported + return 0.0; + return 1.00003; + case QAudioFormat::SignedInt: + if (format.sampleSize() == 32) + return 2147483648.0; + if (format.sampleSize() == 16) + return 32768.0; + if (format.sampleSize() == 8) + return 128.0; + break; + case QAudioFormat::UnSignedInt: + // Unsigned formats are not supported in this example + break; + } + + return 0.0; +} + +qreal getBufferLevel(const QAudioBuffer& buffer) +{ + if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian) + return 0.0; + + if (buffer.format().codec() != "audio/pcm") + return 0.0; + + qreal peak_value = getPeakValue(buffer.format()); + if (qFuzzyCompare(peak_value, 0.0)) + return 0.0; + + switch (buffer.format().sampleType()) { + case QAudioFormat::Unknown: + case QAudioFormat::UnSignedInt: + break; + case QAudioFormat::Float: + if (buffer.format().sampleSize() == 32) + return getBufferLevel(buffer.constData<float>(), buffer.sampleCount()) / peak_value; + break; + case QAudioFormat::SignedInt: + if (buffer.format().sampleSize() == 32) + return getBufferLevel(buffer.constData<long int>(), buffer.sampleCount()) / peak_value; + if (buffer.format().sampleSize() == 16) + return getBufferLevel(buffer.constData<short int>(), buffer.sampleCount()) / peak_value; + if (buffer.format().sampleSize() == 8) + return getBufferLevel(buffer.constData<signed char>(), buffer.sampleCount()) / peak_value; + break; + } + + return 0.0; +} + +template <class T> +qreal getBufferLevel(const T *buffer, int samples) +{ + qreal max_value = 0.0; + + for (int i = 0; i < samples; ++i) { + qreal value = qAbs(qreal(buffer[i])); + if (value > max_value) + max_value = value; + } + + return max_value; +} + +void AudioRecorder::processBuffer(const QAudioBuffer& buffer) +{ + qreal level = getBufferLevel(buffer); + ui->audioLevel->setLevel(level); +} diff --git a/examples/multimedia/audiorecorder/audiorecorder.h b/examples/multimedia/audiorecorder/audiorecorder.h new file mode 100644 index 000000000..a58daf5f7 --- /dev/null +++ b/examples/multimedia/audiorecorder/audiorecorder.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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 AUDIORECORDER_H +#define AUDIORECORDER_H + +#include <QMainWindow> +#include <QMediaRecorder> +#include <QUrl> + +QT_BEGIN_NAMESPACE +namespace Ui { class AudioRecorder; } +class QAudioRecorder; +class QAudioProbe; +class QAudioBuffer; +QT_END_NAMESPACE + +class AudioRecorder : public QMainWindow +{ + Q_OBJECT + +public: + AudioRecorder(QWidget *parent = 0); + ~AudioRecorder(); + +public slots: + void processBuffer(const QAudioBuffer&); + +private slots: + void setOutputLocation(); + void togglePause(); + void toggleRecord(); + + void updateState(QMediaRecorder::State); + void updateProgress(qint64 pos); + void displayErrorMessage(); + QUrl generateAudioFilePath(); + +private: + Ui::AudioRecorder *ui; + + QAudioRecorder *audioRecorder; + QAudioProbe *probe; + bool outputLocationSet; + +}; + +#endif // AUDIORECORDER_H diff --git a/examples/multimedia/audiorecorder/audiorecorder.pro b/examples/multimedia/audiorecorder/audiorecorder.pro new file mode 100644 index 000000000..6fdc4b13d --- /dev/null +++ b/examples/multimedia/audiorecorder/audiorecorder.pro @@ -0,0 +1,26 @@ +TEMPLATE = app +TARGET = audiorecorder + +QT += multimedia + +win32:INCLUDEPATH += $$PWD + +HEADERS = \ + audiorecorder.h \ + qaudiolevel.h + +SOURCES = \ + main.cpp \ + audiorecorder.cpp \ + qaudiolevel.cpp + +maemo*: { + FORMS += audiorecorder_small.ui +}else { + FORMS += audiorecorder.ui +} + +target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audiorecorder +INSTALLS += target + +QT+=widgets diff --git a/examples/multimedia/audiorecorder/audiorecorder.ui b/examples/multimedia/audiorecorder/audiorecorder.ui new file mode 100644 index 000000000..ff6c2d935 --- /dev/null +++ b/examples/multimedia/audiorecorder/audiorecorder.ui @@ -0,0 +1,261 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AudioRecorder</class> + <widget class="QMainWindow" name="AudioRecorder"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>297</width> + <height>374</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0" colspan="3"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Input Device:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="audioDeviceBox"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Audio Codec:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="audioCodecBox"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>File Container:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="containerBox"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Sample rate:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="sampleRateBox"/> + </item> + </layout> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Encoding Mode:</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QRadioButton" name="constantQualityRadioButton"> + <property name="text"> + <string>Constant Quality:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="qualitySlider"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QRadioButton" name="constantBitrateRadioButton"> + <property name="text"> + <string>Constant Bitrate:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="bitrateBox"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QPushButton" name="outputButton"> + <property name="text"> + <string>Output...</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="recordButton"> + <property name="text"> + <string>Record</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="pauseButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Pause</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="levelLabel"> + <property name="text"> + <string>Audio Level:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="-1"> + <widget class="QAudioLevel" name="audioLevel"> + </widget> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <resources/> + <connections> + <connection> + <sender>constantQualityRadioButton</sender> + <signal>toggled(bool)</signal> + <receiver>qualitySlider</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>113</x> + <y>197</y> + </hint> + <hint type="destinationlabel"> + <x>115</x> + <y>223</y> + </hint> + </hints> + </connection> + <connection> + <sender>constantBitrateRadioButton</sender> + <signal>toggled(bool)</signal> + <receiver>bitrateBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>173</x> + <y>259</y> + </hint> + <hint type="destinationlabel"> + <x>190</x> + <y>291</y> + </hint> + </hints> + </connection> + <connection> + <sender>outputButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>setOutputLocation()</slot> + <hints> + <hint type="sourcelabel"> + <x>46</x> + <y>340</y> + </hint> + <hint type="destinationlabel"> + <x>6</x> + <y>302</y> + </hint> + </hints> + </connection> + <connection> + <sender>recordButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>toggleRecord()</slot> + <hints> + <hint type="sourcelabel"> + <x>191</x> + <y>340</y> + </hint> + <hint type="destinationlabel"> + <x>113</x> + <y>317</y> + </hint> + </hints> + </connection> + <connection> + <sender>pauseButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>togglePause()</slot> + <hints> + <hint type="sourcelabel"> + <x>252</x> + <y>334</y> + </hint> + <hint type="destinationlabel"> + <x>258</x> + <y>346</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <slot>setOutputLocation()</slot> + <slot>toggleRecord()</slot> + <slot>togglePause()</slot> + </slots> +</ui> diff --git a/examples/multimedia/audiorecorder/audiorecorder_small.ui b/examples/multimedia/audiorecorder/audiorecorder_small.ui new file mode 100644 index 000000000..9d23c4267 --- /dev/null +++ b/examples/multimedia/audiorecorder/audiorecorder_small.ui @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AudioRecorder</class> + <widget class="QMainWindow" name="AudioRecorder"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>420</width> + <height>346</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0" colspan="3"> + <widget class="QScrollArea" name="scrollArea"> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>398</width> + <height>275</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QWidget" name="widget" native="true"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Input Device:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="audioDeviceBox"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Audio Codec:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="audioCodecBox"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>File Container:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="containerBox"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Sample rate:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="sampleRateBox"/> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QRadioButton" name="constantQualityRadioButton"> + <property name="text"> + <string>Quality:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QRadioButton" name="constantBitrateRadioButton"> + <property name="text"> + <string>Bitrate:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QSlider" name="qualitySlider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="bitrateBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>29</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="outputButton"> + <property name="text"> + <string>Output...</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="recordButton"> + <property name="text"> + <string>Record</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pauseButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Pause</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <resources/> + <connections> + <connection> + <sender>constantQualityRadioButton</sender> + <signal>toggled(bool)</signal> + <receiver>qualitySlider</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>113</x> + <y>197</y> + </hint> + <hint type="destinationlabel"> + <x>115</x> + <y>223</y> + </hint> + </hints> + </connection> + <connection> + <sender>constantBitrateRadioButton</sender> + <signal>toggled(bool)</signal> + <receiver>bitrateBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>173</x> + <y>259</y> + </hint> + <hint type="destinationlabel"> + <x>190</x> + <y>291</y> + </hint> + </hints> + </connection> + <connection> + <sender>outputButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>setOutputLocation()</slot> + <hints> + <hint type="sourcelabel"> + <x>46</x> + <y>340</y> + </hint> + <hint type="destinationlabel"> + <x>6</x> + <y>302</y> + </hint> + </hints> + </connection> + <connection> + <sender>recordButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>toggleRecord()</slot> + <hints> + <hint type="sourcelabel"> + <x>191</x> + <y>340</y> + </hint> + <hint type="destinationlabel"> + <x>113</x> + <y>317</y> + </hint> + </hints> + </connection> + <connection> + <sender>pauseButton</sender> + <signal>clicked()</signal> + <receiver>AudioRecorder</receiver> + <slot>togglePause()</slot> + <hints> + <hint type="sourcelabel"> + <x>252</x> + <y>334</y> + </hint> + <hint type="destinationlabel"> + <x>258</x> + <y>346</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <slot>setOutputLocation()</slot> + <slot>toggleRecord()</slot> + <slot>togglePause()</slot> + </slots> +</ui> diff --git a/examples/multimedia/audiorecorder/doc/images/audiorecorder.png b/examples/multimedia/audiorecorder/doc/images/audiorecorder.png Binary files differnew file mode 100644 index 000000000..6643bf320 --- /dev/null +++ b/examples/multimedia/audiorecorder/doc/images/audiorecorder.png diff --git a/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc new file mode 100644 index 000000000..3dea92cac --- /dev/null +++ b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example audiorecorder + \title Audio Recorder Example + \ingroup audio_examples + \brief The Audio Recorder Example shows how to create a simple audio recorder. + + It demonstrates the discovery of the supported devices and codecs and the use + of recording functions in the QAudioRecorder class. + + We display a window for the user to select the appropriate audio input, + codec, container, and sample rate. Allow a setting of either quality or + bitrate. Finally, the output file can be selected and recording can be + started. + + The lists are setup using the \l{QAudioRecorder::audioInputs()}{audioInputs()}, + \l{QAudioRecorder::supportedAudioCodecs()}{supportedAudioCodecs()}, + \l{QAudioRecorder::supportedContainers()}{supportedContainers()}, + \l{QAudioRecorder::supportedContainers()}{supportedContainers()}, and + \l{QAudioRecorder::supportedAudioSampleRates()}{supportedAudioSampleRates()} + methods. The quality slider is setup from 0 (zero) to + \l{QMultimedia::VeryHighQuality} with a default value of + \l{QMultimedia::NormalQuality}, while the bitrates are hardcoded + into the list. + + \image audiorecorder.png + + To record audio we simply create a QAudioRecorder object. + + \code + audioRecorder = new QAudioRecorder(this); + \endcode + + And setup the lists as described above. The text on the record and pause + buttons are toggled depending on the \l{QMediaRecorder::State}{state} of + the \c audioRecorder object. This means that if the state is + \l{QMediaRecorder::StoppedState} then the button text will be "Record" and + "Pause". In \l{QMediaRecorder::RecordingState} the record button will have + the text "Stop", and in \l{QMediaRecorder::PausedState} the pause button + will have the text "Resume". + + Pressing the buttons will also result in a toggle based on the state. If + recording is stopped, then pressing the record button will setup the + \l{QAudioEncoderSettings} based on the values of the selection lists, + will set the encoding settings and container on the \c audioRecorder + object, and start recording using the + \l{QMediaRecorder::record()}{record()} method. + + \code + QAudioEncoderSettings settings; + settings.setCodec(boxValue(ui->audioCodecBox).toString()); + settings.setSampleRate(boxValue(ui->sampleRateBox).toInt()); + settings.setBitRate(boxValue(ui->bitrateBox).toInt()); + settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value())); + settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ? + QMultimedia::ConstantQualityEncoding : + QMultimedia::ConstantBitRateEncoding); + + QString container = boxValue(ui->containerBox).toString(); + + audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container); + audioRecorder->record(); + \endcode + + While recording, the status bar of the application is updated with duration information + from the \l{QMediaRecorder::durationChanged()}{durationChanged} signal from the + \c audioRecorder object. + + \code + ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000)); + \endcode + + + + +*/ + + diff --git a/examples/multimedia/audiorecorder/main.cpp b/examples/multimedia/audiorecorder/main.cpp new file mode 100644 index 000000000..532cfc86b --- /dev/null +++ b/examples/multimedia/audiorecorder/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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 "audiorecorder.h" + +#include <QtWidgets> + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AudioRecorder recorder; + recorder.show(); + + return app.exec(); +} diff --git a/examples/multimedia/audiorecorder/qaudiolevel.cpp b/examples/multimedia/audiorecorder/qaudiolevel.cpp new file mode 100644 index 000000000..1ae034628 --- /dev/null +++ b/examples/multimedia/audiorecorder/qaudiolevel.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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 "qaudiolevel.h" +#include <QPainter> + +QAudioLevel::QAudioLevel(QWidget *parent) + : QWidget(parent) + , m_level(0.0) +{ +} + +void QAudioLevel::setLevel(qreal level) +{ + if (m_level != level) { + m_level = level; + update(); + } +} + +void QAudioLevel::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + // draw level + qreal widthLevel = m_level * width(); + painter.fillRect(0, 0, widthLevel, height(), Qt::red); + // clear the rest of the control + painter.fillRect(widthLevel, 0, width(), height(), Qt::black); +} diff --git a/examples/multimedia/audiorecorder/qaudiolevel.h b/examples/multimedia/audiorecorder/qaudiolevel.h new file mode 100644 index 000000000..7a9dd07ce --- /dev/null +++ b/examples/multimedia/audiorecorder/qaudiolevel.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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 QAUDIOLEVEL_H +#define QAUDIOLEVEL_H + +#include <QWidget> + +class QAudioLevel : public QWidget +{ + Q_OBJECT +public: + explicit QAudioLevel(QWidget *parent = 0); + + // Using [0; 1.0] range + void setLevel(qreal level); + +protected: + void paintEvent(QPaintEvent *event); + +private: + qreal m_level; +}; + +#endif // QAUDIOLEVEL_H |