diff options
21 files changed, 1219 insertions, 803 deletions
diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp index 7d09c38..1a7a7ee 100644 --- a/examples/multimedia/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audiodevices/audiodevices.cpp @@ -44,6 +44,40 @@ #include "audiodevices.h" +// Utility functions for converting QAudioFormat fields into text + +QString toString(QAudioFormat::SampleType sampleType) +{ + QString result("Unknown"); + switch (sampleType) { + case QAudioFormat::SignedInt: + result = "SignedInt"; + break; + case QAudioFormat::UnSignedInt: + result = "UnSignedInt"; + break; + case QAudioFormat::Float: + result = "Float"; + break; + } + return result; +} + +QString toString(QAudioFormat::Endian endian) +{ + QString result("Unknown"); + switch (endian) { + case QAudioFormat::LittleEndian: + result = "LittleEndian"; + break; + case QAudioFormat::BigEndian: + result = "BigEndian"; + break; + } + return result; +} + + AudioDevicesBase::AudioDevicesBase(QWidget *parent, Qt::WFlags f) : QMainWindow(parent, f) { @@ -67,6 +101,7 @@ AudioTest::AudioTest(QWidget *parent, Qt::WFlags f) connect(sampleSizesBox, SIGNAL(activated(int)), SLOT(sampleSizeChanged(int))); connect(sampleTypesBox, SIGNAL(activated(int)), SLOT(sampleTypeChanged(int))); connect(endianBox, SIGNAL(activated(int)), SLOT(endianChanged(int))); + connect(populateTableButton, SIGNAL(clicked()), SLOT(populateTable())); modeBox->setCurrentIndex(0); modeChanged(0); @@ -81,12 +116,11 @@ AudioTest::~AudioTest() void AudioTest::test() { // tries to set all the settings picked. - logOutput->clear(); - logOutput->append("NOTE: an invalid codec audio/test exists for testing, to get a fail condition."); + testResult->clear(); if (!deviceInfo.isNull()) { if (deviceInfo.isFormatSupported(settings)) { - logOutput->append(tr("Success")); + testResult->setText(tr("Success")); nearestFreq->setText(""); nearestChannel->setText(""); nearestCodec->setText(""); @@ -95,40 +129,23 @@ void AudioTest::test() nearestEndian->setText(""); } else { QAudioFormat nearest = deviceInfo.nearestFormat(settings); - logOutput->append(tr("Failed")); + testResult->setText(tr("Failed")); nearestFreq->setText(QString("%1").arg(nearest.frequency())); nearestChannel->setText(QString("%1").arg(nearest.channels())); nearestCodec->setText(nearest.codec()); nearestSampleSize->setText(QString("%1").arg(nearest.sampleSize())); - - switch(nearest.sampleType()) { - case QAudioFormat::SignedInt: - nearestSampleType->setText("SignedInt"); - break; - case QAudioFormat::UnSignedInt: - nearestSampleType->setText("UnSignedInt"); - break; - case QAudioFormat::Float: - nearestSampleType->setText("Float"); - break; - case QAudioFormat::Unknown: - nearestSampleType->setText("Unknown"); - } - switch(nearest.byteOrder()) { - case QAudioFormat::LittleEndian: - nearestEndian->setText("LittleEndian"); - break; - case QAudioFormat::BigEndian: - nearestEndian->setText("BigEndian"); - } + nearestSampleType->setText(toString(nearest.sampleType())); + nearestEndian->setText(toString(nearest.byteOrder())); } } else - logOutput->append(tr("No Device")); + testResult->setText(tr("No Device")); } void AudioTest::modeChanged(int idx) { + testResult->clear(); + // mode has changed if (idx == 0) mode = QAudio::AudioInput; @@ -138,10 +155,15 @@ void AudioTest::modeChanged(int idx) deviceBox->clear(); foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(mode)) deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); + + deviceBox->setCurrentIndex(0); + deviceChanged(0); } void AudioTest::deviceChanged(int idx) { + testResult->clear(); + if (deviceBox->count() == 0) return; @@ -180,38 +202,68 @@ void AudioTest::deviceChanged(int idx) sampleTypesBox->clear(); QList<QAudioFormat::SampleType> sampleTypez = deviceInfo.supportedSampleTypes(); - for (int i = 0; i < sampleTypez.size(); ++i) { - switch(sampleTypez.at(i)) { - case QAudioFormat::SignedInt: - sampleTypesBox->addItem("SignedInt"); - break; - case QAudioFormat::UnSignedInt: - sampleTypesBox->addItem("UnSignedInt"); - break; - case QAudioFormat::Float: - sampleTypesBox->addItem("Float"); - break; - case QAudioFormat::Unknown: - sampleTypesBox->addItem("Unknown"); - } - if (sampleTypez.size()) - settings.setSampleType(sampleTypez.at(0)); - } + + for (int i = 0; i < sampleTypez.size(); ++i) + sampleTypesBox->addItem(toString(sampleTypez.at(i))); + if (sampleTypez.size()) + settings.setSampleType(sampleTypez.at(0)); endianBox->clear(); QList<QAudioFormat::Endian> endianz = deviceInfo.supportedByteOrders(); - for (int i = 0; i < endianz.size(); ++i) { - switch (endianz.at(i)) { - case QAudioFormat::LittleEndian: - endianBox->addItem("Little Endian"); - break; - case QAudioFormat::BigEndian: - endianBox->addItem("Big Endian"); - break; - } - } + for (int i = 0; i < endianz.size(); ++i) + endianBox->addItem(toString(endianz.at(i))); if (endianz.size()) settings.setByteOrder(endianz.at(0)); + + allFormatsTable->clearContents(); +} + +void AudioTest::populateTable() +{ + int row = 0; + + QAudioFormat format; + foreach (QString codec, deviceInfo.supportedCodecs()) { + format.setCodec(codec); + foreach (int frequency, deviceInfo.supportedFrequencies()) { + format.setFrequency(frequency); + foreach (int channels, deviceInfo.supportedChannels()) { + format.setChannels(channels); + foreach (QAudioFormat::SampleType sampleType, deviceInfo.supportedSampleTypes()) { + format.setSampleType(sampleType); + foreach (int sampleSize, deviceInfo.supportedSampleSizes()) { + format.setSampleSize(sampleSize); + foreach (QAudioFormat::Endian endian, deviceInfo.supportedByteOrders()) { + format.setByteOrder(endian); + if (deviceInfo.isFormatSupported(format)) { + allFormatsTable->setRowCount(row + 1); + + QTableWidgetItem *codecItem = new QTableWidgetItem(format.codec()); + allFormatsTable->setItem(row, 0, codecItem); + + QTableWidgetItem *frequencyItem = new QTableWidgetItem(QString("%1").arg(format.frequency())); + allFormatsTable->setItem(row, 1, frequencyItem); + + QTableWidgetItem *channelsItem = new QTableWidgetItem(QString("%1").arg(format.channels())); + allFormatsTable->setItem(row, 2, channelsItem); + + QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(format.sampleType())); + allFormatsTable->setItem(row, 3, sampleTypeItem); + + QTableWidgetItem *sampleSizeItem = new QTableWidgetItem(QString("%1").arg(format.sampleSize())); + allFormatsTable->setItem(row, 4, sampleSizeItem); + + QTableWidgetItem *byteOrderItem = new QTableWidgetItem(toString(format.byteOrder())); + allFormatsTable->setItem(row, 5, byteOrderItem); + + ++row; + } + } + } + } + } + } + } } void AudioTest::freqChanged(int idx) diff --git a/examples/multimedia/audiodevices/audiodevices.h b/examples/multimedia/audiodevices/audiodevices.h index 15ace92..b5b5204 100644 --- a/examples/multimedia/audiodevices/audiodevices.h +++ b/examples/multimedia/audiodevices/audiodevices.h @@ -74,5 +74,7 @@ private slots: void sampleTypeChanged(int idx); void endianChanged(int idx); void test(); + void populateTable(); + }; diff --git a/examples/multimedia/audiodevices/audiodevicesbase.ui b/examples/multimedia/audiodevices/audiodevicesbase.ui index 667a6e5..23b45d7 100644 --- a/examples/multimedia/audiodevices/audiodevicesbase.ui +++ b/examples/multimedia/audiodevices/audiodevicesbase.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>320</width> - <height>300</height> + <width>679</width> + <height>598</height> </rect> </property> <property name="windowTitle"> @@ -30,58 +30,30 @@ <property name="geometry"> <rect> <x>0</x> - <y>-192</y> - <width>282</width> - <height>471</height> + <y>0</y> + <width>659</width> + <height>558</height> </rect> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QGridLayout" name="gridLayout"> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> - <widget class="QLabel" name="deviceLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <widget class="QLabel" name="modeLabel"> <property name="text"> - <string>Device</string> + <string>Mode</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QLabel" name="modeLabel"> + <widget class="QLabel" name="deviceLabel"> <property name="text"> - <string>Mode</string> + <string>Device</string> </property> </widget> </item> <item row="1" column="0"> - <widget class="QComboBox" name="deviceBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>150</width> - <height>0</height> - </size> - </property> - </widget> - </item> - <item row="1" column="1"> <widget class="QComboBox" name="modeBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> <item> <property name="text"> <string>Input</string> @@ -94,203 +66,322 @@ </item> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="actualLabel"> - <property name="frameShape"> - <enum>QFrame::Panel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Actual Settings</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="nearestLabel"> - <property name="frameShape"> - <enum>QFrame::Panel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <property name="text"> - <string>Nearest Settings</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="actualFreqLabel"> - <property name="text"> - <string>Frequency</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLabel" name="nearestFreqLabel"> - <property name="text"> - <string>Frequency</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QComboBox" name="frequencyBox"/> - </item> - <item row="4" column="1"> - <widget class="QLineEdit" name="nearestFreq"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="actualChannelsLabel"> - <property name="text"> - <string>Channels</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QLabel" name="nearestChannelLabel"> - <property name="text"> - <string>Channel</string> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QComboBox" name="channelsBox"/> - </item> - <item row="6" column="1"> - <widget class="QLineEdit" name="nearestChannel"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="actualCodecLabel"> - <property name="text"> - <string>Codecs</string> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="QLabel" name="nearestCodecLabel"> - <property name="text"> - <string>Codec</string> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QComboBox" name="codecsBox"/> - </item> - <item row="8" column="1"> - <widget class="QLineEdit" name="nearestCodec"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="actualSampleSizeLabel"> - <property name="text"> - <string>SampleSize</string> - </property> - </widget> - </item> - <item row="9" column="1"> - <widget class="QLabel" name="nearestSampleSizeLabel"> - <property name="text"> - <string>SampleSize</string> - </property> - </widget> - </item> - <item row="10" column="0"> - <widget class="QComboBox" name="sampleSizesBox"/> - </item> - <item row="10" column="1"> - <widget class="QLineEdit" name="nearestSampleSize"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="11" column="0"> - <widget class="QLabel" name="actualSampleTypeLabel"> - <property name="text"> - <string>SampleType</string> - </property> - </widget> - </item> - <item row="11" column="1"> - <widget class="QLabel" name="nearestSampleTypeLabel"> - <property name="text"> - <string>SampleType</string> - </property> - </widget> - </item> - <item row="12" column="0"> - <widget class="QComboBox" name="sampleTypesBox"/> - </item> - <item row="12" column="1"> - <widget class="QLineEdit" name="nearestSampleType"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="13" column="0"> - <widget class="QLabel" name="actualEndianLabel"> - <property name="text"> - <string>Endianess</string> - </property> - </widget> - </item> - <item row="13" column="1"> - <widget class="QLabel" name="nearestEndianLabel"> - <property name="text"> - <string>Endianess</string> - </property> - </widget> - </item> - <item row="14" column="0"> - <widget class="QComboBox" name="endianBox"/> - </item> - <item row="14" column="1"> - <widget class="QLineEdit" name="nearestEndian"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="15" column="0" colspan="2"> - <widget class="QTextEdit" name="logOutput"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - </widget> - </item> - <item row="16" column="0" colspan="2"> - <widget class="QPushButton" name="testButton"> - <property name="text"> - <string>Test</string> - </property> + <item row="1" column="1"> + <widget class="QComboBox" name="deviceBox"/> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="testFormatTab"> + <attribute name="title"> + <string>Test format</string> + </attribute> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QLabel" name="actualLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="text"> + <string><i>Actual Settings</i></string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="nearestLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Nearest Settings</span></p></body></html></string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="frequencyBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLineEdit" name="nearestFreq"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QComboBox" name="channelsBox"/> + </item> + <item row="5" column="2"> + <widget class="QLineEdit" name="nearestChannel"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="9" column="1"> + <widget class="QComboBox" name="sampleSizesBox"/> + </item> + <item row="9" column="2"> + <widget class="QLineEdit" name="nearestSampleSize"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="14" column="1"> + <widget class="QComboBox" name="endianBox"/> + </item> + <item row="14" column="2"> + <widget class="QLineEdit" name="nearestEndian"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="15" column="1"> + <widget class="QPushButton" name="testButton"> + <property name="text"> + <string>Test</string> + </property> + </widget> + </item> + <item row="15" column="2"> + <widget class="QLabel" name="testResult"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="actualFreqLabel"> + <property name="text"> + <string>Frequency (Hz)</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="actualChannelLabel"> + <property name="text"> + <string>Channels</string> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="actualSampleSizeLabel"> + <property name="text"> + <string>Sample size (bits)</string> + </property> + </widget> + </item> + <item row="14" column="0"> + <widget class="QLabel" name="actualEndianLabel"> + <property name="text"> + <string>Endianess</string> + </property> + </widget> + </item> + <item row="16" column="0" colspan="3"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Note: an invalid codec 'audio/test' exists in order to allow an invalid format to be constructed, and therefore to trigger a 'nearest format' calculation.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="actualCodecLabel"> + <property name="text"> + <string>Codec</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLineEdit" name="nearestCodec"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="codecsBox"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="actualSampleTypeLabel"> + <property name="text"> + <string>SampleType</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QComboBox" name="sampleTypesBox"/> + </item> + <item row="6" column="2"> + <widget class="QLineEdit" name="nearestSampleType"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>All formats</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="populateTableButton"> + <property name="text"> + <string>Populate table</string> + </property> + </widget> + </item> + <item> + <widget class="QTableWidget" name="allFormatsTable"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="dragDropOverwriteMode"> + <bool>false</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectItems</enum> + </property> + <property name="textElideMode"> + <enum>Qt::ElideNone</enum> + </property> + <property name="sortingEnabled"> + <bool>false</bool> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Codec</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Frequency (Hz)</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Channels</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Sample type</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Sample size (bits)</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Endianness</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> diff --git a/examples/multimedia/audiodevices/main.cpp b/examples/multimedia/audiodevices/main.cpp index 0ea18a1..8ca4932 100644 --- a/examples/multimedia/audiodevices/main.cpp +++ b/examples/multimedia/audiodevices/main.cpp @@ -49,7 +49,11 @@ int main(int argv, char **args) app.setApplicationName("Audio Device Test"); AudioTest audio; +#ifdef Q_OS_SYMBIAN + audio.showMaximized(); +#else audio.show(); +#endif return app.exec(); } diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index ffe8d06..bdb0cfd 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3129,10 +3129,11 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QString *output) static const char * const idn_whitelist[] = { - "ac", "at", - "br", + "ac", "ar", "at", + "biz", "br", "cat", "ch", "cl", "cn", "de", "dk", + "es", "fi", "gr", "hu", @@ -3146,6 +3147,9 @@ static const char * const idn_whitelist[] = { "se", "sh", "th", "tm", "tw", "vn", + "xn--mgbaam7a8h", // UAE + "xn--mgberp4a5d4ar", // Saudi Arabia + "xn--wgbh1c" // Egypt }; static QStringList *user_idn_whitelist = 0; @@ -3304,6 +3308,7 @@ static QString qt_ACE_do(const QString &domain, AceOperation op) qt_nameprep(&result, prevLen); labelLength = result.length() - prevLen; register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes + aceForm.resize(0); if (toReserve > aceForm.capacity()) aceForm.reserve(toReserve); toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index c85d1be..6448b06 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -47,6 +47,8 @@ #include <unistd.h> #include <errno.h> +#include <net/if.h> + QT_BEGIN_NAMESPACE #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS @@ -569,13 +571,17 @@ void QSelectThread::updateActivatedNotifiers(QSocketNotifier::Type type, fd_set * check if socket is in exception set * then signal RequestComplete for it */ - qWarning("exception on %d [will close the socket handle - hack]", i.key()->socket()); + qWarning("exception on %d [will do setdefaultif(0) - hack]", i.key()->socket()); // quick fix; there is a bug // when doing read on socket // errors not preoperly mapped // after offline-ing the device // on some devices we do get exception - ::close(i.key()->socket()); + // close all exiting sockets + // and reset default IAP + if(::setdefaultif(0) != KErrNone) // well we can't do much about it + qWarning("setdefaultif(0) failed"); + toRemove.append(i.key()); TRequestStatus *status = i.value(); QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 98fc10f..2131993 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -693,6 +693,14 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) --selectionChanging; if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize) emit q->selectionChanged(); + + QHash<QGesture *, QGraphicsObject *>::iterator it; + for (it = gestureTargets.begin(); it != gestureTargets.end();) { + if (it.value() == item) + it = gestureTargets.erase(it); + else + ++it; + } } /*! @@ -5960,7 +5968,8 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) if (gesture->state() == Qt::GestureStarted) startedGestures.insert(gesture); } else { - gesturesPerItem[target].append(gesture); + if (index->items().contains(target)) + gesturesPerItem[target].append(gesture); } } diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index a0e8496..8bae18e 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -815,12 +815,6 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const widgetPalette.setColor(QPalette::HighlightedText, s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0)); QApplication::setPalette(widgetPalette, "QLineEdit"); - widgetPalette = *palette; - - widgetPalette.setColor(QPalette::Text, - s60Color(QS60StyleEnums::CL_QsnTextColors, 27, 0)); - widgetPalette.setColor(QPalette::HighlightedText, - s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0)); QApplication::setPalette(widgetPalette, "QTextEdit"); widgetPalette = *palette; @@ -1121,11 +1115,9 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom tool.rect = button.unite(menuRect); tool.state = bflags; const QToolButton *toolButtonWidget = qobject_cast<const QToolButton *>(widget); - QS60StylePrivate::SkinElements element; - if (toolButtonWidget) - element = (toolButtonWidget->isDown()) ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; - else - element = (option->state & State_Sunken) ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; + const QS60StylePrivate::SkinElements element = + ((toolButtonWidget && toolButtonWidget->isDown()) || (option->state & State_Sunken)) ? + QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; QS60StylePrivate::drawSkinElement(element, painter, tool.rect, flags); drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); } @@ -1535,13 +1527,13 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QS60StylePrivate::SE_TabBarTabNorthInactive; break; } - if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive|| - skinElement==QS60StylePrivate::SE_TabBarTabNorthInactive|| - skinElement==QS60StylePrivate::SE_TabBarTabSouthInactive|| - skinElement==QS60StylePrivate::SE_TabBarTabWestInactive|| - skinElement==QS60StylePrivate::SE_TabBarTabEastActive|| - skinElement==QS60StylePrivate::SE_TabBarTabNorthActive|| - skinElement==QS60StylePrivate::SE_TabBarTabSouthActive|| + if (skinElement == QS60StylePrivate::SE_TabBarTabEastInactive || + skinElement == QS60StylePrivate::SE_TabBarTabNorthInactive || + skinElement == QS60StylePrivate::SE_TabBarTabSouthInactive || + skinElement == QS60StylePrivate::SE_TabBarTabWestInactive || + skinElement == QS60StylePrivate::SE_TabBarTabEastActive || + skinElement == QS60StylePrivate::SE_TabBarTabNorthActive || + skinElement == QS60StylePrivate::SE_TabBarTabSouthActive || skinElement==QS60StylePrivate::SE_TabBarTabWestActive) { const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); @@ -2362,41 +2354,43 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti #endif QCommonStyle::drawPrimitive(element, option, painter, widget); } else { - const bool rightLine = option->state & State_Item; - const bool downLine = option->state & State_Sibling; - const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling); - - QS60StyleEnums::SkinParts skinPart; - bool drawSkinPart = false; - if (rightLine && downLine && upLine) { - skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch; - drawSkinPart = true; - } else if (rightLine && upLine) { - skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd; - drawSkinPart = true; - } else if (upLine && downLine) { - skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight; - drawSkinPart = true; - } - - if (drawSkinPart) - QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags); + if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(option)) { + const bool rightLine = option->state & State_Item; + const bool downLine = option->state & State_Sibling; + const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling); + QS60StylePrivate::SkinElementFlags adjustedFlags = flags; + + QS60StyleEnums::SkinParts skinPart; + bool drawSkinPart = false; + if (rightLine && downLine && upLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch; + drawSkinPart = true; + } else if (rightLine && upLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd; + drawSkinPart = true; + } else if (upLine && downLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight; + drawSkinPart = true; + } - if (option->state & State_Children) { - QS60StyleEnums::SkinParts skinPart = - (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper; - int minDimension = qMin(option->rect.width(), option->rect.height()); - QRect iconRect(option->rect.topLeft(), QSize(minDimension, minDimension)); - const int magicTweak = 3; - int resizeValue = minDimension >> 1; - if (!QS60StylePrivate::isTouchSupported()) { - minDimension += resizeValue; // Adjust the icon bigger because of empty space in svg icon. - iconRect.setSize(QSize(minDimension, minDimension)); - const int verticalMagic = (option->rect.width() <= option->rect.height()) ? magicTweak : 0; - resizeValue = verticalMagic - resizeValue; + if (option->direction == Qt::RightToLeft) + adjustedFlags |= QS60StylePrivate::SF_Mirrored_X_Axis; + + if (drawSkinPart) + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, adjustedFlags); + + if (option->state & State_Children) { + QS60StyleEnums::SkinParts skinPart = + (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper; + const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); + const int minDimension = qMin(option->rect.width(), option->rect.height()); + const int magicTweak = (option->direction == Qt::RightToLeft) ? -3 : 3; //@todo: magic + //The branch indicator icon in S60 is supposed to be superimposed on top of branch lines. + QRect iconRect(QPoint(option->rect.left() + magicTweak, selectionRect.top() + 1), QSize(minDimension, minDimension)); + if (!QS60StylePrivate::isTouchSupported()) + iconRect.translate(0, -4); //@todo: magic + QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, adjustedFlags); } - iconRect.translate(magicTweak, resizeValue); - QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, flags); } } break; @@ -2510,7 +2504,7 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0); const int iconHeight = (!buttonWidget->icon().isNull()) ? buttonWidget->iconSize().height() : 0; const int textHeight = (buttonWidget->text().length() > 0) ? - buttonWidget->fontMetrics().size(Qt::TextSingleLine, buttonWidget->text()).height() : 0; + buttonWidget->fontMetrics().size(Qt::TextSingleLine, buttonWidget->text()).height() : opt->fontMetrics.height(); const int decoratorHeight = (buttonWidget->isCheckable()) ? pixelMetric(PM_IndicatorHeight) : 0; const int contentHeight = @@ -3009,7 +3003,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con } break; case SE_ItemViewItemCheckIndicator: - if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) { + if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) { const QListWidget *listItem = qobject_cast<const QListWidget *>(widget); const bool singleSelection = listItem && diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 9dd3810..d8c31f8 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -476,6 +476,8 @@ public: SF_StateDisabled = 0x0020, SF_ColorSkinned = 0x0040, // pixmap is colored with foreground pen color SF_Animation = 0x0080, + SF_Mirrored_X_Axis = 0x0100, + SF_Mirrored_Y_Axis = 0x0200 }; enum CacheClearReason { diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 5bc36f8..c0ecc5d 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -654,6 +654,14 @@ QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask pixmap = QPixmap::fromImage(iconImage); } + if ((flags & QS60StylePrivate::SF_Mirrored_X_Axis) || + (flags & QS60StylePrivate::SF_Mirrored_Y_Axis)) { + QImage iconImage = pixmap.toImage().mirrored( + flags & QS60StylePrivate::SF_Mirrored_X_Axis, + flags & QS60StylePrivate::SF_Mirrored_Y_Axis); + pixmap = QPixmap::fromImage(iconImage); + } + return pixmap; } @@ -969,7 +977,7 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme switch(frameElement) { case QS60StylePrivate::SF_ToolTip: - if (QSysInfo::s60Version()!=QSysInfo::SV_S60_3_1) { + if (QSysInfo::s60Version() != QSysInfo::SV_S60_3_1) { centerId.Set(EAknsMajorGeneric, 0x19c2); frameId.Set(EAknsMajorSkin, 0x5300); } else { @@ -978,7 +986,8 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme } break; case QS60StylePrivate::SF_ToolBar: - if (QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 || QSysInfo::s60Version()==QSysInfo::SV_S60_3_2) { + if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || + QSysInfo::s60Version() == QSysInfo::SV_S60_3_2) { centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu); frameId.Set(KAknsIIDQsnFrPopupSub); } diff --git a/src/multimedia/audio/qaudio_symbian_p.cpp b/src/multimedia/audio/qaudio_symbian_p.cpp index afe98f5..4522c5c 100644 --- a/src/multimedia/audio/qaudio_symbian_p.cpp +++ b/src/multimedia/audio/qaudio_symbian_p.cpp @@ -45,41 +45,6 @@ QT_BEGIN_NAMESPACE namespace SymbianAudio { - -DevSoundCapabilities::DevSoundCapabilities(CMMFDevSound &devsound, - QAudio::Mode mode) -{ - QT_TRAP_THROWING(constructL(devsound, mode)); -} - -DevSoundCapabilities::~DevSoundCapabilities() -{ - m_fourCC.Close(); -} - -void DevSoundCapabilities::constructL(CMMFDevSound &devsound, - QAudio::Mode mode) -{ - m_caps = devsound.Capabilities(); - - TMMFPrioritySettings settings; - - switch (mode) { - case QAudio::AudioOutput: - settings.iState = EMMFStatePlaying; - devsound.GetSupportedInputDataTypesL(m_fourCC, settings); - break; - - case QAudio::AudioInput: - settings.iState = EMMFStateRecording; - devsound.GetSupportedInputDataTypesL(m_fourCC, settings); - break; - - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode"); - } -} - namespace Utils { //----------------------------------------------------------------------------- @@ -274,11 +239,8 @@ bool sampleInfoQtToNative(int inputSampleSize, return found; } -//----------------------------------------------------------------------------- -// Public functions -//----------------------------------------------------------------------------- - -void capabilitiesNativeToQt(const DevSoundCapabilities &caps, +void capabilitiesNativeToQt(const TMMFCapabilities &caps, + const TFourCC &fourcc, QList<int> &frequencies, QList<int> &channels, QList<int> &sampleSizes, @@ -292,37 +254,20 @@ void capabilitiesNativeToQt(const DevSoundCapabilities &caps, channels.clear(); for (int i=0; i<SampleRateCount; ++i) - if (caps.caps().iRate & SampleRateListNative[i]) + if (caps.iRate & SampleRateListNative[i]) frequencies += SampleRateListQt[i]; for (int i=0; i<ChannelsCount; ++i) - if (caps.caps().iChannels & ChannelsListNative[i]) + if (caps.iChannels & ChannelsListNative[i]) channels += ChannelsListQt[i]; for (int i=0; i<EncodingCount; ++i) { - if (caps.fourCC().Find(EncodingFourCC[i]) != KErrNotFound) { + if (fourcc == EncodingFourCC[i]) { sampleSizes += EncodingSampleSize[i]; byteOrders += EncodingByteOrder[i]; sampleTypes += EncodingSampleType[i]; } } - -} - -bool isFormatSupported(const QAudioFormat &formatQt, - const DevSoundCapabilities &caps) { - TMMFCapabilities formatNative; - TUint32 fourCC; - - bool result = false; - if (formatQt.codec() == QString::fromAscii("audio/pcm") && - formatQtToNative(formatQt, fourCC, formatNative)) { - result = - (formatNative.iRate & caps.caps().iRate) - && (formatNative.iChannels & caps.caps().iChannels) - && (caps.fourCC().Find(fourCC) != KErrNotFound); - } - return result; } bool formatQtToNative(const QAudioFormat &inputFormat, @@ -337,7 +282,7 @@ bool formatQtToNative(const QAudioFormat &inputFormat, TMMFMonoStereo outputChannels; TMMFSoundEncoding outputEncoding; - if (inputFormat.codec() == QString::fromAscii("audio/pcm")) { + if (inputFormat.codec() == QLatin1String("audio/pcm")) { result = sampleRateQtToNative(inputFormat.frequency(), outputSampleRate) && channelsQtToNative(inputFormat.channels(), outputChannels) @@ -357,14 +302,13 @@ bool formatQtToNative(const QAudioFormat &inputFormat, return result; } -QAudio::State stateNativeToQt(State nativeState, - QAudio::State initializingState) +QAudio::State stateNativeToQt(State nativeState) { switch (nativeState) { case ClosedState: return QAudio::StoppedState; case InitializingState: - return initializingState; + return QAudio::StoppedState; case ActiveState: return QAudio::ActiveState; case IdleState: @@ -388,6 +332,291 @@ qint64 samplesToBytes(const QAudioFormat &format, qint64 samples) } } // namespace Utils + + +//----------------------------------------------------------------------------- +// DevSoundWrapper +//----------------------------------------------------------------------------- + +DevSoundWrapper::DevSoundWrapper(QAudio::Mode mode, QObject *parent) + : QObject(parent) + , m_mode(mode) + , m_state(StateIdle) + , m_devsound(0) + , m_fourcc(0) +{ + QT_TRAP_THROWING(m_devsound = CMMFDevSound::NewL()); + + switch (mode) { + case QAudio::AudioOutput: + m_nativeMode = EMMFStatePlaying; + break; + + case QAudio::AudioInput: + m_nativeMode = EMMFStateRecording; + break; + + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode"); + } + + getSupportedCodecs(); +} + +DevSoundWrapper::~DevSoundWrapper() +{ + delete m_devsound; +} + +const QList<QString>& DevSoundWrapper::supportedCodecs() const +{ + return m_supportedCodecs; +} + +void DevSoundWrapper::initialize(const QString& codec) +{ + Q_ASSERT(StateInitializing != m_state); + m_state = StateInitializing; + if (QLatin1String("audio/pcm") == codec) { + m_fourcc = KMMFFourCCCodePCM16; + TRAPD(err, m_devsound->InitializeL(*this, m_fourcc, m_nativeMode)); + if (KErrNone != err) { + m_state = StateIdle; + emit initializeComplete(err); + } + } else { + emit initializeComplete(KErrNotSupported); + } +} + +const QList<int>& DevSoundWrapper::supportedFrequencies() const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedFrequencies; +} + +const QList<int>& DevSoundWrapper::supportedChannels() const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedChannels; +} + +const QList<int>& DevSoundWrapper::supportedSampleSizes() const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedSampleSizes; +} + +const QList<QAudioFormat::Endian>& DevSoundWrapper::supportedByteOrders() const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedByteOrders; +} + +const QList<QAudioFormat::SampleType>& DevSoundWrapper::supportedSampleTypes() const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedSampleTypes; +} + +bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const +{ + Q_ASSERT(StateInitialized == m_state); + return m_supportedCodecs.contains(format.codec()) + && m_supportedFrequencies.contains(format.frequency()) + && m_supportedChannels.contains(format.channels()) + && m_supportedSampleSizes.contains(format.sampleSize()) + && m_supportedSampleTypes.contains(format.sampleType()) + && m_supportedByteOrders.contains(format.byteOrder()); +} + +int DevSoundWrapper::samplesProcessed() const +{ + Q_ASSERT(StateInitialized == m_state); + int result = 0; + switch (m_mode) { + case QAudio::AudioInput: + result = m_devsound->SamplesRecorded(); + break; + case QAudio::AudioOutput: + result = m_devsound->SamplesPlayed(); + break; + } + return result; +} + +bool DevSoundWrapper::setFormat(const QAudioFormat &format) +{ + Q_ASSERT(StateInitialized == m_state); + bool result = false; + TUint32 fourcc; + TMMFCapabilities nativeFormat; + if (Utils::formatQtToNative(format, fourcc, nativeFormat)) { + TMMFCapabilities currentNativeFormat = m_devsound->Config(); + nativeFormat.iBufferSize = currentNativeFormat.iBufferSize; + TRAPD(err, m_devsound->SetConfigL(nativeFormat)); + result = (KErrNone == err); + } + return result; +} + +bool DevSoundWrapper::start() +{ + Q_ASSERT(StateInitialized == m_state); + int err = KErrArgument; + switch (m_mode) { + case QAudio::AudioInput: + TRAP(err, m_devsound->RecordInitL()); + break; + case QAudio::AudioOutput: + TRAP(err, m_devsound->PlayInitL()); + break; + } + return (KErrNone == err); +} + +void DevSoundWrapper::pause() +{ + Q_ASSERT(StateInitialized == m_state); + m_devsound->Pause(); +} + +void DevSoundWrapper::stop() +{ + m_devsound->Stop(); +} + +void DevSoundWrapper::bufferProcessed() +{ + Q_ASSERT(StateInitialized == m_state); + switch (m_mode) { + case QAudio::AudioInput: + m_devsound->RecordData(); + break; + case QAudio::AudioOutput: + m_devsound->PlayData(); + break; + } +} + +void DevSoundWrapper::getSupportedCodecs() +{ +/* + * TODO: once we support formats other than PCM, this function should + * convert the array of FourCC codes into MIME types for each codec. + * + RArray<TFourCC> fourcc; + QT_TRAP_THROWING(CleanupClosePushL(&fourcc)); + + TMMFPrioritySettings settings; + switch (mode) { + case QAudio::AudioOutput: + settings.iState = EMMFStatePlaying; + m_devsound->GetSupportedInputDataTypesL(fourcc, settings); + break; + + case QAudio::AudioInput: + settings.iState = EMMFStateRecording; + m_devsound->GetSupportedInputDataTypesL(fourcc, settings); + break; + + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode"); + } + + CleanupStack::PopAndDestroy(); // fourcc +*/ + + m_supportedCodecs.append(QLatin1String("audio/pcm")); +} + +void DevSoundWrapper::populateCapabilities() +{ + m_supportedFrequencies.clear(); + m_supportedChannels.clear(); + m_supportedSampleSizes.clear(); + m_supportedByteOrders.clear(); + m_supportedSampleTypes.clear(); + + const TMMFCapabilities caps = m_devsound->Capabilities(); + + for (int i=0; i<Utils::SampleRateCount; ++i) + if (caps.iRate & Utils::SampleRateListNative[i]) + m_supportedFrequencies += Utils::SampleRateListQt[i]; + + for (int i=0; i<Utils::ChannelsCount; ++i) + if (caps.iChannels & Utils::ChannelsListNative[i]) + m_supportedChannels += Utils::ChannelsListQt[i]; + + for (int i=0; i<Utils::EncodingCount; ++i) { + if (m_fourcc == Utils::EncodingFourCC[i]) { + m_supportedSampleSizes += Utils::EncodingSampleSize[i]; + m_supportedByteOrders += Utils::EncodingByteOrder[i]; + m_supportedSampleTypes += Utils::EncodingSampleType[i]; + } + } +} + +void DevSoundWrapper::InitializeComplete(TInt aError) +{ + Q_ASSERT(StateInitializing == m_state); + if (KErrNone == aError) { + m_state = StateInitialized; + populateCapabilities(); + } else { + m_state = StateIdle; + } + emit initializeComplete(aError); +} + +void DevSoundWrapper::ToneFinished(TInt aError) +{ + Q_UNUSED(aError) + // This class doesn't use DevSound's tone playback functions, so should + // never receive this callback. + Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); +} + +void DevSoundWrapper::BufferToBeFilled(CMMFBuffer *aBuffer) +{ + Q_ASSERT(QAudio::AudioOutput == m_mode); + emit bufferToBeProcessed(aBuffer); +} + +void DevSoundWrapper::PlayError(TInt aError) +{ + Q_ASSERT(QAudio::AudioOutput == m_mode); + emit processingError(aError); +} + +void DevSoundWrapper::BufferToBeEmptied(CMMFBuffer *aBuffer) +{ + Q_ASSERT(QAudio::AudioInput == m_mode); + emit bufferToBeProcessed(aBuffer); +} + +void DevSoundWrapper::RecordError(TInt aError) +{ + Q_ASSERT(QAudio::AudioInput == m_mode); + emit processingError(aError); +} + +void DevSoundWrapper::ConvertError(TInt aError) +{ + Q_UNUSED(aError) + // This class doesn't use DevSound's format conversion functions, so + // should never receive this callback. + Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); +} + +void DevSoundWrapper::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg) +{ + Q_UNUSED(aMessageType) + Q_UNUSED(aMsg) + // Ignore this callback. +} + + } // namespace SymbianAudio QT_END_NAMESPACE diff --git a/src/multimedia/audio/qaudio_symbian_p.h b/src/multimedia/audio/qaudio_symbian_p.h index d5238b4..58ef192 100644 --- a/src/multimedia/audio/qaudio_symbian_p.h +++ b/src/multimedia/audio/qaudio_symbian_p.h @@ -53,7 +53,8 @@ #ifndef QAUDIO_SYMBIAN_P_H #define QAUDIO_SYMBIAN_P_H -#include <QtCore/qnamespace.h> +#include <QtCore/QList> +#include <QtCore/QString> #include <QtMultimedia/qaudioformat.h> #include <QtMultimedia/qaudio.h> #include <sounddevice.h> @@ -83,60 +84,92 @@ enum State { , SuspendedState }; -/* - * Helper class for querying DevSound codec / format support +/** + * Wrapper around DevSound instance */ -class DevSoundCapabilities { +class DevSoundWrapper + : public QObject + , public MDevSoundObserver +{ + Q_OBJECT + +public: + DevSoundWrapper(QAudio::Mode mode, QObject *parent = 0); + ~DevSoundWrapper(); + public: - DevSoundCapabilities(CMMFDevSound &devsound, QAudio::Mode mode); - ~DevSoundCapabilities(); + // List of supported codecs; can be called once object is constructed + const QList<QString>& supportedCodecs() const; + + // Asynchronous initialization function; emits devsoundInitializeComplete + void initialize(const QString& codec); + + // Capabilities, for selected codec. Can be called once initialize has returned + // successfully. + const QList<int>& supportedFrequencies() const; + const QList<int>& supportedChannels() const; + const QList<int>& supportedSampleSizes() const; + const QList<QAudioFormat::Endian>& supportedByteOrders() const; + const QList<QAudioFormat::SampleType>& supportedSampleTypes() const; - const RArray<TFourCC>& fourCC() const { return m_fourCC; } - const TMMFCapabilities& caps() const { return m_caps; } + bool isFormatSupported(const QAudioFormat &format) const; + + int samplesProcessed() const; + bool setFormat(const QAudioFormat &format); + bool start(); + void pause(); + void stop(); + void bufferProcessed(); + +public: + // MDevSoundObserver + void InitializeComplete(TInt aError); + void ToneFinished(TInt aError); + void BufferToBeFilled(CMMFBuffer *aBuffer); + void PlayError(TInt aError); + void BufferToBeEmptied(CMMFBuffer *aBuffer); + void RecordError(TInt aError); + void ConvertError(TInt aError); + void DeviceMessage(TUid aMessageType, const TDesC8 &aMsg); + +signals: + void initializeComplete(int error); + void bufferToBeProcessed(CMMFBuffer *buffer); + void processingError(int error); private: - void constructL(CMMFDevSound &devsound, QAudio::Mode mode); + void getSupportedCodecs(); + void populateCapabilities(); private: - RArray<TFourCC> m_fourCC; - TMMFCapabilities m_caps; -}; + const QAudio::Mode m_mode; + TMMFState m_nativeMode; -namespace Utils { + enum State { + StateIdle, + StateInitializing, + StateInitialized + } m_state; -/** - * Convert native audio capabilities to QAudio lists. - */ -void capabilitiesNativeToQt(const DevSoundCapabilities &caps, - QList<int> &frequencies, - QList<int> &channels, - QList<int> &sampleSizes, - QList<QAudioFormat::Endian> &byteOrders, - QList<QAudioFormat::SampleType> &sampleTypes); + CMMFDevSound* m_devsound; + TFourCC m_fourcc; -/** - * Check whether format is supported. - */ -bool isFormatSupported(const QAudioFormat &format, - const DevSoundCapabilities &caps); + QList<QString> m_supportedCodecs; + QList<int> m_supportedFrequencies; + QList<int> m_supportedChannels; + QList<int> m_supportedSampleSizes; + QList<QAudioFormat::Endian> m_supportedByteOrders; + QList<QAudioFormat::SampleType> m_supportedSampleTypes; -/** - * Convert QAudioFormat to native format types. - * - * Note that, despite the name, DevSound uses TMMFCapabilities to specify - * single formats as well as capabilities. - * - * Note that this function does not modify outputFormat.iBufferSize. - */ -bool formatQtToNative(const QAudioFormat &inputFormat, - TUint32 &outputFourCC, - TMMFCapabilities &outputFormat); +}; + + +namespace Utils { /** * Convert internal states to QAudio states. */ -QAudio::State stateNativeToQt(State nativeState, - QAudio::State initializingState); +QAudio::State stateNativeToQt(State nativeState); /** * Convert data length to number of samples. diff --git a/src/multimedia/audio/qaudiodeviceinfo_symbian_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_symbian_p.cpp index 36284d3..4be116f 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_symbian_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_symbian_p.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include <QtCore/QCoreApplication> #include "qaudiodeviceinfo_symbian_p.h" #include "qaudio_symbian_p.h" @@ -50,7 +51,7 @@ QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray device, , m_mode(mode) , m_updated(false) { - QT_TRAP_THROWING(m_devsound.reset(CMMFDevSound::NewL())); + } QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal() @@ -85,16 +86,21 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const } if (!isFormatSupported(format)) { - if (m_frequencies.size()) - format.setFrequency(m_frequencies[0]); - if (m_channels.size()) - format.setChannels(m_channels[0]); - if (m_sampleSizes.size()) - format.setSampleSize(m_sampleSizes[0]); - if (m_byteOrders.size()) - format.setByteOrder(m_byteOrders[0]); - if (m_sampleTypes.size()) - format.setSampleType(m_sampleTypes[0]); + format = QAudioFormat(); + format.setCodec(QLatin1String("audio/pcm")); + if (m_capabilities.contains(format.codec())) { + const Capabilities &codecCaps = m_capabilities[format.codec()]; + if (codecCaps.m_frequencies.size()) + format.setFrequency(codecCaps.m_frequencies[0]); + if (codecCaps.m_channels.size()) + format.setChannels(codecCaps.m_channels[0]); + if (codecCaps.m_sampleSizes.size()) + format.setSampleSize(codecCaps.m_sampleSizes[0]); + if (codecCaps.m_byteOrders.size()) + format.setByteOrder(codecCaps.m_byteOrders[0]); + if (codecCaps.m_sampleTypes.size()) + format.setSampleType(codecCaps.m_sampleTypes[0]); + } } return format; @@ -104,14 +110,15 @@ bool QAudioDeviceInfoInternal::isFormatSupported( const QAudioFormat &format) const { getSupportedFormats(); - const bool supported = - m_codecs.contains(format.codec()) - && m_frequencies.contains(format.frequency()) - && m_channels.contains(format.channels()) - && m_sampleSizes.contains(format.sampleSize()) - && m_byteOrders.contains(format.byteOrder()) - && m_sampleTypes.contains(format.sampleType()); - + bool supported = false; + if (m_capabilities.contains(format.codec())) { + const Capabilities &codecCaps = m_capabilities[format.codec()]; + supported = codecCaps.m_frequencies.contains(format.frequency()) + && codecCaps.m_channels.contains(format.channels()) + && codecCaps.m_sampleSizes.contains(format.sampleSize()) + && codecCaps.m_byteOrders.contains(format.byteOrder()) + && codecCaps.m_sampleTypes.contains(format.sampleType()); + } return supported; } @@ -131,37 +138,37 @@ QString QAudioDeviceInfoInternal::deviceName() const QStringList QAudioDeviceInfoInternal::codecList() { getSupportedFormats(); - return m_codecs; + return m_capabilities.keys(); } QList<int> QAudioDeviceInfoInternal::frequencyList() { getSupportedFormats(); - return m_frequencies; + return m_unionCapabilities.m_frequencies; } QList<int> QAudioDeviceInfoInternal::channelsList() { getSupportedFormats(); - return m_channels; + return m_unionCapabilities.m_channels; } QList<int> QAudioDeviceInfoInternal::sampleSizeList() { getSupportedFormats(); - return m_sampleSizes; + return m_unionCapabilities.m_sampleSizes; } QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::byteOrderList() { getSupportedFormats(); - return m_byteOrders; + return m_unionCapabilities.m_byteOrders; } QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::sampleTypeList() { getSupportedFormats(); - return m_sampleTypes; + return m_unionCapabilities.m_sampleTypes; } QByteArray QAudioDeviceInfoInternal::defaultInputDevice() @@ -181,17 +188,50 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode) return result; } -void QAudioDeviceInfoInternal::getSupportedFormats() const +void QAudioDeviceInfoInternal::devsoundInitializeComplete(int err) { - if (!m_updated) { - QScopedPointer<SymbianAudio::DevSoundCapabilities> caps( - new SymbianAudio::DevSoundCapabilities(*m_devsound, m_mode)); + m_intializationResult = err; + m_initializing = false; +} - SymbianAudio::Utils::capabilitiesNativeToQt(*caps, - m_frequencies, m_channels, m_sampleSizes, - m_byteOrders, m_sampleTypes); +// Helper function +template<typename T> +void appendUnique(QList<T> &left, const QList<T> &right) +{ + foreach (const T &value, right) + if (!left.contains(value)) + left += value; +} - m_codecs.append(QLatin1String("audio/pcm")); +void QAudioDeviceInfoInternal::getSupportedFormats() const +{ + if (!m_updated) { + QScopedPointer<SymbianAudio::DevSoundWrapper> devsound(new SymbianAudio::DevSoundWrapper(m_mode)); + connect(devsound.data(), SIGNAL(initializeComplete(int)), + this, SLOT(devsoundInitializeComplete(int))); + + foreach (const QString& codec, devsound->supportedCodecs()) { + m_initializing = true; + devsound->initialize(codec); + while (m_initializing) + QCoreApplication::instance()->processEvents(QEventLoop::WaitForMoreEvents); + if (KErrNone == m_intializationResult) { + m_capabilities[codec].m_frequencies = devsound->supportedFrequencies(); + appendUnique(m_unionCapabilities.m_frequencies, devsound->supportedFrequencies()); + + m_capabilities[codec].m_channels = devsound->supportedChannels(); + appendUnique(m_unionCapabilities.m_channels, devsound->supportedChannels()); + + m_capabilities[codec].m_sampleSizes = devsound->supportedSampleSizes(); + appendUnique(m_unionCapabilities.m_sampleSizes, devsound->supportedSampleSizes()); + + m_capabilities[codec].m_byteOrders = devsound->supportedByteOrders(); + appendUnique(m_unionCapabilities.m_byteOrders, devsound->supportedByteOrders()); + + m_capabilities[codec].m_sampleTypes = devsound->supportedSampleTypes(); + appendUnique(m_unionCapabilities.m_sampleTypes, devsound->supportedSampleTypes()); + } + } m_updated = true; } diff --git a/src/multimedia/audio/qaudiodeviceinfo_symbian_p.h b/src/multimedia/audio/qaudiodeviceinfo_symbian_p.h index 89e539f..79b23cc 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_symbian_p.h +++ b/src/multimedia/audio/qaudiodeviceinfo_symbian_p.h @@ -53,11 +53,16 @@ #ifndef QAUDIODEVICEINFO_SYMBIAN_P_H #define QAUDIODEVICEINFO_SYMBIAN_P_H +#include <QtCore/QMap> #include <QtMultimedia/qaudioengine.h> #include <sounddevice.h> QT_BEGIN_NAMESPACE +namespace SymbianAudio { +class DevSoundWrapper; +} + class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo { @@ -82,24 +87,33 @@ public: static QByteArray defaultOutputDevice(); static QList<QByteArray> availableDevices(QAudio::Mode); +private slots: + void devsoundInitializeComplete(int err); + private: void getSupportedFormats() const; private: - QScopedPointer<CMMFDevSound> m_devsound; + mutable bool m_initializing; + int m_intializationResult; QString m_deviceName; QAudio::Mode m_mode; + struct Capabilities + { + QList<int> m_frequencies; + QList<int> m_channels; + QList<int> m_sampleSizes; + QList<QAudioFormat::Endian> m_byteOrders; + QList<QAudioFormat::SampleType> m_sampleTypes; + }; + // Mutable to allow lazy initialization when called from const-qualified // public functions (isFormatSupported, nearestFormat) mutable bool m_updated; - mutable QStringList m_codecs; - mutable QList<int> m_frequencies; - mutable QList<int> m_channels; - mutable QList<int> m_sampleSizes; - mutable QList<QAudioFormat::Endian> m_byteOrders; - mutable QList<QAudioFormat::SampleType> m_sampleTypes; + mutable QMap<QString, Capabilities> m_capabilities; + mutable Capabilities m_unionCapabilities; }; QT_END_NAMESPACE diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index c99e870..a1708f1 100644 --- a/src/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/audio/qaudioinput.cpp @@ -211,6 +211,10 @@ QAudioInput::~QAudioInput() If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + In either case, the stateChanged() signal may be emitted either synchronously + during execution of the start() function or asynchronously after start() has + returned to the caller. + \sa {Symbian Platform Security Requirements} \sa QIODevice @@ -233,6 +237,10 @@ void QAudioInput::start(QIODevice* device) If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + In either case, the stateChanged() signal may be emitted either synchronously + during execution of the start() function or asynchronously after start() has + returned to the caller. + \sa {Symbian Platform Security Requirements} \sa QIODevice @@ -278,6 +286,8 @@ void QAudioInput::reset() Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and emit stateChanged() signal. + + Note: signal will always be emitted during execution of the resume() function. */ void QAudioInput::suspend() diff --git a/src/multimedia/audio/qaudioinput_symbian_p.cpp b/src/multimedia/audio/qaudioinput_symbian_p.cpp index 52daa88..9d240ca 100644 --- a/src/multimedia/audio/qaudioinput_symbian_p.cpp +++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp @@ -116,16 +116,16 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, , m_pullMode(false) , m_sink(0) , m_pullTimer(new QTimer(this)) + , m_devSound(0) , m_devSoundBuffer(0) , m_devSoundBufferSize(0) , m_totalBytesReady(0) , m_devSoundBufferPos(0) , m_totalSamplesRecorded(0) { - connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); + qRegisterMetaType<CMMFBuffer *>("CMMFBuffer *"); - SymbianAudio::Utils::formatQtToNative(m_format, m_nativeFourCC, - m_nativeFormat); + connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); m_pullTimer->setInterval(PushInterval); connect(m_pullTimer.data(), SIGNAL(timeout()), this, SLOT(pullData())); @@ -164,7 +164,7 @@ void QAudioInputPrivate::stop() void QAudioInputPrivate::reset() { m_totalSamplesRecorded += getSamplesRecorded(); - m_devSound->Stop(); + m_devSound->stop(); startRecording(); } @@ -174,7 +174,7 @@ void QAudioInputPrivate::suspend() || SymbianAudio::IdleState == m_internalState) { m_notifyTimer->stop(); m_pullTimer->stop(); - m_devSound->Pause(); + m_devSound->pause(); const qint64 samplesRecorded = getSamplesRecorded(); m_totalSamplesRecorded += samplesRecorded; @@ -189,8 +189,11 @@ void QAudioInputPrivate::suspend() void QAudioInputPrivate::resume() { - if (SymbianAudio::SuspendedState == m_internalState) + if (SymbianAudio::SuspendedState == m_internalState) { + if (!m_pullMode && !bytesReady()) + m_devSound->start(); startDataTransfer(); + } } int QAudioInputPrivate::bytesReady() const @@ -224,11 +227,14 @@ int QAudioInputPrivate::bufferSize() const void QAudioInputPrivate::setNotifyInterval(int ms) { - if (ms > 0) { + if (ms >= 0) { const int oldNotifyInterval = m_notifyInterval; m_notifyInterval = ms; - if (m_notifyTimer->isActive() && ms != oldNotifyInterval) + if (m_notifyInterval && (SymbianAudio::ActiveState == m_internalState || + SymbianAudio::IdleState == m_internalState)) m_notifyTimer->start(m_notifyInterval); + else + m_notifyTimer->stop(); } } @@ -275,88 +281,6 @@ QAudioFormat QAudioInputPrivate::format() const return m_format; } -//----------------------------------------------------------------------------- -// MDevSoundObserver implementation -//----------------------------------------------------------------------------- - -void QAudioInputPrivate::InitializeComplete(TInt aError) -{ - Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, - Q_FUNC_INFO, "Invalid state"); - - if (KErrNone == aError) - startRecording(); -} - -void QAudioInputPrivate::ToneFinished(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound's tone playback functions, so should - // never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::BufferToBeFilled(CMMFBuffer *aBuffer) -{ - Q_UNUSED(aBuffer) - // This class doesn't use DevSound in play mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::PlayError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound in play mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::BufferToBeEmptied(CMMFBuffer *aBuffer) -{ - // Following receipt of this callback, DevSound should not provide another - // buffer until we have returned the current one. - Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held"); - - CMMFDataBuffer *const buffer = static_cast<CMMFDataBuffer*>(aBuffer); - - if (!m_devSoundBufferSize) - m_devSoundBufferSize = buffer->Data().MaxLength(); - - m_totalBytesReady += buffer->Data().Length(); - - if (SymbianAudio::SuspendedState == m_internalState) { - m_devSoundBufferQ.append(buffer); - } else { - // Will be returned to DevSound by bufferEmptied(). - m_devSoundBuffer = buffer; - m_devSoundBufferPos = 0; - - if (bytesReady() && !m_pullMode) - pushData(); - } -} - -void QAudioInputPrivate::RecordError(TInt aError) -{ - Q_UNUSED(aError) - setError(QAudio::IOError); -} - -void QAudioInputPrivate::ConvertError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound's format conversion functions, so - // should never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg) -{ - Q_UNUSED(aMessageType) - Q_UNUSED(aMsg) - // Ignore this callback. -} //----------------------------------------------------------------------------- // Private functions @@ -367,33 +291,30 @@ void QAudioInputPrivate::open() Q_ASSERT_X(SymbianAudio::ClosedState == m_internalState, Q_FUNC_INFO, "DevSound already opened"); - QT_TRAP_THROWING( m_devSound.reset(CMMFDevSound::NewL()) ) - - QScopedPointer<SymbianAudio::DevSoundCapabilities> caps( - new SymbianAudio::DevSoundCapabilities(*m_devSound, QAudio::AudioInput)); + Q_ASSERT(!m_devSound); + m_devSound = new SymbianAudio::DevSoundWrapper(QAudio::AudioInput, this); - int err = SymbianAudio::Utils::isFormatSupported(m_format, *caps) ? - KErrNone : KErrNotSupported; - - if (KErrNone == err) { - setState(SymbianAudio::InitializingState); - TRAP(err, m_devSound->InitializeL(*this, m_nativeFourCC, - EMMFStateRecording)); - } + connect(m_devSound, SIGNAL(initializeComplete(int)), + this, SLOT(devsoundInitializeComplete(int))); + connect(m_devSound, SIGNAL(bufferToBeProcessed(CMMFBuffer *)), + this, SLOT(devsoundBufferToBeEmptied(CMMFBuffer *))); + connect(m_devSound, SIGNAL(processingError(int)), + this, SLOT(devsoundRecordError(int))); - if (KErrNone != err) { - setError(QAudio::OpenError); - m_devSound.reset(); - } + setState(SymbianAudio::InitializingState); + m_devSound->initialize(m_format.codec()); } void QAudioInputPrivate::startRecording() { - const int samplesRecorded = m_devSound->SamplesRecorded(); + const int samplesRecorded = m_devSound->samplesProcessed(); Q_ASSERT(samplesRecorded == 0); - TRAPD(err, startDevSoundL()); - if (KErrNone == err) { + bool ok = m_devSound->setFormat(m_format); + if (ok) + ok = m_devSound->start(); + + if (ok) { startDataTransfer(); } else { setError(QAudio::OpenError); @@ -401,17 +322,10 @@ void QAudioInputPrivate::startRecording() } } -void QAudioInputPrivate::startDevSoundL() -{ - TMMFCapabilities nativeFormat = m_devSound->Config(); - m_nativeFormat.iBufferSize = nativeFormat.iBufferSize; - m_devSound->SetConfigL(m_nativeFormat); - m_devSound->RecordInitL(); -} - void QAudioInputPrivate::startDataTransfer() { - m_notifyTimer->start(m_notifyInterval); + if (m_notifyInterval) + m_notifyTimer->start(m_notifyInterval); if (m_pullMode) m_pullTimer->start(); @@ -503,6 +417,48 @@ void QAudioInputPrivate::pullData() } } +void QAudioInputPrivate::devsoundInitializeComplete(int err) +{ + Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, + Q_FUNC_INFO, "Invalid state"); + + if (!err && m_devSound->isFormatSupported(m_format)) + startRecording(); + else + setError(QAudio::OpenError); +} + +void QAudioInputPrivate::devsoundBufferToBeEmptied(CMMFBuffer *baseBuffer) +{ + // Following receipt of this signal, DevSound should not provide another + // buffer until we have returned the current one. + Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held"); + + CMMFDataBuffer *const buffer = static_cast<CMMFDataBuffer*>(baseBuffer); + + if (!m_devSoundBufferSize) + m_devSoundBufferSize = buffer->Data().MaxLength(); + + m_totalBytesReady += buffer->Data().Length(); + + if (SymbianAudio::SuspendedState == m_internalState) { + m_devSoundBufferQ.append(buffer); + } else { + // Will be returned to DevSoundWrapper by bufferProcessed(). + m_devSoundBuffer = buffer; + m_devSoundBufferPos = 0; + + if (bytesReady() && !m_pullMode) + pushData(); + } +} + +void QAudioInputPrivate::devsoundRecordError(int err) +{ + Q_UNUSED(err) + setError(QAudio::IOError); +} + void QAudioInputPrivate::bufferEmptied() { m_devSoundBufferPos = 0; @@ -510,7 +466,7 @@ void QAudioInputPrivate::bufferEmptied() if (m_devSoundBuffer) { m_totalBytesReady -= m_devSoundBuffer->Data().Length(); m_devSoundBuffer = 0; - m_devSound->RecordData(); + m_devSound->bufferProcessed(); } else { Q_ASSERT(!m_devSoundBufferQ.empty()); m_totalBytesReady -= m_devSoundBufferQ.front()->Data().Length(); @@ -518,7 +474,8 @@ void QAudioInputPrivate::bufferEmptied() // If the queue has been emptied, resume transfer from the hardware if (m_devSoundBufferQ.empty()) - m_devSound->RecordInitL(); + if (!m_devSound->start()) + setError(QAudio::IOError); } Q_ASSERT(m_totalBytesReady >= 0); @@ -532,8 +489,10 @@ void QAudioInputPrivate::close() m_error = QAudio::NoError; if (m_devSound) - m_devSound->Stop(); - m_devSound.reset(); + m_devSound->stop(); + delete m_devSound; + m_devSound = 0; + m_devSoundBuffer = 0; m_devSoundBufferSize = 0; m_totalBytesReady = 0; @@ -554,7 +513,7 @@ qint64 QAudioInputPrivate::getSamplesRecorded() const { qint64 result = 0; if (m_devSound) - result = qint64(m_devSound->SamplesRecorded()); + result = qint64(m_devSound->samplesProcessed()); return result; } @@ -565,30 +524,28 @@ void QAudioInputPrivate::setError(QAudio::Error error) // Although no state transition actually occurs here, a stateChanged event // must be emitted to inform the client that the call to start() was // unsuccessful. - if (QAudio::OpenError == error) + if (QAudio::OpenError == error) { emit stateChanged(QAudio::StoppedState); - - // Close the DevSound instance. This causes a transition to StoppedState. - // This must be done asynchronously in case the current function was called - // from a DevSound event handler, in which case deleting the DevSound - // instance may cause an exception. - QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } else { + if (QAudio::UnderrunError == error) + setState(SymbianAudio::IdleState); + else + // Close the DevSound instance. This causes a transition to + // StoppedState. This must be done asynchronously in case the + // current function was called from a DevSound event handler, in which + // case deleting the DevSound instance may cause an exception. + QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } } void QAudioInputPrivate::setState(SymbianAudio::State newInternalState) { const QAudio::State oldExternalState = m_externalState; m_internalState = newInternalState; - m_externalState = SymbianAudio::Utils::stateNativeToQt( - m_internalState, initializingState()); + m_externalState = SymbianAudio::Utils::stateNativeToQt(m_internalState); if (m_externalState != oldExternalState) emit stateChanged(m_externalState); } -QAudio::State QAudioInputPrivate::initializingState() const -{ - return QAudio::IdleState; -} - QT_END_NAMESPACE diff --git a/src/multimedia/audio/qaudioinput_symbian_p.h b/src/multimedia/audio/qaudioinput_symbian_p.h index ca3ccf7..7417655 100644 --- a/src/multimedia/audio/qaudioinput_symbian_p.h +++ b/src/multimedia/audio/qaudioinput_symbian_p.h @@ -56,7 +56,6 @@ #include <QtMultimedia/qaudioengine.h> #include <QTime> #include <QTimer> -#include <sounddevice.h> #include "qaudio_symbian_p.h" QT_BEGIN_NAMESPACE @@ -82,7 +81,6 @@ private: class QAudioInputPrivate : public QAbstractAudioInput - , public MDevSoundObserver { friend class SymbianAudioInputPrivate; Q_OBJECT @@ -109,23 +107,15 @@ public: QAudio::State state() const; QAudioFormat format() const; - // MDevSoundObserver - void InitializeComplete(TInt aError); - void ToneFinished(TInt aError); - void BufferToBeFilled(CMMFBuffer *aBuffer); - void PlayError(TInt aError); - void BufferToBeEmptied(CMMFBuffer *aBuffer); - void RecordError(TInt aError); - void ConvertError(TInt aError); - void DeviceMessage(TUid aMessageType, const TDesC8 &aMsg); - private slots: void pullData(); + void devsoundInitializeComplete(int err); + void devsoundBufferToBeEmptied(CMMFBuffer *); + void devsoundRecordError(int err); private: void open(); void startRecording(); - void startDevSoundL(); void startDataTransfer(); CMMFDataBuffer* currentBuffer() const; void pushData(); @@ -138,8 +128,6 @@ private: void setError(QAudio::Error error); void setState(SymbianAudio::State state); - QAudio::State initializingState() const; - private: const QByteArray m_device; const QAudioFormat m_format; @@ -158,9 +146,7 @@ private: QScopedPointer<QTimer> m_pullTimer; - QScopedPointer<CMMFDevSound> m_devSound; - TUint32 m_nativeFourCC; - TMMFCapabilities m_nativeFormat; + SymbianAudio::DevSoundWrapper* m_devSound; // Latest buffer provided by DevSound, to be empied of data. CMMFDataBuffer *m_devSoundBuffer; diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index b0b5244..371773c 100644 --- a/src/multimedia/audio/qaudiooutput.cpp +++ b/src/multimedia/audio/qaudiooutput.cpp @@ -209,6 +209,10 @@ QAudioFormat QAudioOutput::format() const If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + In either case, the stateChanged() signal may be emitted either synchronously + during execution of the start() function or asynchronously after start() has + returned to the caller. + \sa QIODevice */ @@ -228,6 +232,10 @@ void QAudioOutput::start(QIODevice* device) If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + In either case, the stateChanged() signal may be emitted either synchronously + during execution of the start() function or asynchronously after start() has + returned to the caller. + \sa QIODevice */ @@ -276,6 +284,8 @@ void QAudioOutput::suspend() Sets state() to QAudio::ActiveState if you previously called start(QIODevice*). Sets state() to QAudio::IdleState if you previously called start(). emits stateChanged() signal. + + Note: signal will always be emitted during execution of the resume() function. */ void QAudioOutput::resume() diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index 3f8e933..5098469 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -110,6 +110,7 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, , m_externalState(QAudio::StoppedState) , m_pullMode(false) , m_source(0) + , m_devSound(0) , m_devSoundBuffer(0) , m_devSoundBufferSize(0) , m_bytesWritten(0) @@ -121,10 +122,9 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, , m_samplesPlayed(0) , m_totalSamplesPlayed(0) { - connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); + qRegisterMetaType<CMMFBuffer *>("CMMFBuffer *"); - SymbianAudio::Utils::formatQtToNative(m_format, m_nativeFourCC, - m_nativeFormat); + connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); m_underflowTimer->setInterval(UnderflowTimerInterval); connect(m_underflowTimer.data(), SIGNAL(timeout()), this, @@ -140,8 +140,6 @@ QIODevice* QAudioOutputPrivate::start(QIODevice *device) { stop(); - // We have to set these before the call to open() because of the - // logic in initializingState() if (device) { m_pullMode = true; m_source = device; @@ -171,7 +169,7 @@ void QAudioOutputPrivate::stop() void QAudioOutputPrivate::reset() { m_totalSamplesPlayed += getSamplesPlayed(); - m_devSound->Stop(); + m_devSound->stop(); m_bytesPadding = 0; startPlayback(); } @@ -196,11 +194,12 @@ void QAudioOutputPrivate::suspend() // Because this causes buffered data to be dropped, we replace the // lost data with silence following a call to resume(), in order to // ensure that processedUSecs() returns the correct value. - m_devSound->Stop(); + m_devSound->stop(); m_totalSamplesPlayed += samplesPlayed; // Calculate the amount of data dropped const qint64 paddingSamples = samplesWritten - samplesPlayed; + Q_ASSERT(paddingSamples >= 0); m_bytesPadding = SymbianAudio::Utils::samplesToBytes(m_format, paddingSamples); @@ -210,8 +209,11 @@ void QAudioOutputPrivate::suspend() void QAudioOutputPrivate::resume() { - if (SymbianAudio::SuspendedState == m_internalState) + if (SymbianAudio::SuspendedState == m_internalState) { + if (!m_pullMode && m_devSoundBuffer && m_devSoundBuffer->Data().Length()) + bufferFilled(); startPlayback(); + } } int QAudioOutputPrivate::bytesFree() const @@ -249,11 +251,14 @@ int QAudioOutputPrivate::bufferSize() const void QAudioOutputPrivate::setNotifyInterval(int ms) { - if (ms > 0) { + if (ms >= 0) { const int oldNotifyInterval = m_notifyInterval; m_notifyInterval = ms; - if (m_notifyTimer->isActive() && ms != oldNotifyInterval) + if (m_notifyInterval && (SymbianAudio::ActiveState == m_internalState || + SymbianAudio::IdleState == m_internalState)) m_notifyTimer->start(m_notifyInterval); + else + m_notifyTimer->stop(); } } @@ -300,35 +305,52 @@ QAudioFormat QAudioOutputPrivate::format() const return m_format; } + //----------------------------------------------------------------------------- -// MDevSoundObserver implementation +// Private functions //----------------------------------------------------------------------------- -void QAudioOutputPrivate::InitializeComplete(TInt aError) +void QAudioOutputPrivate::dataReady() { - Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, - Q_FUNC_INFO, "Invalid state"); + // Client-provided QIODevice has data ready to read. - if (KErrNone == aError) - startPlayback(); + Q_ASSERT_X(m_source->bytesAvailable(), Q_FUNC_INFO, + "readyRead signal received, but no data available"); + + if (!m_bytesPadding) + pullData(); } -void QAudioOutputPrivate::ToneFinished(TInt aError) +void QAudioOutputPrivate::underflowTimerExpired() { - Q_UNUSED(aError) - // This class doesn't use DevSound's tone playback functions, so should - // never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); + const TInt samplesPlayed = getSamplesPlayed(); + if (m_samplesPlayed && (samplesPlayed == m_samplesPlayed)) { + setError(QAudio::UnderrunError); + } else { + m_samplesPlayed = samplesPlayed; + m_underflowTimer->start(); + } +} + +void QAudioOutputPrivate::devsoundInitializeComplete(int err) +{ + Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, + Q_FUNC_INFO, "Invalid state"); + + if (!err && m_devSound->isFormatSupported(m_format)) + startPlayback(); + else + setError(QAudio::OpenError); } -void QAudioOutputPrivate::BufferToBeFilled(CMMFBuffer *aBuffer) +void QAudioOutputPrivate::devsoundBufferToBeFilled(CMMFBuffer *bufferBase) { - // Following receipt of this callback, DevSound should not provide another + // Following receipt of this signal, DevSound should not provide another // buffer until we have returned the current one. Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held"); - // Will be returned to DevSound by bufferFilled(). - m_devSoundBuffer = static_cast<CMMFDataBuffer*>(aBuffer); + // Will be returned to DevSoundWrapper by bufferProcessed(). + m_devSoundBuffer = static_cast<CMMFDataBuffer*>(bufferBase); if (!m_devSoundBufferSize) m_devSoundBufferSize = m_devSoundBuffer->Data().MaxLength(); @@ -339,9 +361,9 @@ void QAudioOutputPrivate::BufferToBeFilled(CMMFBuffer *aBuffer) pullData(); } -void QAudioOutputPrivate::PlayError(TInt aError) +void QAudioOutputPrivate::devsoundPlayError(int err) { - switch (aError) { + switch (err) { case KErrUnderflow: m_underflow = true; if (m_pullMode && !m_lastBuffer) @@ -355,102 +377,42 @@ void QAudioOutputPrivate::PlayError(TInt aError) } } -void QAudioOutputPrivate::BufferToBeEmptied(CMMFBuffer *aBuffer) -{ - Q_UNUSED(aBuffer) - // This class doesn't use DevSound in record mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioOutputPrivate::RecordError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound in record mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioOutputPrivate::ConvertError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound's format conversion functions, so - // should never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioOutputPrivate::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg) -{ - Q_UNUSED(aMessageType) - Q_UNUSED(aMsg) - // Ignore this callback. -} - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -void QAudioOutputPrivate::dataReady() -{ - // Client-provided QIODevice has data ready to read. - - Q_ASSERT_X(m_source->bytesAvailable(), Q_FUNC_INFO, - "readyRead signal received, but no data available"); - - if (!m_bytesPadding) - pullData(); -} - -void QAudioOutputPrivate::underflowTimerExpired() -{ - const TInt samplesPlayed = getSamplesPlayed(); - if (m_samplesPlayed && (samplesPlayed == m_samplesPlayed)) { - setError(QAudio::UnderrunError); - } else { - m_samplesPlayed = samplesPlayed; - m_underflowTimer->start(); - } -} - void QAudioOutputPrivate::open() { Q_ASSERT_X(SymbianAudio::ClosedState == m_internalState, Q_FUNC_INFO, "DevSound already opened"); - QT_TRAP_THROWING( m_devSound.reset(CMMFDevSound::NewL()) ) - - QScopedPointer<SymbianAudio::DevSoundCapabilities> caps( - new SymbianAudio::DevSoundCapabilities(*m_devSound, - QAudio::AudioOutput)); + Q_ASSERT(!m_devSound); + m_devSound = new SymbianAudio::DevSoundWrapper(QAudio::AudioOutput, this); - int err = SymbianAudio::Utils::isFormatSupported(m_format, *caps) ? - KErrNone : KErrNotSupported; + connect(m_devSound, SIGNAL(initializeComplete(int)), + this, SLOT(devsoundInitializeComplete(int))); + connect(m_devSound, SIGNAL(bufferToBeProcessed(CMMFBuffer *)), + this, SLOT(devsoundBufferToBeFilled(CMMFBuffer *))); + connect(m_devSound, SIGNAL(processingError(int)), + this, SLOT(devsoundPlayError(int))); - if (KErrNone == err) { - setState(SymbianAudio::InitializingState); - TRAP(err, m_devSound->InitializeL(*this, m_nativeFourCC, - EMMFStatePlaying)); - } - - if (KErrNone != err) { - setError(QAudio::OpenError); - m_devSound.reset(); - } + setState(SymbianAudio::InitializingState); + m_devSound->initialize(m_format.codec()); } void QAudioOutputPrivate::startPlayback() { - TRAPD(err, startDevSoundL()); - if (KErrNone == err) { + bool ok = m_devSound->setFormat(m_format); + if (ok) + ok = m_devSound->start(); + + if (ok) { if (isDataReady()) setState(SymbianAudio::ActiveState); else setState(SymbianAudio::IdleState); - m_notifyTimer->start(m_notifyInterval); + if (m_notifyInterval) + m_notifyTimer->start(m_notifyInterval); m_underflow = false; - Q_ASSERT(m_devSound->SamplesPlayed() == 0); + Q_ASSERT(m_devSound->samplesProcessed() == 0); writePaddingData(); @@ -462,14 +424,6 @@ void QAudioOutputPrivate::startPlayback() } } -void QAudioOutputPrivate::startDevSoundL() -{ - TMMFCapabilities nativeFormat = m_devSound->Config(); - m_nativeFormat.iBufferSize = nativeFormat.iBufferSize; - m_devSound->SetConfigL(m_nativeFormat); - m_devSound->PlayInitL(); -} - void QAudioOutputPrivate::writePaddingData() { // See comments in suspend() @@ -486,10 +440,11 @@ void QAudioOutputPrivate::writePaddingData() Mem::FillZ(ptr, paddingBytes); outputBuffer.SetLength(outputBuffer.Length() + paddingBytes); m_bytesPadding -= paddingBytes; + Q_ASSERT(m_bytesPadding >= 0); if (m_pullMode && m_source->atEnd()) lastBufferFilled(); - if (paddingBytes == outputBytes) + if ((paddingBytes == outputBytes) || !m_bytesPadding) bufferFilled(); } } @@ -543,9 +498,6 @@ void QAudioOutputPrivate::pullData() Q_ASSERT_X(m_pullMode, Q_FUNC_INFO, "pullData called when in push mode"); - if (m_bytesPadding) - m_bytesPadding = 1; - // writePaddingData() is called by BufferToBeFilled() before pullData(), // so we should never have any padding data left at this point. Q_ASSERT_X(0 == m_bytesPadding, Q_FUNC_INFO, @@ -590,7 +542,7 @@ void QAudioOutputPrivate::bufferFilled() if (QAudio::UnderrunError == m_error) m_error = QAudio::NoError; - m_devSound->PlayData(); + m_devSound->bufferProcessed(); } void QAudioOutputPrivate::lastBufferFilled() @@ -610,8 +562,10 @@ void QAudioOutputPrivate::close() m_error = QAudio::NoError; if (m_devSound) - m_devSound->Stop(); - m_devSound.reset(); + m_devSound->stop(); + delete m_devSound; + m_devSound = 0; + m_devSoundBuffer = 0; m_devSoundBufferSize = 0; @@ -644,7 +598,7 @@ qint64 QAudioOutputPrivate::getSamplesPlayed() const // This is necessary because some DevSound implementations report // that they have played more data than has actually been provided to them // by the client. - const qint64 devSoundSamplesPlayed(m_devSound->SamplesPlayed()); + const qint64 devSoundSamplesPlayed(m_devSound->samplesProcessed()); result = qMin(devSoundSamplesPlayed, samplesWritten); } } @@ -658,25 +612,25 @@ void QAudioOutputPrivate::setError(QAudio::Error error) // Although no state transition actually occurs here, a stateChanged event // must be emitted to inform the client that the call to start() was // unsuccessful. - if (QAudio::OpenError == error) + if (QAudio::OpenError == error) { emit stateChanged(QAudio::StoppedState); - - if (QAudio::UnderrunError == error) - setState(SymbianAudio::IdleState); - else - // Close the DevSound instance. This causes a transition to - // StoppedState. This must be done asynchronously in case the - // current function was called from a DevSound event handler, in which - // case deleting the DevSound instance may cause an exception. - QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } else { + if (QAudio::UnderrunError == error) + setState(SymbianAudio::IdleState); + else + // Close the DevSound instance. This causes a transition to + // StoppedState. This must be done asynchronously in case the + // current function was called from a DevSound event handler, in which + // case deleting the DevSound instance may cause an exception. + QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } } void QAudioOutputPrivate::setState(SymbianAudio::State newInternalState) { const QAudio::State oldExternalState = m_externalState; m_internalState = newInternalState; - m_externalState = SymbianAudio::Utils::stateNativeToQt( - m_internalState, initializingState()); + m_externalState = SymbianAudio::Utils::stateNativeToQt(m_internalState); if (m_externalState != oldExternalState) emit stateChanged(m_externalState); @@ -689,9 +643,4 @@ bool QAudioOutputPrivate::isDataReady() const || m_pushDataReady; } -QAudio::State QAudioOutputPrivate::initializingState() const -{ - return isDataReady() ? QAudio::ActiveState : QAudio::IdleState; -} - QT_END_NAMESPACE diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.h b/src/multimedia/audio/qaudiooutput_symbian_p.h index 00ccb24..c0acb07 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.h +++ b/src/multimedia/audio/qaudiooutput_symbian_p.h @@ -80,7 +80,6 @@ private: class QAudioOutputPrivate : public QAbstractAudioOutput - , public MDevSoundObserver { friend class SymbianAudioOutputPrivate; Q_OBJECT @@ -107,24 +106,16 @@ public: QAudio::State state() const; QAudioFormat format() const; - // MDevSoundObserver - void InitializeComplete(TInt aError); - void ToneFinished(TInt aError); - void BufferToBeFilled(CMMFBuffer *aBuffer); - void PlayError(TInt aError); - void BufferToBeEmptied(CMMFBuffer *aBuffer); - void RecordError(TInt aError); - void ConvertError(TInt aError); - void DeviceMessage(TUid aMessageType, const TDesC8 &aMsg); - private slots: void dataReady(); void underflowTimerExpired(); + void devsoundInitializeComplete(int err); + void devsoundBufferToBeFilled(CMMFBuffer *); + void devsoundPlayError(int err); private: void open(); void startPlayback(); - void startDevSoundL(); void writePaddingData(); qint64 pushData(const char *data, qint64 len); void pullData(); @@ -138,7 +129,6 @@ private: void setState(SymbianAudio::State state); bool isDataReady() const; - QAudio::State initializingState() const; private: const QByteArray m_device; @@ -156,9 +146,7 @@ private: bool m_pullMode; QIODevice *m_source; - QScopedPointer<CMMFDevSound> m_devSound; - TUint32 m_nativeFourCC; - TMMFCapabilities m_nativeFormat; + SymbianAudio::DevSoundWrapper* m_devSound; // Buffer provided by DevSound, to be filled with data. CMMFDataBuffer *m_devSoundBuffer; diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 83109b5..8dffebb 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3189,6 +3189,32 @@ void tst_QUrl::ace_testsuite_data() QTest::newRow("separator-3002") << QString::fromUtf8("example\343\200\202com") << "example.com" << "." << "example.com"; + + QString egyptianIDN = + QString::fromUtf8("\331\210\330\262\330\247\330\261\330\251\055\330\247\331\204\330" + "\243\330\252\330\265\330\247\331\204\330\247\330\252.\331\205" + "\330\265\330\261"); + QTest::newRow("egyptian-tld-ace") + << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" + << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" + << "." + << egyptianIDN; + QTest::newRow("egyptian-tld-unicode") + << egyptianIDN + << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" + << "." + << egyptianIDN; + QTest::newRow("egyptian-tld-mix1") + << QString::fromUtf8("\331\210\330\262\330\247\330\261\330\251\055\330\247\331\204\330" + "\243\330\252\330\265\330\247\331\204\330\247\330\252.xn--wgbh1c") + << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" + << "." + << egyptianIDN; + QTest::newRow("egyptian-tld-mix2") + << QString::fromUtf8("xn----rmckbbajlc6dj7bxne2c.\331\205\330\265\330\261") + << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" + << "." + << egyptianIDN; } void tst_QUrl::ace_testsuite() |