From 616d84ddb2a07191d2754b0f3e7296cae472b738 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Fri, 17 Sep 2010 12:42:05 +0300 Subject: Panic in qs60style.cpp while drawing a QTreeView QS60Style crashes when running a test application that modifies active style AND application's palette. After switching to other style, setting palette to application default, re-enabling the style's palette and activating QS60Style, causes a crash. This is due to that internal theme palette is tried to access, before it is constructed. Fixed by making sure that when theme palette is accessed, it is not NULL. Task-number: QTBUG-13553 Reviewed-by: Miikka Heikkinen --- src/gui/styles/qs60style.cpp | 36 +++++++++++++++++++++++++----------- src/gui/styles/qs60style_p.h | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 971e1e3..d529dd5 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -491,6 +491,24 @@ QPalette* QS60StylePrivate::themePalette() return m_themePalette; } +bool QS60StylePrivate::equalToThemePalette(QColor color, QPalette::ColorRole role) +{ + if (!m_themePalette) + return false; + if (color == m_themePalette->color(role)) + return true; + return false; +} + +bool QS60StylePrivate::equalToThemePalette(qint64 cacheKey, QPalette::ColorRole role) +{ + if (!m_themePalette) + return false; + if (cacheKey == m_themePalette->brush(role).texture().cacheKey()) + return true; + return false; +} + void QS60StylePrivate::setBackgroundTexture(QApplication *app) const { Q_UNUSED(app) @@ -2050,7 +2068,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, } break; case CE_Splitter: - if (option->state & State_Sunken && option->state & State_Enabled) { + if (option->state & State_Sunken && option->state & State_Enabled && QS60StylePrivate::themePalette()) { painter->save(); painter->setOpacity(0.5); painter->setBrush(QS60StylePrivate::themePalette()->light()); @@ -2077,7 +2095,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_FrameFocusRect: { //Draw themed highlight to radiobuttons and checkboxes. //For other widgets skip, unless palette has been modified. In that case, draw with commonstyle. - if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) { + if (QS60StylePrivate::equalToThemePalette(option->palette.highlight().color(), QPalette::Highlight)) { if ((qstyleoption_cast(option) && (qobject_cast(widget) || qobject_cast(widget)))) QS60StylePrivate::drawSkinElement( @@ -2109,11 +2127,8 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff; painter->save(); - const QColor themeColor = QS60StylePrivate::themePalette()->windowText().color(); - const QColor windowTextColor = option->palette.windowText().color(); - - if (themeColor != windowTextColor) - painter->setPen(windowTextColor); + if (QS60StylePrivate::equalToThemePalette(option->palette.windowText().color(), QPalette::WindowText)) + painter->setPen(option->palette.windowText().color()); QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags | QS60StylePrivate::SF_ColorSkinned ); painter->restore(); @@ -2266,8 +2281,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti ) { //Need extra check since dialogs have their own theme background if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) && - option->palette.window().texture().cacheKey() == - QS60StylePrivate::m_themePalette->window().texture().cacheKey()) + QS60StylePrivate::equalToThemePalette(option->palette.window().texture().cacheKey(), QPalette::Window)) //todo: for combobox listviews, the background should include area for menu scrollers, //but this produces drawing issues as we need to turn clipping off. QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, option->rect, flags); @@ -2314,7 +2328,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti const bool hasFocus = (vopt->state & State_HasFocus); const bool isPressed = QS60StylePrivate::isWidgetPressed(widget); - if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) { + if (QS60StylePrivate::equalToThemePalette(option->palette.highlight().color(), QPalette::Highlight)) { QRect highlightRect = vopt->rect.adjusted(1,1,-1,-1); const QAbstractItemView *itemView = qobject_cast(widget); QAbstractItemView::SelectionBehavior selectionBehavior = @@ -2439,7 +2453,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_PanelItemViewRow: // ### Qt 5: remove #ifndef QT_NO_ITEMVIEWS if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { - if (vopt->palette.base().texture().cacheKey() != QS60StylePrivate::m_themePalette->base().texture().cacheKey()) { + if (QS60StylePrivate::equalToThemePalette(vopt->palette.base().texture().cacheKey(), QPalette::Base)) { //QPalette::Base has been changed, let commonstyle draw the item commonStyleDraws = true; } else { diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 51ced96..b3f4160 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -598,6 +598,8 @@ private: void setThemePaletteHash(QPalette *palette) const; static void storeThemePalette(QPalette *palette); static void deleteThemePalette(); + static bool equalToThemePalette(QColor color, QPalette::ColorRole role); + static bool equalToThemePalette(qint64 cacheKey, QPalette::ColorRole role); static QSize partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags = KDefaultSkinElementFlags); -- cgit v0.12 From 9d9fc57b4af91eab681abb07c0924c71c1374537 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 17 Sep 2010 12:49:05 +0300 Subject: Remove pre-Symbian3 plugins from Symbian3 and later builds Symbian3 and later builds are not compatible with pre-Symbian3 phones anyway, so no need to build and deploy older version plugins when building for Symbian3 or later. Task-number: QT-3949 Reviewed-by: Janne Koskinen --- src/plugins/bearer/symbian/symbian.pri | 6 ++--- src/plugins/bearer/symbian/symbian.pro | 7 ++++- src/plugins/s60/s60.pro | 10 ++++++- src/s60installs/s60installs.pro | 48 ++++++++++++++++++++-------------- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/plugins/bearer/symbian/symbian.pri b/src/plugins/bearer/symbian/symbian.pri index 9b3f50c..e874945 100644 --- a/src/plugins/bearer/symbian/symbian.pri +++ b/src/plugins/bearer/symbian/symbian.pri @@ -22,11 +22,9 @@ LIBS += -lcommdb \ -lnetmeta is_using_gnupoc { - LIBS += -lconnmon \ - -lapsettingshandlerui + LIBS += -lconnmon } else { - LIBS += -lConnMon \ - -lApSettingsHandlerUI + LIBS += -lConnMon } QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer diff --git a/src/plugins/bearer/symbian/symbian.pro b/src/plugins/bearer/symbian/symbian.pro index f320eb6..91f8217 100644 --- a/src/plugins/bearer/symbian/symbian.pro +++ b/src/plugins/bearer/symbian/symbian.pro @@ -1,3 +1,8 @@ TEMPLATE = subdirs -SUBDIRS += 3_1 3_2 symbian_3 \ No newline at end of file +contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + SUBDIRS += 3_1 3_2 +} + +# Symbian3 builds the default plugin for winscw so it is always needed +SUBDIRS += symbian_3 \ No newline at end of file diff --git a/src/plugins/s60/s60.pro b/src/plugins/s60/s60.pro index 8ae639c..c999fff 100644 --- a/src/plugins/s60/s60.pro +++ b/src/plugins/s60/s60.pro @@ -1,3 +1,11 @@ TEMPLATE = subdirs -symbian:SUBDIRS = 3_1 3_2 5_0 + +symbian { + contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + SUBDIRS += 3_1 3_2 + } + + # 5.0 is used also for Symbian3 and later + SUBDIRS += 5_0 +} \ No newline at end of file diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 9e1d582..1f622c0 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -65,26 +65,36 @@ symbian: { bearerStubZ = $${PWD}/qsymbianbearer.qtplugin } - qts60plugindeployment = \ - "IF package(0x20022E6D)" \ - " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ - " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ - "ELSEIF package(0x1028315F)" \ - " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ - " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_2.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ - "ELSEIF package(0x102752AE)" \ - " \"$$pluginLocations/qts60plugin_3_2$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_2$${QT_LIBINFIX}.dll\"" \ - " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_2.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ - "ELSEIF package(0x102032BE)" \ - " \"$$pluginLocations/qts60plugin_3_1$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_1$${QT_LIBINFIX}.dll\"" \ - " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_1.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ - "ELSE" \ - " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ - " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ - "ENDIF" \ - " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\" - qtlibraries.pkg_postrules += qts60plugindeployment + contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + qts60plugindeployment = \ + "IF package(0x20022E6D)" \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ + " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ + "ELSEIF package(0x1028315F)" \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ + " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_2.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ + "ELSEIF package(0x102752AE)" \ + " \"$$pluginLocations/qts60plugin_3_2$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_2$${QT_LIBINFIX}.dll\"" \ + " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_2.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ + "ELSEIF package(0x102032BE)" \ + " \"$$pluginLocations/qts60plugin_3_1$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_1$${QT_LIBINFIX}.dll\"" \ + " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}_3_1.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ + "ELSE" \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ + " \"$$bearerPluginLocation/qsymbianbearer$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qsymbianbearer$${QT_LIBINFIX}.dll\"" \ + "ENDIF" \ + " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\" + } else { + # No need to deploy plugins for older platform versions when building on Symbian3 or later + qts60plugindeployment = \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" + bearer_plugin.sources = $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll + bearer_plugin.path = c:$$QT_PLUGINS_BASE_DIR/bearer + DEPLOYMENT += bearer_plugin + } + + qtlibraries.pkg_postrules += qts60plugindeployment qtlibraries.path = c:/sys/bin -- cgit v0.12 From 4aea5ebee1ddaa9c05471b0562443d0bab079e68 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 17 Sep 2010 13:29:33 +0300 Subject: Load environment.prf from Symbian SDK if it exists there Environment.prf can contain SDK specific variable settings such as SYMBIAN_VERSION. Task-number: QT-3949 Reviewed-by: Janne Koskinen --- mkspecs/common/symbian/symbian.conf | 55 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index beef193..679731f 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -125,36 +125,47 @@ QT_IMPORTS_BASE_DIR = /resource/qt/imports load(symbian/platform_paths) -# The Symbian^3 PDK does not necessarily contain the required sis files. -# However, libstdcppv5 first appeared in Symbian^3 (S60 5.2), so check for that too. -exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/release/armv5/lib/libstdcppv5.dso) { - S60_VERSION = 5.2 -} else { - exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.1.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.1.sis) { - S60_VERSION = 5.1 +# If environment.prf is provided by platform, load that. +# It is used for platform specific variable settings, such as SYMBIAN_VERSION. +exists($${EPOCROOT}epoc32/tools/qt/mkspecs/features/environment.prf) { + load($${EPOCROOT}epoc32/tools/qt/mkspecs/features/environment.prf) +} + +# Try to detect SDK version if it wasn't set by environment.prf +isEmpty(S60_VERSION) { + # The Symbian^3 PDK does not necessarily contain the required sis files. + # However, libstdcppv5 first appeared in Symbian^3 (S60 5.2), so check for that too. + exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/release/armv5/lib/libstdcppv5.dso) { + S60_VERSION = 5.2 } else { - exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.0.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.0.sis) { - S60_VERSION = 5.0 + exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.1.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.1.sis) { + S60_VERSION = 5.1 } else { - exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v3.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v3.2.sis) { - S60_VERSION = 3.2 + exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.0.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.0.sis) { + S60_VERSION = 5.0 } else { - S60_VERSION = 3.1 + exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v3.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v3.2.sis) { + S60_VERSION = 3.2 + } else { + S60_VERSION = 3.1 + } } } } } -contains(S60_VERSION, "3\\.1") { - SYMBIAN_VERSION = 9.2 -} else:contains(S60_VERSION, "3\\.2") { - SYMBIAN_VERSION = 9.3 -} else:contains(S60_VERSION, "5\\.0") { - SYMBIAN_VERSION = 9.4 -} else:contains(S60_VERSION, "5\\.1") { - SYMBIAN_VERSION = Symbian2 -} else:contains(S60_VERSION, "5\\.2") { - SYMBIAN_VERSION = Symbian3 +isEmpty(SYMBIAN_VERSION) { + contains(S60_VERSION, "3\\.1") { + SYMBIAN_VERSION = 9.2 + } else:contains(S60_VERSION, "3\\.2") { + SYMBIAN_VERSION = 9.3 + } else:contains(S60_VERSION, "5\\.0") { + SYMBIAN_VERSION = 9.4 + } else:contains(S60_VERSION, "5\\.1") { + SYMBIAN_VERSION = Symbian2 + } else:contains(S60_VERSION, "5\\.2") { + SYMBIAN_VERSION = Symbian3 + } } # pkg_depends_webkit, pkg_depends_core, and pkg_platform_dependencies can be removed by developer -- cgit v0.12 From d242d2f863936a4e3e2b07a4d84b7f0c4b4eb817 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Fri, 17 Sep 2010 15:12:12 +0300 Subject: QS60Style does not show checkbox for checkable item in QTreeView QS60Style currently skips drawing of checkbox for checkable itemviews. It however reserves space for the checkbox in the itemview item row. As a fix, also draw the checkbox. Task-number: QTBUG-11150 Reviewed-by: Shane Kearns --- src/gui/styles/qs60style.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index d529dd5..5996032 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -1475,8 +1475,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, const QIcon::State state = (voptAdj.state & State_Open) ? QIcon::On : QIcon::Off; voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); - // Draw selection check mark. Show check mark only in multi selection modes. - if (itemView && !singleSelection) { + // Draw selection check mark or checkbox + if (itemView && (!singleSelection || (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator))) { const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget); QStyleOptionViewItemV4 checkMarkOption(voptAdj); -- cgit v0.12 From 82244a4b24776202802f35797e0bb72ec32dd0e7 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 1 Sep 2010 14:04:10 +0100 Subject: Fixed buffer overrun in Symbian QAudioInput backend Task-number: QTBUG-13058 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudioinput_symbian_p.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/multimedia/audio/qaudioinput_symbian_p.cpp b/src/multimedia/audio/qaudioinput_symbian_p.cpp index 9d240ca..9ae4368 100644 --- a/src/multimedia/audio/qaudioinput_symbian_p.cpp +++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp @@ -373,7 +373,8 @@ qint64 QAudioInputPrivate::read(char *data, qint64 len) TDesC8 &inputBuffer = buffer->Data(); - const qint64 inputBytes = bytesReady(); + Q_ASSERT(inputBuffer.Length() >= m_devSoundBufferPos); + const qint64 inputBytes = inputBuffer.Length() - m_devSoundBufferPos; const qint64 outputBytes = len - bytesRead; const qint64 copyBytes = outputBytes < inputBytes ? outputBytes : inputBytes; @@ -384,7 +385,7 @@ qint64 QAudioInputPrivate::read(char *data, qint64 len) data += copyBytes; bytesRead += copyBytes; - if (!bytesReady()) + if (inputBytes == copyBytes) bufferEmptied(); } @@ -403,13 +404,14 @@ void QAudioInputPrivate::pullData() TDesC8 &inputBuffer = buffer->Data(); - const qint64 inputBytes = bytesReady(); + Q_ASSERT(inputBuffer.Length() >= m_devSoundBufferPos); + const qint64 inputBytes = inputBuffer.Length() - m_devSoundBufferPos; const qint64 bytesPushed = m_sink->write( (char*)inputBuffer.Ptr() + m_devSoundBufferPos, inputBytes); m_devSoundBufferPos += bytesPushed; - if (!bytesReady()) + if (inputBytes == bytesPushed) bufferEmptied(); if (!bytesPushed) -- cgit v0.12 From f43ec0dc8414d7342f02269fdc5cd6ac7b7ec44f Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 8 Sep 2010 13:41:54 +0100 Subject: Discard all DevSound buffers held when QAudioInput::suspend() called Resuming recording causes buffers previously provided to the client (via MDevSoundObserver::BufferToBeEmptied()) to be invalidated. The buffers therefore must be discarded when recording is suspended. Task-number: QTBUG-13058 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudioinput_symbian_p.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/multimedia/audio/qaudioinput_symbian_p.cpp b/src/multimedia/audio/qaudioinput_symbian_p.cpp index 9ae4368..b837055 100644 --- a/src/multimedia/audio/qaudioinput_symbian_p.cpp +++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp @@ -178,10 +178,9 @@ void QAudioInputPrivate::suspend() const qint64 samplesRecorded = getSamplesRecorded(); m_totalSamplesRecorded += samplesRecorded; - if (m_devSoundBuffer) { - m_devSoundBufferQ.append(m_devSoundBuffer); - m_devSoundBuffer = 0; - } + m_devSoundBuffer = 0; + m_devSoundBufferQ.clear(); + m_devSoundBufferPos = 0; setState(SymbianAudio::SuspendedState); } -- cgit v0.12 From 7eb0aea6d3d261b97d224b5342fac1637cb9b792 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 1 Sep 2010 13:47:16 +0100 Subject: Permit QAudioOutput::processedUSecs() to be called immediately after start() If QAudioOutput::processedUSecs() is called very soon after QAudioOutput::start(), the DevSound instance owned by the Symbian backend may still be initializing. This patch causes the function to return zero, rather than failing an assertion. Task-number: QTBUG-13059 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudio_symbian_p.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/multimedia/audio/qaudio_symbian_p.cpp b/src/multimedia/audio/qaudio_symbian_p.cpp index 4522c5c..ae58b94 100644 --- a/src/multimedia/audio/qaudio_symbian_p.cpp +++ b/src/multimedia/audio/qaudio_symbian_p.cpp @@ -432,15 +432,16 @@ bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const 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; + if (StateInitialized == m_state) { + switch (m_mode) { + case QAudio::AudioInput: + result = m_devsound->SamplesRecorded(); + break; + case QAudio::AudioOutput: + result = m_devsound->SamplesPlayed(); + break; + } } return result; } -- cgit v0.12 From 98b335dadef433e383d3a25dbdadbb5efe7f8429 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 1 Sep 2010 13:49:54 +0100 Subject: Discard empty buffer on call to QAudioOutput::resume() The Symbian backend holds buffers which are passed to it from DevSound, exposing the memory of these buffers via the QIODevice interface. When QAudioOutput::resume() is called, the backend re-starts data flow by passing the buffer it holds back to DevSound. Previously, this would not happen if the buffer was empty, potentially causing playback to stall. This patch ensures that the buffer is always sent back to DevSound, and data flow therefore always resumes. Task-number: QTBUG-13059 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudiooutput_symbian_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index 5098469..5054ae3 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -210,7 +210,7 @@ void QAudioOutputPrivate::suspend() void QAudioOutputPrivate::resume() { if (SymbianAudio::SuspendedState == m_internalState) { - if (!m_pullMode && m_devSoundBuffer && m_devSoundBuffer->Data().Length()) + if (!m_pullMode && m_devSoundBuffer) bufferFilled(); startPlayback(); } -- cgit v0.12 From 4b0435b0dc2287756221e35f2ebe9493aad8306d Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 1 Sep 2010 13:52:46 +0100 Subject: Suppress overflow errors raised by Symbian DevSound during playback When QAudioOutput::suspend() and QAudioOutput::resume() are called repeatedly, with a short delay between each call, DevSound occasionally raises a KErrOverflow error. The backend previously translated this into QAudio::IOError, causing the object to transition into the QAudio::Stopped state. This error can be safely ignored, with playback resuming as soon as more audio data is provided to DevSound. This patch therefore suppresses the error. Task-number: QTBUG-13059 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudiooutput_symbian_p.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index 5054ae3..c8b6ecf 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -371,6 +371,9 @@ void QAudioOutputPrivate::devsoundPlayError(int err) else setState(SymbianAudio::IdleState); break; + case KErrOverflow: + // Silently consume this error when in playback mode + break; default: setError(QAudio::IOError); break; -- cgit v0.12 From 9fd8589c9d4574c04a989a6c5e1d335779d2b244 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 8 Sep 2010 15:18:06 +0100 Subject: Discard buffer pointer when DevSound is stopped Task-number: QTBUG-13504 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudiooutput_symbian_p.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index c8b6ecf..cc32f9d 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -195,6 +195,7 @@ void QAudioOutputPrivate::suspend() // lost data with silence following a call to resume(), in order to // ensure that processedUSecs() returns the correct value. m_devSound->stop(); + m_devSoundBuffer = 0; m_totalSamplesPlayed += samplesPlayed; // Calculate the amount of data dropped -- cgit v0.12 From 737b75e19b7206cb9888e87930cb37b1906a6345 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Tue, 14 Sep 2010 15:02:03 +0100 Subject: Implement QAudioInput::suspend() using CMMFDevSound::Stop() As with playback mode, lack of support for CMMFDevSound::Pause() in DevSound's recording mode causes problems on some devices. Specifically, while QAudioInput works fine on the Nokia 5800, this bug was observed on the Nokia N8. This fix means that suspending and resuming audio input will work correctly on all devices. Task-number: QTBUG-13506 Reviewed-by: Derick Hawcroft --- src/multimedia/audio/qaudio_symbian_p.cpp | 25 ++++++++++++-- src/multimedia/audio/qaudio_symbian_p.h | 15 +++++++-- src/multimedia/audio/qaudioinput_symbian_p.cpp | 30 +++++++++++------ src/multimedia/audio/qaudiooutput_symbian_p.cpp | 45 +++++++++++-------------- 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/multimedia/audio/qaudio_symbian_p.cpp b/src/multimedia/audio/qaudio_symbian_p.cpp index ae58b94..59fc05f 100644 --- a/src/multimedia/audio/qaudio_symbian_p.cpp +++ b/src/multimedia/audio/qaudio_symbian_p.cpp @@ -313,7 +313,8 @@ QAudio::State stateNativeToQt(State nativeState) return QAudio::ActiveState; case IdleState: return QAudio::IdleState; - case SuspendedState: + case SuspendedPausedState: + case SuspendedStoppedState: return QAudio::SuspendedState; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid state"); @@ -476,10 +477,22 @@ bool DevSoundWrapper::start() return (KErrNone == err); } -void DevSoundWrapper::pause() +bool DevSoundWrapper::pause() { Q_ASSERT(StateInitialized == m_state); - m_devsound->Pause(); + const bool canPause = isResumeSupported(); + if (canPause) + m_devsound->Pause(); + else + stop(); + return canPause; +} + +void DevSoundWrapper::resume() +{ + Q_ASSERT(StateInitialized == m_state); + Q_ASSERT(isResumeSupported()); + // TODO: QTBUG-13625 } void DevSoundWrapper::stop() @@ -558,6 +571,12 @@ void DevSoundWrapper::populateCapabilities() } } +bool DevSoundWrapper::isResumeSupported() const +{ + // TODO: QTBUG-13625 + return false; +} + void DevSoundWrapper::InitializeComplete(TInt aError) { Q_ASSERT(StateInitializing == m_state); diff --git a/src/multimedia/audio/qaudio_symbian_p.h b/src/multimedia/audio/qaudio_symbian_p.h index 58ef192..84a93d1 100644 --- a/src/multimedia/audio/qaudio_symbian_p.h +++ b/src/multimedia/audio/qaudio_symbian_p.h @@ -81,7 +81,10 @@ enum State { , InitializingState , ActiveState , IdleState - , SuspendedState + // QAudio is suspended; DevSound is paused + , SuspendedPausedState + // QAudio is suspended; DevSound is stopped + , SuspendedStoppedState }; /** @@ -117,7 +120,14 @@ public: int samplesProcessed() const; bool setFormat(const QAudioFormat &format); bool start(); - void pause(); + + // If DevSound implementation supports pause, calls pause and returns true. + // Otherwise calls stop and returns false. In this case, all DevSound buffers + // currently held by the backend must be discarded. + bool pause(); + + void resume(); + void stop(); void bufferProcessed(); @@ -140,6 +150,7 @@ signals: private: void getSupportedCodecs(); void populateCapabilities(); + bool isResumeSupported() const; private: const QAudio::Mode m_mode; diff --git a/src/multimedia/audio/qaudioinput_symbian_p.cpp b/src/multimedia/audio/qaudioinput_symbian_p.cpp index b837055..485c695 100644 --- a/src/multimedia/audio/qaudioinput_symbian_p.cpp +++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp @@ -174,22 +174,30 @@ void QAudioInputPrivate::suspend() || SymbianAudio::IdleState == m_internalState) { m_notifyTimer->stop(); m_pullTimer->stop(); - m_devSound->pause(); const qint64 samplesRecorded = getSamplesRecorded(); m_totalSamplesRecorded += samplesRecorded; - m_devSoundBuffer = 0; - m_devSoundBufferQ.clear(); - m_devSoundBufferPos = 0; - - setState(SymbianAudio::SuspendedState); + const bool paused = m_devSound->pause(); + if (paused) { + if (m_devSoundBuffer) + m_devSoundBufferQ.append(m_devSoundBuffer); + m_devSoundBuffer = 0; + setState(SymbianAudio::SuspendedPausedState); + } else { + m_devSoundBuffer = 0; + m_devSoundBufferQ.clear(); + m_devSoundBufferPos = 0; + setState(SymbianAudio::SuspendedStoppedState); + } } } void QAudioInputPrivate::resume() { - if (SymbianAudio::SuspendedState == m_internalState) { - if (!m_pullMode && !bytesReady()) + if (QAudio::SuspendedState == m_externalState) { + if (SymbianAudio::SuspendedPausedState == m_internalState) + m_devSound->resume(); + else m_devSound->start(); startDataTransfer(); } @@ -245,7 +253,7 @@ int QAudioInputPrivate::notifyInterval() const qint64 QAudioInputPrivate::processedUSecs() const { int samplesPlayed = 0; - if (m_devSound && SymbianAudio::SuspendedState != m_internalState) + if (m_devSound && QAudio::SuspendedState != m_externalState) samplesPlayed = getSamplesRecorded(); // Protect against division by zero @@ -334,7 +342,7 @@ void QAudioInputPrivate::startDataTransfer() if (!m_pullMode) pushData(); } else { - if (SymbianAudio::SuspendedState == m_internalState) + if (QAudio::SuspendedState == m_externalState) setState(SymbianAudio::ActiveState); else setState(SymbianAudio::IdleState); @@ -442,7 +450,7 @@ void QAudioInputPrivate::devsoundBufferToBeEmptied(CMMFBuffer *baseBuffer) m_totalBytesReady += buffer->Data().Length(); - if (SymbianAudio::SuspendedState == m_internalState) { + if (SymbianAudio::SuspendedPausedState == m_internalState) { m_devSoundBufferQ.append(buffer); } else { // Will be returned to DevSoundWrapper by bufferProcessed(). diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index cc32f9d..ea14e19 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -180,40 +180,33 @@ void QAudioOutputPrivate::suspend() || SymbianAudio::IdleState == m_internalState) { m_notifyTimer->stop(); m_underflowTimer->stop(); - const qint64 samplesWritten = SymbianAudio::Utils::bytesToSamples( m_format, m_bytesWritten); - const qint64 samplesPlayed = getSamplesPlayed(); - - m_bytesWritten = 0; - - // CMMFDevSound::Pause() is not guaranteed to work correctly in all - // implementations, for play-mode DevSound sessions. We therefore - // have to implement suspend() by calling CMMFDevSound::Stop(). - // 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_devSoundBuffer = 0; 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); - - setState(SymbianAudio::SuspendedState); + m_bytesWritten = 0; + const bool paused = m_devSound->pause(); + if (paused) { + setState(SymbianAudio::SuspendedPausedState); + } else { + m_devSoundBuffer = 0; + // Calculate the amount of data dropped + const qint64 paddingSamples = samplesWritten - samplesPlayed; + Q_ASSERT(paddingSamples >= 0); + m_bytesPadding = SymbianAudio::Utils::samplesToBytes(m_format, + paddingSamples); + setState(SymbianAudio::SuspendedStoppedState); + } } } void QAudioOutputPrivate::resume() { - if (SymbianAudio::SuspendedState == m_internalState) { - if (!m_pullMode && m_devSoundBuffer) - bufferFilled(); - startPlayback(); + if (QAudio::SuspendedState == m_externalState) { + if (SymbianAudio::SuspendedPausedState == m_internalState) + m_devSound->resume(); + else + startPlayback(); } } @@ -271,7 +264,7 @@ int QAudioOutputPrivate::notifyInterval() const qint64 QAudioOutputPrivate::processedUSecs() const { int samplesPlayed = 0; - if (m_devSound && SymbianAudio::SuspendedState != m_internalState) + if (m_devSound && QAudio::SuspendedState != m_externalState) samplesPlayed = getSamplesPlayed(); // Protect against division by zero -- cgit v0.12