summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-10-29 12:52:31 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-10-29 12:52:31 (GMT)
commit969750777896dc50f9f5b8043b5da3a4a161e616 (patch)
tree11e8599f5727df234be8c9ab783db47ac12f2a43
parentc02ef9eb331f03dbd59d2fd938c53b54f5c65cea (diff)
parent3cf35876400cb008fb25c8a3191c996af6059264 (diff)
downloadQt-969750777896dc50f9f5b8043b5da3a4a161e616.zip
Qt-969750777896dc50f9f5b8043b5da3a4a161e616.tar.gz
Qt-969750777896dc50f9f5b8043b5da3a4a161e616.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public: Play whole file in spectrum analyzer demo Do not unnecessarily reset state of spectrum demo Set SpectrumAnalyserThread parent to 0 before calling moveToThread() Avoid being killed by graphics out-of-memory monitor. Revert function renaming in QtOpenVG. Support tactile feedback in QWidgets from QS60Style Support tactile feeedback from QS60Style for QWidgets Making the buttons less finger unfriendly Readded .def file entries after a little stunt Do not crash on Symbian Temporarily remove .def file entries for a little stunt Fixed crash with QClipboard in Symbian^3 Fallback to vgWritePixels in drawPixmap.
-rw-r--r--demos/declarative/samegame/SamegameCore/Button.qml4
-rw-r--r--demos/declarative/samegame/samegame.qml3
-rw-r--r--demos/spectrum/app/engine.cpp333
-rw-r--r--demos/spectrum/app/engine.h57
-rw-r--r--demos/spectrum/app/mainwidget.cpp67
-rw-r--r--demos/spectrum/app/mainwidget.h10
-rw-r--r--demos/spectrum/app/progressbar.cpp26
-rw-r--r--demos/spectrum/app/progressbar.h4
-rw-r--r--demos/spectrum/app/spectrumanalyser.cpp2
-rw-r--r--demos/spectrum/app/utils.cpp4
-rw-r--r--demos/spectrum/app/waveform.cpp120
-rw-r--r--demos/spectrum/app/waveform.h14
-rw-r--r--demos/spectrum/app/wavfile.cpp205
-rw-r--r--demos/spectrum/app/wavfile.h36
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice.cpp12
-rw-r--r--src/gui/kernel/qapplication.cpp9
-rw-r--r--src/gui/kernel/qapplication_p.h3
-rw-r--r--src/gui/kernel/qapplication_s60.cpp11
-rw-r--r--src/gui/kernel/qclipboard_s60.cpp10
-rw-r--r--src/gui/styles/qs60style.cpp5
-rw-r--r--src/gui/styles/qs60style_feedbackinterface_p.h50
-rw-r--r--src/gui/styles/qs60style_p.h4
-rw-r--r--src/gui/styles/qs60style_s60.cpp24
-rw-r--r--src/openvg/qpaintengine_vg.cpp86
-rw-r--r--src/openvg/qpaintengine_vg_p.h1
-rw-r--r--src/openvg/qpixmapdata_vg.cpp27
-rw-r--r--src/openvg/qpixmapdata_vg_p.h2
-rw-r--r--src/openvg/qvg_symbian.cpp1
-rw-r--r--src/plugins/s60/feedback/feedback.pro16
-rw-r--r--src/plugins/s60/feedback/qtactileFeedback.h54
-rw-r--r--src/plugins/s60/feedback/qtactileFeedback_s60.cpp83
-rw-r--r--src/plugins/s60/s60.pro4
-rw-r--r--src/s60installs/bwins/QtGuiu.def8
-rw-r--r--src/s60installs/eabi/QtGuiu.def8
-rw-r--r--src/s60installs/qt.iby5
-rw-r--r--src/s60installs/s60installs.pro6
36 files changed, 792 insertions, 522 deletions
diff --git a/demos/declarative/samegame/SamegameCore/Button.qml b/demos/declarative/samegame/SamegameCore/Button.qml
index 7fb7b65..140b196 100644
--- a/demos/declarative/samegame/SamegameCore/Button.qml
+++ b/demos/declarative/samegame/SamegameCore/Button.qml
@@ -48,7 +48,7 @@ Rectangle {
signal clicked
- width: buttonLabel.width + 20; height: buttonLabel.height + 6
+ width: buttonLabel.width + 20; height: buttonLabel.height + 20
smooth: true
border { width: 1; color: Qt.darker(activePalette.button) }
radius: 8
@@ -70,6 +70,6 @@ Rectangle {
MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() }
Text {
- id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+ id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: 24
}
}
diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml
index f66c40e..b66c5a6 100644
--- a/demos/declarative/samegame/samegame.qml
+++ b/demos/declarative/samegame/samegame.qml
@@ -133,7 +133,7 @@ Rectangle {
Rectangle {
id: toolBar
- width: parent.width; height: 32
+ width: parent.width; height: 58
color: activePalette.window
anchors.bottom: screen.bottom
@@ -156,6 +156,7 @@ Rectangle {
anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter }
text: "Score: " + gameCanvas.score
font.bold: true
+ font.pixelSize: 24
color: activePalette.windowText
}
}
diff --git a/demos/spectrum/app/engine.cpp b/demos/spectrum/app/engine.cpp
index 119a0e3..cd847fe 100644
--- a/demos/spectrum/app/engine.cpp
+++ b/demos/spectrum/app/engine.cpp
@@ -85,6 +85,7 @@ Engine::Engine(QObject *parent)
, m_state(QAudio::StoppedState)
, m_generateTone(false)
, m_file(0)
+ , m_analysisFile(0)
, m_availableAudioInputDevices
(QAudioDeviceInfo::availableDevices(QAudio::AudioInput))
, m_audioInputDevice(QAudioDeviceInfo::defaultInputDevice())
@@ -96,15 +97,19 @@ Engine::Engine(QObject *parent)
, m_audioOutputDevice(QAudioDeviceInfo::defaultOutputDevice())
, m_audioOutput(0)
, m_playPosition(0)
+ , m_bufferPosition(0)
+ , m_bufferLength(0)
, m_dataLength(0)
+ , m_levelBufferLength(0)
, m_rmsLevel(0.0)
, m_peakLevel(0.0)
- , m_spectrumLengthBytes(0)
+ , m_spectrumBufferLength(0)
, m_spectrumAnalyser()
, m_spectrumPosition(0)
, m_count(0)
{
qRegisterMetaType<FrequencySpectrum>("FrequencySpectrum");
+ qRegisterMetaType<WindowFunction>("WindowFunction");
CHECKED_CONNECT(&m_spectrumAnalyser,
SIGNAL(spectrumChanged(FrequencySpectrum)),
this,
@@ -132,34 +137,33 @@ Engine::~Engine()
bool Engine::loadFile(const QString &fileName)
{
+ reset();
bool result = false;
- m_generateTone = false;
-
- Q_ASSERT(!fileName.isEmpty());
+ Q_ASSERT(!m_generateTone);
Q_ASSERT(!m_file);
- m_file = new QFile(fileName, this);
- m_file->setFileName(fileName);
- Q_ASSERT(m_file->exists());
- if (m_file->open(QFile::ReadOnly)) {
- m_wavFile.readHeader(*m_file);
- if (isPCMS16LE(m_wavFile.format())) {
+ Q_ASSERT(!fileName.isEmpty());
+ m_file = new WavFile(this);
+ if (m_file->open(fileName)) {
+ if (isPCMS16LE(m_file->fileFormat())) {
result = initialize();
} else {
emit errorMessage(tr("Audio format not supported"),
- formatToString(m_wavFile.format()));
+ formatToString(m_file->fileFormat()));
}
} else {
emit errorMessage(tr("Could not open file"), fileName);
}
-
- delete m_file;
- m_file = 0;
-
+ if (result) {
+ m_analysisFile = new WavFile(this);
+ m_analysisFile->open(fileName);
+ }
return result;
}
bool Engine::generateTone(const Tone &tone)
{
+ reset();
+ Q_ASSERT(!m_generateTone);
Q_ASSERT(!m_file);
m_generateTone = true;
m_tone = tone;
@@ -172,6 +176,7 @@ bool Engine::generateTone(const Tone &tone)
bool Engine::generateSweptTone(qreal amplitude)
{
+ Q_ASSERT(!m_generateTone);
Q_ASSERT(!m_file);
m_generateTone = true;
m_tone.startFreq = 1;
@@ -185,41 +190,18 @@ bool Engine::generateSweptTone(qreal amplitude)
bool Engine::initializeRecord()
{
+ reset();
ENGINE_DEBUG << "Engine::initializeRecord";
+ Q_ASSERT(!m_generateTone);
Q_ASSERT(!m_file);
m_generateTone = false;
m_tone = SweptTone();
return initialize();
}
-qint64 Engine::bufferDuration() const
-{
- return BufferDurationUs;
-}
-
-qint64 Engine::dataDuration() const
+qint64 Engine::bufferLength() const
{
- qint64 result = 0;
- if (QAudioFormat() != m_format)
- result = audioDuration(m_format, m_dataLength);
- return result;
-}
-
-qint64 Engine::audioBufferLength() const
-{
- qint64 length = 0;
- if (QAudio::ActiveState == m_state || QAudio::IdleState == m_state) {
- Q_ASSERT(QAudioFormat() != m_format);
- switch (m_mode) {
- case QAudio::AudioInput:
- length = m_audioInput->bufferSize();
- break;
- case QAudio::AudioOutput:
- length = m_audioOutput->bufferSize();
- break;
- }
- }
- return length;
+ return m_file ? m_file->size() : m_bufferLength;
}
void Engine::setWindowFunction(WindowFunction type)
@@ -252,7 +234,7 @@ void Engine::startRecording()
this, SLOT(audioNotify()));
m_count = 0;
m_dataLength = 0;
- emit dataDurationChanged(0);
+ emit dataLengthChanged(0);
m_audioInputIODevice = m_audioInput->start();
CHECKED_CONNECT(m_audioInputIODevice, SIGNAL(readyRead()),
this, SLOT(audioDataReady()));
@@ -275,7 +257,6 @@ void Engine::startPlayback()
} else {
m_spectrumAnalyser.cancelCalculation();
spectrumChanged(0, 0, FrequencySpectrum());
-
setPlayPosition(0, true);
stopRecording();
m_mode = QAudio::AudioOutput;
@@ -284,10 +265,17 @@ void Engine::startPlayback()
CHECKED_CONNECT(m_audioOutput, SIGNAL(notify()),
this, SLOT(audioNotify()));
m_count = 0;
- m_audioOutputIODevice.close();
- m_audioOutputIODevice.setBuffer(&m_buffer);
- m_audioOutputIODevice.open(QIODevice::ReadOnly);
- m_audioOutput->start(&m_audioOutputIODevice);
+ if (m_file) {
+ m_file->seek(0);
+ m_bufferPosition = 0;
+ m_dataLength = 0;
+ m_audioOutput->start(m_file);
+ } else {
+ m_audioOutputIODevice.close();
+ m_audioOutputIODevice.setBuffer(&m_buffer);
+ m_audioOutputIODevice.open(QIODevice::ReadOnly);
+ m_audioOutput->start(&m_audioOutputIODevice);
+ }
}
}
}
@@ -332,40 +320,55 @@ void Engine::audioNotify()
{
switch (m_mode) {
case QAudio::AudioInput: {
- const qint64 recordPosition =
- qMin(BufferDurationUs, m_audioInput->processedUSecs());
+ const qint64 recordPosition = qMin(m_bufferLength, audioLength(m_format, m_audioInput->processedUSecs()));
setRecordPosition(recordPosition);
-
- // Calculate level of most recently captured data
- qint64 levelLength = audioLength(m_format, LevelWindowUs);
- levelLength = qMin(m_dataLength, levelLength);
- const qint64 levelPosition = m_dataLength - levelLength;
- calculateLevel(levelPosition, levelLength);
-
- // Calculate spectrum of most recently captured data
- if (m_dataLength >= m_spectrumLengthBytes) {
- const qint64 spectrumPosition = m_dataLength - m_spectrumLengthBytes;
+ const qint64 levelPosition = m_dataLength - m_levelBufferLength;
+ if (levelPosition >= 0)
+ calculateLevel(levelPosition, m_levelBufferLength);
+ if (m_dataLength >= m_spectrumBufferLength) {
+ const qint64 spectrumPosition = m_dataLength - m_spectrumBufferLength;
calculateSpectrum(spectrumPosition);
}
+ emit bufferChanged(0, m_dataLength, m_buffer);
}
break;
case QAudio::AudioOutput: {
- const qint64 playPosition =
- qMin(dataDuration(), m_audioOutput->processedUSecs());
- setPlayPosition(playPosition);
-
- qint64 analysisPosition = audioLength(m_format, playPosition);
-
- // Calculate level of data starting at current playback position
- const qint64 levelLength = audioLength(m_format, LevelWindowUs);
- if (analysisPosition + levelLength < m_dataLength)
- calculateLevel(analysisPosition, levelLength);
-
- if (analysisPosition + m_spectrumLengthBytes < m_dataLength)
- calculateSpectrum(analysisPosition);
-
- if (dataDuration() == playPosition)
- stopPlayback();
+ const qint64 playPosition = audioLength(m_format, m_audioOutput->processedUSecs());
+ setPlayPosition(qMin(bufferLength(), playPosition));
+ const qint64 levelPosition = playPosition - m_levelBufferLength;
+ const qint64 spectrumPosition = playPosition - m_spectrumBufferLength;
+ if (m_file) {
+ if (levelPosition > m_bufferPosition ||
+ spectrumPosition > m_bufferPosition ||
+ qMax(m_levelBufferLength, m_spectrumBufferLength) > m_dataLength) {
+ m_bufferPosition = 0;
+ m_dataLength = 0;
+ // Data needs to be read into m_buffer in order to be analysed
+ const qint64 readPos = qMax(qint64(0), qMin(levelPosition, spectrumPosition));
+ const qint64 readEnd = qMin(m_analysisFile->size(), qMax(levelPosition + m_levelBufferLength, spectrumPosition + m_spectrumBufferLength));
+ const qint64 readLen = readEnd - readPos + audioLength(m_format, WaveformWindowDuration);
+ qDebug() << "Engine::audioNotify [1]"
+ << "analysisFileSize" << m_analysisFile->size()
+ << "readPos" << readPos
+ << "readLen" << readLen;
+ if (m_analysisFile->seek(readPos + m_analysisFile->headerLength())) {
+ m_buffer.resize(readLen);
+ m_bufferPosition = readPos;
+ m_dataLength = m_analysisFile->read(m_buffer.data(), readLen);
+ qDebug() << "Engine::audioNotify [2]" << "bufferPosition" << m_bufferPosition << "dataLength" << m_dataLength;
+ } else {
+ qDebug() << "Engine::audioNotify [2]" << "file seek error";
+ }
+ emit bufferChanged(m_bufferPosition, m_dataLength, m_buffer);
+ }
+ } else {
+ if (playPosition >= m_dataLength)
+ stopPlayback();
+ }
+ if (levelPosition >= 0 && levelPosition + m_levelBufferLength < m_bufferPosition + m_dataLength)
+ calculateLevel(levelPosition, m_levelBufferLength);
+ if (spectrumPosition >= 0 && spectrumPosition + m_spectrumBufferLength < m_bufferPosition + m_dataLength)
+ calculateSpectrum(spectrumPosition);
}
break;
}
@@ -376,27 +379,32 @@ void Engine::audioStateChanged(QAudio::State state)
ENGINE_DEBUG << "Engine::audioStateChanged from" << m_state
<< "to" << state;
- if (QAudio::StoppedState == state) {
- // Check error
- QAudio::Error error = QAudio::NoError;
- switch (m_mode) {
- case QAudio::AudioInput:
- error = m_audioInput->error();
- break;
- case QAudio::AudioOutput:
- error = m_audioOutput->error();
- break;
- }
- if (QAudio::NoError != error) {
- reset();
- return;
+ if (QAudio::IdleState == state && m_file && m_file->pos() == m_file->size()) {
+ stopPlayback();
+ } else {
+ if (QAudio::StoppedState == state) {
+ // Check error
+ QAudio::Error error = QAudio::NoError;
+ switch (m_mode) {
+ case QAudio::AudioInput:
+ error = m_audioInput->error();
+ break;
+ case QAudio::AudioOutput:
+ error = m_audioOutput->error();
+ break;
+ }
+ if (QAudio::NoError != error) {
+ reset();
+ return;
+ }
}
+ setState(state);
}
- setState(state);
}
void Engine::audioDataReady()
{
+ Q_ASSERT(0 == m_bufferPosition);
const qint64 bytesReady = m_audioInput->bytesReady();
const qint64 bytesSpace = m_buffer.size() - m_dataLength;
const qint64 bytesToRead = qMin(bytesReady, bytesSpace);
@@ -407,9 +415,7 @@ void Engine::audioDataReady()
if (bytesRead) {
m_dataLength += bytesRead;
-
- const qint64 duration = audioDuration(m_format, m_dataLength);
- emit dataDurationChanged(duration);
+ emit dataLengthChanged(dataLength());
}
if (m_buffer.size() == m_dataLength)
@@ -419,9 +425,7 @@ void Engine::audioDataReady()
void Engine::spectrumChanged(const FrequencySpectrum &spectrum)
{
ENGINE_DEBUG << "Engine::spectrumChanged" << "pos" << m_spectrumPosition;
- const qint64 positionUs = audioDuration(m_format, m_spectrumPosition);
- const qint64 lengthUs = audioDuration(m_format, m_spectrumLengthBytes);
- emit spectrumChanged(positionUs, lengthUs, spectrum);
+ emit spectrumChanged(m_spectrumPosition, m_spectrumBufferLength, spectrum);
}
@@ -429,12 +433,8 @@ void Engine::spectrumChanged(const FrequencySpectrum &spectrum)
// Private functions
//-----------------------------------------------------------------------------
-void Engine::reset()
+void Engine::resetAudioDevices()
{
- stopRecording();
- stopPlayback();
- setState(QAudio::AudioInput, QAudio::StoppedState);
- setFormat(QAudioFormat());
delete m_audioInput;
m_audioInput = 0;
m_audioInputIODevice = 0;
@@ -442,55 +442,71 @@ void Engine::reset()
delete m_audioOutput;
m_audioOutput = 0;
setPlayPosition(0);
- m_buffer.clear();
- m_dataLength = 0;
m_spectrumPosition = 0;
- emit dataDurationChanged(0);
setLevel(0.0, 0.0, 0);
}
+void Engine::reset()
+{
+ stopRecording();
+ stopPlayback();
+ setState(QAudio::AudioInput, QAudio::StoppedState);
+ setFormat(QAudioFormat());
+ m_generateTone = false;
+ delete m_file;
+ m_file = 0;
+ delete m_analysisFile;
+ m_analysisFile = 0;
+ m_buffer.clear();
+ m_bufferPosition = 0;
+ m_bufferLength = 0;
+ m_dataLength = 0;
+ emit dataLengthChanged(0);
+ resetAudioDevices();
+}
+
bool Engine::initialize()
{
bool result = false;
- reset();
+ QAudioFormat format = m_format;
if (selectFormat()) {
- const qint64 bufferLength = audioLength(m_format, BufferDurationUs);
- m_buffer.resize(bufferLength);
- m_buffer.fill(0);
- emit bufferDurationChanged(BufferDurationUs);
-
- if (m_generateTone) {
- if (0 == m_tone.endFreq) {
- const qreal nyquist = nyquistFrequency(m_format);
- m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist);
- }
-
- // Call function defined in utils.h, at global scope
- ::generateTone(m_tone, m_format, m_buffer);
- m_dataLength = m_buffer.size();
- emit dataDurationChanged(bufferDuration());
- setRecordPosition(bufferDuration());
- result = true;
- } else if (m_file) {
- const qint64 length = m_wavFile.readData(*m_file, m_buffer, m_format);
- if (length) {
- m_dataLength = length;
- emit dataDurationChanged(dataDuration());
- setRecordPosition(dataDuration());
+ if (m_format != format) {
+ resetAudioDevices();
+ if (m_file) {
+ emit bufferLengthChanged(bufferLength());
+ emit dataLengthChanged(dataLength());
+ emit bufferChanged(0, 0, m_buffer);
+ setRecordPosition(bufferLength());
result = true;
+ } else {
+ m_bufferLength = audioLength(m_format, BufferDurationUs);
+ m_buffer.resize(m_bufferLength);
+ m_buffer.fill(0);
+ emit bufferLengthChanged(bufferLength());
+ if (m_generateTone) {
+ if (0 == m_tone.endFreq) {
+ const qreal nyquist = nyquistFrequency(m_format);
+ m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist);
+ }
+ // Call function defined in utils.h, at global scope
+ ::generateTone(m_tone, m_format, m_buffer);
+ m_dataLength = m_bufferLength;
+ emit dataLengthChanged(dataLength());
+ emit bufferChanged(0, m_dataLength, m_buffer);
+ setRecordPosition(m_bufferLength);
+ result = true;
+ } else {
+ emit bufferChanged(0, 0, m_buffer);
+ m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this);
+ m_audioInput->setNotifyInterval(NotifyIntervalMs);
+ result = true;
+ }
}
- } else {
- m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this);
- m_audioInput->setNotifyInterval(NotifyIntervalMs);
- result = true;
+ m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this);
+ m_audioOutput->setNotifyInterval(NotifyIntervalMs);
}
-
- m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this);
- m_audioOutput->setNotifyInterval(NotifyIntervalMs);
- m_spectrumLengthBytes = SpectrumLengthSamples *
- (m_format.sampleSize() / 8) * m_format.channels();
} else {
if (m_file)
emit errorMessage(tr("Audio format not supported"),
@@ -501,6 +517,8 @@ bool Engine::initialize()
emit errorMessage(tr("No common input / output format found"), "");
}
+ ENGINE_DEBUG << "Engine::initialize" << "m_bufferLength" << m_bufferLength;
+ ENGINE_DEBUG << "Engine::initialize" << "m_dataLength" << m_dataLength;
ENGINE_DEBUG << "Engine::initialize" << "format" << m_format;
return result;
@@ -510,21 +528,15 @@ bool Engine::selectFormat()
{
bool foundSupportedFormat = false;
- if (m_file) {
- // Header is read from the WAV file; just need to check whether
- // it is supported by the audio output device
- QAudioFormat format = m_wavFile.format();
- if (m_audioOutputDevice.isFormatSupported(m_wavFile.format())) {
- setFormat(m_wavFile.format());
+ if (m_file || QAudioFormat() != m_format) {
+ QAudioFormat format = m_format;
+ if (m_file)
+ // Header is read from the WAV file; just need to check whether
+ // it is supported by the audio output device
+ format = m_file->fileFormat();
+ if (m_audioOutputDevice.isFormatSupported(format)) {
+ setFormat(format);
foundSupportedFormat = true;
- } else {
- // Try flipping mono <-> stereo
- const int channels = (format.channels() == 1) ? 2 : 1;
- format.setChannels(channels);
- if (m_audioOutputDevice.isFormatSupported(format)) {
- setFormat(format);
- foundSupportedFormat = true;
- }
}
} else {
@@ -648,12 +660,12 @@ void Engine::calculateLevel(qint64 position, qint64 length)
Q_UNUSED(position)
Q_UNUSED(length)
#else
- Q_ASSERT(position + length <= m_dataLength);
+ Q_ASSERT(position + length <= m_bufferPosition + m_dataLength);
qreal peakLevel = 0.0;
qreal sum = 0.0;
- const char *ptr = m_buffer.constData() + position;
+ const char *ptr = m_buffer.constData() + position - m_bufferPosition;
const char *const end = ptr + length;
while (ptr < end) {
const qint16 value = *reinterpret_cast<const qint16*>(ptr);
@@ -679,18 +691,18 @@ void Engine::calculateSpectrum(qint64 position)
#ifdef DISABLE_SPECTRUM
Q_UNUSED(position)
#else
- Q_ASSERT(position + m_spectrumLengthBytes <= m_dataLength);
- Q_ASSERT(0 == m_spectrumLengthBytes % 2); // constraint of FFT algorithm
+ Q_ASSERT(position + m_spectrumBufferLength <= m_bufferPosition + m_dataLength);
+ Q_ASSERT(0 == m_spectrumBufferLength % 2); // constraint of FFT algorithm
// QThread::currentThread is marked 'for internal use only', but
// we're only using it for debug output here, so it's probably OK :)
ENGINE_DEBUG << "Engine::calculateSpectrum" << QThread::currentThread()
- << "count" << m_count << "pos" << position << "len" << m_spectrumLengthBytes
+ << "count" << m_count << "pos" << position << "len" << m_spectrumBufferLength
<< "spectrumAnalyser.isReady" << m_spectrumAnalyser.isReady();
if(m_spectrumAnalyser.isReady()) {
- m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position,
- m_spectrumLengthBytes);
+ m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position - m_bufferPosition,
+ m_spectrumBufferLength);
m_spectrumPosition = position;
m_spectrumAnalyser.calculate(m_spectrumBuffer, m_format);
}
@@ -701,6 +713,9 @@ void Engine::setFormat(const QAudioFormat &format)
{
const bool changed = (format != m_format);
m_format = format;
+ m_levelBufferLength = audioLength(m_format, LevelWindowUs);
+ m_spectrumBufferLength = SpectrumLengthSamples *
+ (m_format.sampleSize() / 8) * m_format.channels();
if (changed)
emit formatChanged(m_format);
}
diff --git a/demos/spectrum/app/engine.h b/demos/spectrum/app/engine.h
index e14ac83..c97083e 100644
--- a/demos/spectrum/app/engine.h
+++ b/demos/spectrum/app/engine.h
@@ -91,12 +91,6 @@ public:
QAudio::State state() const { return m_state; }
/**
- * \return Reference to internal audio buffer
- * \note This reference is valid for the lifetime of the Engine
- */
- const QByteArray& buffer() const { return m_buffer; }
-
- /**
* \return Current audio format
* \note May be QAudioFormat() if engine is not initialized
*/
@@ -129,7 +123,7 @@ public:
/**
* Position of the audio input device.
- * \return Position in microseconds.
+ * \return Position in bytes.
*/
qint64 recordPosition() const { return m_recordPosition; }
@@ -147,27 +141,21 @@ public:
/**
* Position of the audio output device.
- * \return Position in microseconds.
+ * \return Position in bytes.
*/
qint64 playPosition() const { return m_playPosition; }
/**
* Length of the internal engine buffer.
- * \return Buffer length in microseconds.
+ * \return Buffer length in bytes.
*/
- qint64 bufferDuration() const;
+ qint64 bufferLength() const;
/**
* Amount of data held in the buffer.
- * \return Data duration in microseconds.
+ * \return Data length in bytes.
*/
- qint64 dataDuration() const;
-
- /**
- * Returns the size of the underlying audio buffer in bytes.
- * This should be an approximation of the capture latency.
- */
- qint64 audioBufferLength() const;
+ qint64 dataLength() const { return m_dataLength; }
/**
* Set window function applied to audio data before spectral analysis.
@@ -203,23 +191,23 @@ signals:
* Length of buffer has changed.
* \param duration Duration in microseconds
*/
- void bufferDurationChanged(qint64 duration);
+ void bufferLengthChanged(qint64 duration);
/**
* Amount of data in buffer has changed.
- * \param duration Duration of data in microseconds
+ * \param Length of data in bytes
*/
- void dataDurationChanged(qint64 duration);
+ void dataLengthChanged(qint64 duration);
/**
* Position of the audio input device has changed.
- * \param position Position in microseconds
+ * \param position Position in bytes
*/
void recordPositionChanged(qint64 position);
/**
* Position of the audio output device has changed.
- * \param position Position in microseconds
+ * \param position Position in bytes
*/
void playPositionChanged(qint64 position);
@@ -233,12 +221,19 @@ signals:
/**
* Spectrum has changed.
- * \param position Position of start of window in microseconds
- * \param length Length of window in microseconds
+ * \param position Position of start of window in bytes
+ * \param length Length of window in bytes
* \param spectrum Resulting frequency spectrum
*/
void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum);
+ /**
+ * Buffer containing audio data has changed.
+ * \param position Position of start of buffer in bytes
+ * \param buffer Buffer
+ */
+ void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer);
+
private slots:
void audioNotify();
void audioStateChanged(QAudio::State state);
@@ -246,6 +241,7 @@ private slots:
void spectrumChanged(const FrequencySpectrum &spectrum);
private:
+ void resetAudioDevices();
bool initialize();
bool selectFormat();
void stopRecording();
@@ -275,8 +271,10 @@ private:
bool m_generateTone;
SweptTone m_tone;
- QFile* m_file;
- WavFile m_wavFile;
+ WavFile* m_file;
+ // We need a second file handle via which to read data into m_buffer
+ // for analysis
+ WavFile* m_analysisFile;
QAudioFormat m_format;
@@ -293,12 +291,15 @@ private:
QBuffer m_audioOutputIODevice;
QByteArray m_buffer;
+ qint64 m_bufferPosition;
+ qint64 m_bufferLength;
qint64 m_dataLength;
+ int m_levelBufferLength;
qreal m_rmsLevel;
qreal m_peakLevel;
- int m_spectrumLengthBytes;
+ int m_spectrumBufferLength;
QByteArray m_spectrumBuffer;
SpectrumAnalyser m_spectrumAnalyser;
qint64 m_spectrumPosition;
diff --git a/demos/spectrum/app/mainwidget.cpp b/demos/spectrum/app/mainwidget.cpp
index dd51a91..4b53bbe 100644
--- a/demos/spectrum/app/mainwidget.cpp
+++ b/demos/spectrum/app/mainwidget.cpp
@@ -65,7 +65,7 @@ MainWidget::MainWidget(QWidget *parent)
, m_mode(NoMode)
, m_engine(new Engine(this))
#ifndef DISABLE_WAVEFORM
- , m_waveform(new Waveform(m_engine->buffer(), this))
+ , m_waveform(new Waveform(this))
#endif
, m_progressBar(new ProgressBar(this))
, m_spectrograph(new Spectrograph(this))
@@ -166,19 +166,18 @@ void MainWidget::timerEvent(QTimerEvent *event)
m_infoMessage->setText("");
}
-void MainWidget::positionChanged(qint64 positionUs)
+void MainWidget::audioPositionChanged(qint64 position)
{
#ifndef DISABLE_WAVEFORM
- qint64 positionBytes = audioLength(m_engine->format(), positionUs);
- m_waveform->positionChanged(positionBytes);
+ m_waveform->audioPositionChanged(position);
#else
- Q_UNUSED(positionUs)
+ Q_UNUSED(position)
#endif
}
-void MainWidget::bufferDurationChanged(qint64 durationUs)
+void MainWidget::bufferLengthChanged(qint64 length)
{
- m_progressBar->bufferDurationChanged(durationUs);
+ m_progressBar->bufferLengthChanged(length);
}
@@ -186,33 +185,22 @@ void MainWidget::bufferDurationChanged(qint64 durationUs)
// Private slots
//-----------------------------------------------------------------------------
-void MainWidget::dataDurationChanged(qint64 duration)
-{
-#ifndef DISABLE_WAVEFORM
- const qint64 dataLength = audioLength(m_engine->format(), duration);
- m_waveform->dataLengthChanged(dataLength);
-#else
- Q_UNUSED(duration)
-#endif
-
- updateButtonStates();
-}
-
void MainWidget::showFileDialog()
{
- reset();
const QString dir;
const QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open WAV file"), dir, "*.wav");
if (fileNames.count()) {
+ reset();
setMode(LoadFileMode);
m_engine->loadFile(fileNames.front());
updateButtonStates();
+ } else {
+ updateModeMenu();
}
}
void MainWidget::showSettingsDialog()
{
- reset();
m_settingsDialog->exec();
if (m_settingsDialog->result() == QDialog::Accepted) {
m_engine->setAudioInputDevice(m_settingsDialog->inputDevice());
@@ -223,9 +211,9 @@ void MainWidget::showSettingsDialog()
void MainWidget::showToneGeneratorDialog()
{
- reset();
m_toneGeneratorDialog->exec();
if (m_toneGeneratorDialog->result() == QDialog::Accepted) {
+ reset();
setMode(GenerateToneMode);
const qreal amplitude = m_toneGeneratorDialog->amplitude();
if (m_toneGeneratorDialog->isFrequencySweepEnabled()) {
@@ -236,6 +224,8 @@ void MainWidget::showToneGeneratorDialog()
m_engine->generateTone(tone);
updateButtonStates();
}
+ } else {
+ updateModeMenu();
}
}
@@ -360,13 +350,13 @@ void MainWidget::connectUi()
CHECKED_CONNECT(m_engine, SIGNAL(formatChanged(const QAudioFormat &)),
this, SLOT(formatChanged(const QAudioFormat &)));
- m_progressBar->bufferDurationChanged(m_engine->bufferDuration());
+ m_progressBar->bufferLengthChanged(m_engine->bufferLength());
- CHECKED_CONNECT(m_engine, SIGNAL(bufferDurationChanged(qint64)),
- this, SLOT(bufferDurationChanged(qint64)));
+ CHECKED_CONNECT(m_engine, SIGNAL(bufferLengthChanged(qint64)),
+ this, SLOT(bufferLengthChanged(qint64)));
- CHECKED_CONNECT(m_engine, SIGNAL(dataDurationChanged(qint64)),
- this, SLOT(dataDurationChanged(qint64)));
+ CHECKED_CONNECT(m_engine, SIGNAL(dataLengthChanged(qint64)),
+ this, SLOT(updateButtonStates()));
CHECKED_CONNECT(m_engine, SIGNAL(recordPositionChanged(qint64)),
m_progressBar, SLOT(recordPositionChanged(qint64)));
@@ -375,10 +365,10 @@ void MainWidget::connectUi()
m_progressBar, SLOT(playPositionChanged(qint64)));
CHECKED_CONNECT(m_engine, SIGNAL(recordPositionChanged(qint64)),
- this, SLOT(positionChanged(qint64)));
+ this, SLOT(audioPositionChanged(qint64)));
CHECKED_CONNECT(m_engine, SIGNAL(playPositionChanged(qint64)),
- this, SLOT(positionChanged(qint64)));
+ this, SLOT(audioPositionChanged(qint64)));
CHECKED_CONNECT(m_engine, SIGNAL(levelChanged(qreal, qreal, int)),
m_levelMeter, SLOT(levelChanged(qreal, qreal, int)));
@@ -394,6 +384,11 @@ void MainWidget::connectUi()
CHECKED_CONNECT(m_spectrograph, SIGNAL(infoMessage(QString, int)),
this, SLOT(infoMessage(QString, int)));
+
+#ifndef DISABLE_WAVEFORM
+ CHECKED_CONNECT(m_engine, SIGNAL(bufferChanged(qint64, qint64, const QByteArray &)),
+ m_waveform, SLOT(bufferChanged(qint64, qint64, const QByteArray &)));
+#endif
}
void MainWidget::createMenus()
@@ -425,7 +420,7 @@ void MainWidget::updateButtonStates()
QAudio::IdleState == m_engine->state());
m_pauseButton->setEnabled(pauseEnabled);
- const bool playEnabled = (m_engine->dataDuration() &&
+ const bool playEnabled = (/*m_engine->dataLength() &&*/
(QAudio::AudioOutput != m_engine->mode() ||
(QAudio::ActiveState != m_engine->state() &&
QAudio::IdleState != m_engine->state())));
@@ -445,10 +440,14 @@ void MainWidget::reset()
void MainWidget::setMode(Mode mode)
{
-
m_mode = mode;
- m_loadFileAction->setChecked(LoadFileMode == mode);
- m_generateToneAction->setChecked(GenerateToneMode == mode);
- m_recordAction->setChecked(RecordMode == mode);
+ updateModeMenu();
+}
+
+void MainWidget::updateModeMenu()
+{
+ m_loadFileAction->setChecked(LoadFileMode == m_mode);
+ m_generateToneAction->setChecked(GenerateToneMode == m_mode);
+ m_recordAction->setChecked(RecordMode == m_mode);
}
diff --git a/demos/spectrum/app/mainwidget.h b/demos/spectrum/app/mainwidget.h
index ddab8b7..13131c0 100644
--- a/demos/spectrum/app/mainwidget.h
+++ b/demos/spectrum/app/mainwidget.h
@@ -80,21 +80,21 @@ public slots:
const FrequencySpectrum &spectrum);
void infoMessage(const QString &message, int timeoutMs);
void errorMessage(const QString &heading, const QString &detail);
- void positionChanged(qint64 position);
- void bufferDurationChanged(qint64 duration);
+ void audioPositionChanged(qint64 position);
+ void bufferLengthChanged(qint64 length);
private slots:
void showFileDialog();
void showSettingsDialog();
void showToneGeneratorDialog();
void initializeRecord();
- void dataDurationChanged(qint64 duration);
+ void updateModeMenu();
+ void updateButtonStates();
private:
void createUi();
void createMenus();
void connectUi();
- void updateButtonStates();
void reset();
enum Mode {
@@ -111,7 +111,9 @@ private:
Engine* m_engine;
+#ifndef DISABLE_WAVEFORM
Waveform* m_waveform;
+#endif
ProgressBar* m_progressBar;
Spectrograph* m_spectrograph;
LevelMeter* m_levelMeter;
diff --git a/demos/spectrum/app/progressbar.cpp b/demos/spectrum/app/progressbar.cpp
index 6bfc690..0ac76f1 100644
--- a/demos/spectrum/app/progressbar.cpp
+++ b/demos/spectrum/app/progressbar.cpp
@@ -44,7 +44,7 @@
ProgressBar::ProgressBar(QWidget *parent)
: QWidget(parent)
- , m_bufferDuration(0)
+ , m_bufferLength(0)
, m_recordPosition(0)
, m_playPosition(0)
, m_windowPosition(0)
@@ -64,7 +64,7 @@ ProgressBar::~ProgressBar()
void ProgressBar::reset()
{
- m_bufferDuration = 0;
+ m_bufferLength = 0;
m_recordPosition = 0;
m_playPosition = 0;
m_windowPosition = 0;
@@ -86,26 +86,26 @@ void ProgressBar::paintEvent(QPaintEvent * /*event*/)
painter.fillRect(rect(), Qt::black);
#endif
- if (m_bufferDuration) {
+ if (m_bufferLength) {
QRect bar = rect();
- const qreal play = qreal(m_playPosition) / m_bufferDuration;
+ const qreal play = qreal(m_playPosition) / m_bufferLength;
bar.setLeft(rect().left() + play * rect().width());
- const qreal record = qreal(m_recordPosition) / m_bufferDuration;
+ const qreal record = qreal(m_recordPosition) / m_bufferLength;
bar.setRight(rect().left() + record * rect().width());
painter.fillRect(bar, bufferColor);
QRect window = rect();
- const qreal windowLeft = qreal(m_windowPosition) / m_bufferDuration;
+ const qreal windowLeft = qreal(m_windowPosition) / m_bufferLength;
window.setLeft(rect().left() + windowLeft * rect().width());
- const qreal windowWidth = qreal(m_windowLength) / m_bufferDuration;
+ const qreal windowWidth = qreal(m_windowLength) / m_bufferLength;
window.setWidth(windowWidth * rect().width());
painter.fillRect(window, windowColor);
}
}
-void ProgressBar::bufferDurationChanged(qint64 bufferSize)
+void ProgressBar::bufferLengthChanged(qint64 bufferSize)
{
- m_bufferDuration = bufferSize;
+ m_bufferLength = bufferSize;
m_recordPosition = 0;
m_playPosition = 0;
m_windowPosition = 0;
@@ -116,7 +116,7 @@ void ProgressBar::bufferDurationChanged(qint64 bufferSize)
void ProgressBar::recordPositionChanged(qint64 recordPosition)
{
Q_ASSERT(recordPosition >= 0);
- Q_ASSERT(recordPosition <= m_bufferDuration);
+ Q_ASSERT(recordPosition <= m_bufferLength);
m_recordPosition = recordPosition;
repaint();
}
@@ -124,7 +124,7 @@ void ProgressBar::recordPositionChanged(qint64 recordPosition)
void ProgressBar::playPositionChanged(qint64 playPosition)
{
Q_ASSERT(playPosition >= 0);
- Q_ASSERT(playPosition <= m_bufferDuration);
+ Q_ASSERT(playPosition <= m_bufferLength);
m_playPosition = playPosition;
repaint();
}
@@ -132,8 +132,8 @@ void ProgressBar::playPositionChanged(qint64 playPosition)
void ProgressBar::windowChanged(qint64 position, qint64 length)
{
Q_ASSERT(position >= 0);
- Q_ASSERT(position <= m_bufferDuration);
- Q_ASSERT(position + length <= m_bufferDuration);
+ Q_ASSERT(position <= m_bufferLength);
+ Q_ASSERT(position + length <= m_bufferLength);
m_windowPosition = position;
m_windowLength = length;
repaint();
diff --git a/demos/spectrum/app/progressbar.h b/demos/spectrum/app/progressbar.h
index 8514adb..e715cf5 100644
--- a/demos/spectrum/app/progressbar.h
+++ b/demos/spectrum/app/progressbar.h
@@ -57,13 +57,13 @@ public:
void paintEvent(QPaintEvent *event);
public slots:
- void bufferDurationChanged(qint64 bufferSize);
+ void bufferLengthChanged(qint64 length);
void recordPositionChanged(qint64 recordPosition);
void playPositionChanged(qint64 playPosition);
void windowChanged(qint64 position, qint64 length);
private:
- qint64 m_bufferDuration;
+ qint64 m_bufferLength;
qint64 m_recordPosition;
qint64 m_playPosition;
qint64 m_windowPosition;
diff --git a/demos/spectrum/app/spectrumanalyser.cpp b/demos/spectrum/app/spectrumanalyser.cpp
index 1cc47a6..2fa17b1 100644
--- a/demos/spectrum/app/spectrumanalyser.cpp
+++ b/demos/spectrum/app/spectrumanalyser.cpp
@@ -64,6 +64,8 @@ SpectrumAnalyserThread::SpectrumAnalyserThread(QObject *parent)
#endif
{
#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD
+ // moveToThread() cannot be called on a QObject with a parent
+ setParent(0);
moveToThread(m_thread);
m_thread->start();
#endif
diff --git a/demos/spectrum/app/utils.cpp b/demos/spectrum/app/utils.cpp
index 4ead6c2..49a7626 100644
--- a/demos/spectrum/app/utils.cpp
+++ b/demos/spectrum/app/utils.cpp
@@ -49,8 +49,10 @@ qint64 audioDuration(const QAudioFormat &format, qint64 bytes)
qint64 audioLength(const QAudioFormat &format, qint64 microSeconds)
{
- return (format.frequency() * format.channels() * (format.sampleSize() / 8))
+ qint64 result = (format.frequency() * format.channels() * (format.sampleSize() / 8))
* microSeconds / 1000000;
+ result -= result % (format.channelCount() * format.sampleSize());
+ return result;
}
qreal nyquistFrequency(const QAudioFormat &format)
diff --git a/demos/spectrum/app/waveform.cpp b/demos/spectrum/app/waveform.cpp
index 1f7d315..bd854c0 100644
--- a/demos/spectrum/app/waveform.cpp
+++ b/demos/spectrum/app/waveform.cpp
@@ -44,12 +44,18 @@
#include <QResizeEvent>
#include <QDebug>
-
-Waveform::Waveform(const QByteArray &buffer, QWidget *parent)
+//#define PAINT_EVENT_TRACE
+#ifdef PAINT_EVENT_TRACE
+# define WAVEFORM_PAINT_DEBUG qDebug()
+#else
+# define WAVEFORM_PAINT_DEBUG nullDebug()
+#endif
+
+Waveform::Waveform(QWidget *parent)
: QWidget(parent)
- , m_buffer(buffer)
- , m_dataLength(0)
- , m_position(0)
+ , m_bufferPosition(0)
+ , m_bufferLength(0)
+ , m_audioPosition(0)
, m_active(false)
, m_tileLength(0)
, m_tileArrayStart(0)
@@ -72,19 +78,19 @@ void Waveform::paintEvent(QPaintEvent * /*event*/)
painter.fillRect(rect(), Qt::black);
if (m_active) {
- WAVEFORM_DEBUG << "Waveform::paintEvent"
- << "windowPosition" << m_windowPosition
- << "windowLength" << m_windowLength;
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent"
+ << "windowPosition" << m_windowPosition
+ << "windowLength" << m_windowLength;
qint64 pos = m_windowPosition;
const qint64 windowEnd = m_windowPosition + m_windowLength;
int destLeft = 0;
int destRight = 0;
while (pos < windowEnd) {
const TilePoint point = tilePoint(pos);
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos
- << "tileIndex" << point.index
- << "positionOffset" << point.positionOffset
- << "pixelOffset" << point.pixelOffset;
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos
+ << "tileIndex" << point.index
+ << "positionOffset" << point.positionOffset
+ << "pixelOffset" << point.pixelOffset;
if (point.index != NullIndex) {
const Tile &tile = m_tiles[point.index];
@@ -104,9 +110,9 @@ void Waveform::paintEvent(QPaintEvent * /*event*/)
sourceRect.setLeft(point.pixelOffset);
sourceRect.setRight(sourceRight);
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index
- << "source" << point.pixelOffset << sourceRight
- << "dest" << destLeft << destRight;
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index
+ << "source" << point.pixelOffset << sourceRight
+ << "dest" << destLeft << destRight;
painter.drawPixmap(destRect, *tile.pixmap, sourceRect);
@@ -114,25 +120,25 @@ void Waveform::paintEvent(QPaintEvent * /*event*/)
if (point.index < m_tiles.count()) {
pos = tilePosition(point.index + 1);
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos ->" << pos;
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos ->" << pos;
} else {
// Reached end of tile array
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "reached end of tile array";
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "reached end of tile array";
break;
}
} else {
// Passed last tile which is painted
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted";
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted";
break;
}
} else {
// pos is past end of tile array
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array";
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array";
break;
}
}
- WAVEFORM_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight;
+ WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight;
}
}
@@ -146,7 +152,6 @@ void Waveform::initialize(const QAudioFormat &format, qint64 audioBufferSize, qi
{
WAVEFORM_DEBUG << "Waveform::initialize"
<< "audioBufferSize" << audioBufferSize
- << "m_buffer.size()" << m_buffer.size()
<< "windowDurationUs" << windowDurationUs;
reset();
@@ -186,8 +191,9 @@ void Waveform::reset()
{
WAVEFORM_DEBUG << "Waveform::reset";
- m_dataLength = 0;
- m_position = 0;
+ m_bufferPosition = 0;
+ m_buffer = QByteArray();
+ m_audioPosition = 0;
m_format = QAudioFormat();
m_active = false;
deletePixmaps();
@@ -198,30 +204,31 @@ void Waveform::reset()
m_windowLength = 0;
}
-void Waveform::dataLengthChanged(qint64 length)
+void Waveform::bufferChanged(qint64 position, qint64 length, const QByteArray &buffer)
{
- WAVEFORM_DEBUG << "Waveform::dataLengthChanged" << length;
- const qint64 oldLength = m_dataLength;
- m_dataLength = length;
-
- if (m_active) {
- if (m_dataLength < oldLength)
- positionChanged(m_dataLength);
- else
- paintTiles();
- }
+ WAVEFORM_DEBUG << "Waveform::bufferChanged"
+ << "audioPosition" << m_audioPosition
+ << "bufferPosition" << position
+ << "bufferLength" << length;
+ m_bufferPosition = position;
+ m_bufferLength = length;
+ m_buffer = buffer;
+ paintTiles();
}
-void Waveform::positionChanged(qint64 position)
+void Waveform::audioPositionChanged(qint64 position)
{
- WAVEFORM_DEBUG << "Waveform::positionChanged" << position;
-
- if (position + m_windowLength > m_dataLength)
- position = m_dataLength - m_windowLength;
-
- m_position = position;
-
- setWindowPosition(position);
+ WAVEFORM_DEBUG << "Waveform::audioPositionChanged"
+ << "audioPosition" << position
+ << "bufferPosition" << m_bufferPosition
+ << "bufferLength" << m_bufferLength;
+
+ if (position >= m_bufferPosition) {
+ if (position + m_windowLength > m_bufferPosition + m_bufferLength)
+ position = qMax(qint64(0), m_bufferPosition + m_bufferLength - m_windowLength);
+ m_audioPosition = position;
+ setWindowPosition(position);
+ }
}
void Waveform::deletePixmaps()
@@ -255,8 +262,6 @@ void Waveform::createPixmaps(const QSize &widgetSize)
m_tiles[i].pixmap = m_pixmaps[i];
m_tiles[i].painted = false;
}
-
- paintTiles();
}
void Waveform::setWindowPosition(qint64 position)
@@ -327,8 +332,9 @@ bool Waveform::paintTiles()
for (int i=0; i<m_tiles.count(); ++i) {
const Tile &tile = m_tiles[i];
if (!tile.painted) {
- const qint64 tileEnd = m_tileArrayStart + (i + 1) * m_tileLength;
- if (m_dataLength >= tileEnd) {
+ const qint64 tileStart = m_tileArrayStart + i * m_tileLength;
+ const qint64 tileEnd = tileStart + m_tileLength;
+ if (m_bufferPosition <= tileStart && m_bufferPosition + m_bufferLength >= tileEnd) {
paintTile(i);
updateRequired = true;
}
@@ -343,16 +349,23 @@ bool Waveform::paintTiles()
void Waveform::paintTile(int index)
{
- WAVEFORM_DEBUG << "Waveform::paintTile" << "index" << index;
-
const qint64 tileStart = m_tileArrayStart + index * m_tileLength;
- Q_ASSERT(m_dataLength >= tileStart + m_tileLength);
+
+ WAVEFORM_DEBUG << "Waveform::paintTile"
+ << "index" << index
+ << "bufferPosition" << m_bufferPosition
+ << "bufferLength" << m_bufferLength
+ << "start" << tileStart
+ << "end" << tileStart + m_tileLength;
+
+ Q_ASSERT(m_bufferPosition <= tileStart);
+ Q_ASSERT(m_bufferPosition + m_bufferLength >= tileStart + m_tileLength);
Tile &tile = m_tiles[index];
Q_ASSERT(!tile.painted);
const qint16* base = reinterpret_cast<const qint16*>(m_buffer.constData());
- const qint16* buffer = base + (tileStart / 2);
+ const qint16* buffer = base + ((tileStart - m_bufferPosition) / 2);
const int numSamples = m_tileLength / (2 * m_format.channels());
QPainter painter(tile.pixmap);
@@ -376,6 +389,11 @@ void Waveform::paintTile(int index)
for (int i=0; i<numSamples; ++i) {
const qint16* ptr = buffer + i * m_format.channels();
+
+ const int offset = reinterpret_cast<const char*>(ptr) - m_buffer.constData();
+ Q_ASSERT(offset >= 0);
+ Q_ASSERT(offset < m_bufferLength);
+
const qint16 pcmValue = *ptr;
const qreal realValue = pcmToReal(pcmValue);
diff --git a/demos/spectrum/app/waveform.h b/demos/spectrum/app/waveform.h
index 57c9eec..1c54c86 100644
--- a/demos/spectrum/app/waveform.h
+++ b/demos/spectrum/app/waveform.h
@@ -60,7 +60,7 @@ QT_FORWARD_DECLARE_CLASS(QByteArray)
class Waveform : public QWidget {
Q_OBJECT
public:
- Waveform(const QByteArray &buffer, QWidget *parent = 0);
+ Waveform(QWidget *parent = 0);
~Waveform();
// QWidget
@@ -73,8 +73,8 @@ public:
void setAutoUpdatePosition(bool enabled);
public slots:
- void dataLengthChanged(qint64 length);
- void positionChanged(qint64 position);
+ void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer);
+ void audioPositionChanged(qint64 position);
private:
static const int NullIndex = -1;
@@ -167,9 +167,11 @@ private:
void resetTiles(qint64 newStartPos);
private:
- const QByteArray& m_buffer;
- qint64 m_dataLength;
- qint64 m_position;
+ qint64 m_bufferPosition;
+ qint64 m_bufferLength;
+ QByteArray m_buffer;
+
+ qint64 m_audioPosition;
QAudioFormat m_format;
bool m_active;
diff --git a/demos/spectrum/app/wavfile.cpp b/demos/spectrum/app/wavfile.cpp
index 74d5918..44c3ac5 100644
--- a/demos/spectrum/app/wavfile.cpp
+++ b/demos/spectrum/app/wavfile.cpp
@@ -78,179 +78,74 @@ struct CombinedHeader
WAVEHeader wave;
};
-
-
-WavFile::WavFile(const QAudioFormat &format, qint64 dataLength)
- : m_format(format)
- , m_dataLength(dataLength)
- , m_dataPosition(0)
-{
-}
-
-bool WavFile::readHeader(QIODevice &device)
-{
- if (!device.isSequential()) {
- if (!device.seek(0))
- return false;
- // XXX: else, assume that current position is the start of the header
- }
-
- CombinedHeader header;
- if (device.read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) != sizeof(CombinedHeader))
- return false;
-
- if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
- || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
- && memcmp(&header.riff.type, "WAVE", 4) == 0
- && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
- && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) {
-
- // Read off remaining header information
- DATAHeader dataHeader;
-
- if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) {
- // Extended data available
- quint16 extraFormatBytes;
- if (device.peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
- return false;
- const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
- if (device.read(throwAwayBytes).size() != throwAwayBytes)
- return false;
- }
-
- if (device.read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
- return false;
-
- // Establish format
- if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
- m_format.setByteOrder(QAudioFormat::LittleEndian);
- else
- m_format.setByteOrder(QAudioFormat::BigEndian);
-
- int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
- m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
- m_format.setCodec("audio/pcm");
- m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
- m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
- m_format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
-
- m_dataLength = qFromLittleEndian<quint32>(dataHeader.descriptor.size);
- m_dataPosition = 0;
- }
-
- return true;
-}
-
-bool WavFile::writeHeader(QIODevice &device)
+WavFile::WavFile(QObject *parent)
+ : QFile(parent)
+ , m_headerLength(0)
{
- CombinedHeader header;
- DATAHeader dataHeader;
-
- memset(&header, 0, sizeof(CombinedHeader));
-
- // RIFF header
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- strncpy(&header.riff.descriptor.id[0], "RIFF", 4);
- else
- strncpy(&header.riff.descriptor.id[0], "RIFX", 4);
- qToLittleEndian<quint32>(quint32(m_dataLength + sizeof(CombinedHeader) + sizeof(DATAHeader) - sizeof(chunk)),
- reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
- strncpy(&header.riff.type[0], "WAVE", 4);
-
- // WAVE header
- strncpy(&header.wave.descriptor.id[0], "fmt ", 4);
- qToLittleEndian<quint32>(quint32(16),
- reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
- qToLittleEndian<quint16>(quint16(1),
- reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
- qToLittleEndian<quint16>(quint16(m_format.channels()),
- reinterpret_cast<unsigned char*>(&header.wave.numChannels));
- qToLittleEndian<quint32>(quint32(m_format.frequency()),
- reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
- qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8),
- reinterpret_cast<unsigned char*>(&header.wave.byteRate));
- qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8),
- reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
- qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
- reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
-
- // DATA header
- strncpy(dataHeader.descriptor.id, "data", 4);
- qToLittleEndian<quint32>(quint32(m_dataLength),
- reinterpret_cast<unsigned char*>(&dataHeader.descriptor.size));
- return device.write(reinterpret_cast<const char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader)
- && device.write(reinterpret_cast<const char*>(&dataHeader), sizeof(DATAHeader)) == sizeof(DATAHeader);
}
-const QAudioFormat& WavFile::format() const
+bool WavFile::open(const QString &fileName)
{
- return m_format;
+ close();
+ setFileName(fileName);
+ return QFile::open(QIODevice::ReadOnly) && readHeader();
}
-qint64 WavFile::dataLength() const
+const QAudioFormat &WavFile::fileFormat() const
{
- return m_dataLength;
+ return m_fileFormat;
}
-qint64 WavFile::headerLength()
+qint64 WavFile::headerLength() const
{
- return sizeof(CombinedHeader);
-}
-
-bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength)
-{
- bool result = false;
- if (!device.isSequential()) {
- device.seek(40);
- unsigned char dataLengthLE[4];
- qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);
- result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);
- }
- return result;
+return m_headerLength;
}
-qint64 WavFile::readData(QIODevice &device, QByteArray &buffer,
- QAudioFormat outputFormat)
+bool WavFile::readHeader()
{
- // Sanity checks
- if (!outputFormat.isValid())
- outputFormat = m_format;
-
- if (!isPCMS16LE(outputFormat) || !isPCMS16LE(m_format))
- return 0;
-
- if (m_dataPosition == m_dataLength)
- return 0;
-
- // Process
- qint64 result = 0;
-
- const int frameSize = 2 * m_format.channels(); // 16 bit samples
- QVector<char> inputSample(frameSize);
-
- qint16 *output = reinterpret_cast<qint16*>(buffer.data());
+ seek(0);
+ CombinedHeader header;
+ bool result = read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader);
+ if (result) {
+ if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
+ || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
+ && memcmp(&header.riff.type, "WAVE", 4) == 0
+ && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
+ && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) {
+
+ // Read off remaining header information
+ DATAHeader dataHeader;
+
+ if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) {
+ // Extended data available
+ quint16 extraFormatBytes;
+ if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
+ return false;
+ const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
+ if (read(throwAwayBytes).size() != throwAwayBytes)
+ return false;
+ }
- while (result < buffer.size()) {
- if (m_dataPosition == m_dataLength)
- break;
+ if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
+ return false;
- // XXX only working with particular alignments
- if (device.read(inputSample.data(), inputSample.count())) {
- int inputIdx = 0;
- for (int outputIdx = 0; outputIdx < outputFormat.channels(); ++outputIdx) {
- const qint16* input = reinterpret_cast<const qint16*>(inputSample.data() + 2 * inputIdx);
- *output++ = qFromLittleEndian<qint16>(*input);
- result += 2;
- if (inputIdx < m_format.channels())
- ++inputIdx;
- }
- m_dataPosition += frameSize;
+ // Establish format
+ if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+ m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
+ else
+ m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
+
+ int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
+ m_fileFormat.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
+ m_fileFormat.setCodec("audio/pcm");
+ m_fileFormat.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
+ m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
+ m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
} else {
- break;
+ result = false;
}
}
-
+ m_headerLength = pos();
return result;
}
-
diff --git a/demos/spectrum/app/wavfile.h b/demos/spectrum/app/wavfile.h
index fc14b08..935e935 100644
--- a/demos/spectrum/app/wavfile.h
+++ b/demos/spectrum/app/wavfile.h
@@ -46,38 +46,22 @@
#include <QtCore/qfile.h>
#include <QtMultimedia/qaudioformat.h>
-/**
- * Helper class for reading WAV files
- *
- * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
- */
-class WavFile
+class WavFile : public QFile
{
public:
- WavFile(const QAudioFormat &format = QAudioFormat(),
- qint64 dataLength = 0);
+ WavFile(QObject *parent = 0);
- // Reads WAV header and seeks to start of data
- bool readHeader(QIODevice &device);
+ bool open(const QString &fileName);
+ const QAudioFormat &fileFormat() const;
+ qint64 headerLength() const;
- // Writes WAV header
- bool writeHeader(QIODevice &device);
-
- // Read PCM data
- qint64 readData(QIODevice &device, QByteArray &buffer,
- QAudioFormat outputFormat = QAudioFormat());
-
- const QAudioFormat& format() const;
- qint64 dataLength() const;
-
- static qint64 headerLength();
-
- static bool writeDataLength(QIODevice &device, qint64 dataLength);
+private:
+ bool readHeader();
private:
- QAudioFormat m_format;
- qint64 m_dataLength;
- qint64 m_dataPosition;
+ QAudioFormat m_fileFormat;
+ qint64 m_headerLength;
+
};
#endif
diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp
index b98cd5d..c39da3d 100644
--- a/src/declarative/debugger/qdeclarativedebugservice.cpp
+++ b/src/declarative/debugger/qdeclarativedebugservice.cpp
@@ -204,13 +204,13 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
bool ok = false;
// format: qmljsdebugger=port:3768[,block]
- if (!appD->qmljsDebugArguments.isEmpty()) {
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- if (appD->qmljsDebugArguments.indexOf(QLatin1String("port:")) == 0) {
- int separatorIndex = appD->qmljsDebugArguments.indexOf(QLatin1Char(','));
- port = appD->qmljsDebugArguments.mid(5, separatorIndex - 5).toInt(&ok);
+ if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
+ int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
+ port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
}
- block = appD->qmljsDebugArguments.contains(QLatin1String("block"));
+ block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));
if (ok) {
server = new QDeclarativeDebugServer(port);
@@ -221,7 +221,7 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
} else {
qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
"Format is -qmljsdebugger=port:<port>[,block]").arg(
- appD->qmljsDebugArguments).toAscii().constData());
+ appD->qmljsDebugArgumentsString()).toAscii().constData());
}
}
#endif
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 3323fbc..6c4004e 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -497,7 +497,7 @@ bool QApplicationPrivate::fade_tooltip = false;
bool QApplicationPrivate::animate_toolbox = false;
bool QApplicationPrivate::widgetCount = false;
bool QApplicationPrivate::load_testability = false;
-QString QApplicationPrivate::qmljsDebugArguments;
+QString QApplicationPrivate::qmljs_debug_arguments;
#ifdef QT_KEYPAD_NAVIGATION
# ifdef Q_OS_SYMBIAN
Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
@@ -570,7 +570,7 @@ void QApplicationPrivate::process_cmdline()
if (arg == "-qdevel" || arg == "-qdebug") {
// obsolete argument
} else if (arg.indexOf("-qmljsdebugger=", 0) != -1) {
- qmljsDebugArguments = QString::fromLocal8Bit(arg.right(arg.length() - 15));
+ qmljs_debug_arguments = QString::fromLocal8Bit(arg.right(arg.length() - 15));
} else if (arg.indexOf("-style=", 0) != -1) {
s = QString::fromLocal8Bit(arg.right(arg.length() - 7).toLower());
} else if (arg == "-style" && i < argc-1) {
@@ -6086,6 +6086,11 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
return QPixmap();
}
+QString QApplicationPrivate::qmljsDebugArgumentsString()
+{
+ return qmljs_debug_arguments;
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 9c5095d..a0e1452 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -446,7 +446,8 @@ public:
static bool animate_toolbox;
static bool widgetCount; // Coupled with -widgetcount switch
static bool load_testability; // Coupled with -testability switch
- static QString qmljsDebugArguments; // a string containing arguments for js/qml debugging.
+ static QString qmljs_debug_arguments; // a string containing arguments for js/qml debugging.
+ static QString qmljsDebugArgumentsString(); // access string from other libraries
#ifdef Q_WS_MAC
static bool native_modal_dialog_active;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 5ff2fd4..ae7070e 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -2055,6 +2055,17 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent
}
#endif
break;
+#ifdef Q_SYMBIAN_SUPPORTS_SURFACES
+ case EEventUser:
+ {
+ // GOOM is looking for candidates to kill so indicate that we are
+ // capable of cleaning up by handling this event
+ TInt32 *data = reinterpret_cast<TInt32 *>(event->EventData());
+ if (data[0] == EApaSystemEventShutdown && data[1] == KGoomMemoryLowEvent)
+ return 1;
+ }
+ break;
+#endif
default:
break;
}
diff --git a/src/gui/kernel/qclipboard_s60.cpp b/src/gui/kernel/qclipboard_s60.cpp
index c9b1d23..73280b2 100644
--- a/src/gui/kernel/qclipboard_s60.cpp
+++ b/src/gui/kernel/qclipboard_s60.cpp
@@ -257,18 +257,14 @@ const QMimeData* QClipboard::mimeData(Mode mode) const
}
}
CleanupStack::PopAndDestroy(cb);
- if (dataExists) {
- return d->source();
- }
- else {
- return 0;
- }
-
});
if (err != KErrNone){
qDebug()<< "clipboard is empty/err: " << err;
}
+ if (dataExists) {
+ return d->source();
+ }
}
return 0;
}
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index ca3a9d0..d39a2ba 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -3424,8 +3424,11 @@ bool QS60Style::eventFilter(QObject *object, QEvent *event)
qobject_cast<QCheckBox *>(w))
d->m_pressedWidget = w;
- if ( d->m_pressedWidget)
+ if (d->m_pressedWidget)
d->m_pressedWidget->update();
+#ifdef Q_WS_S60
+ d->touchFeedback(event, w);
+#endif
}
break;
}
diff --git a/src/gui/styles/qs60style_feedbackinterface_p.h b/src/gui/styles/qs60style_feedbackinterface_p.h
new file mode 100644
index 0000000..81fcdc3
--- /dev/null
+++ b/src/gui/styles/qs60style_feedbackinterface_p.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QObject>
+
+class TactileFeedbackInterface : public QObject
+{
+ public:
+ virtual void touchFeedback(QEvent *event, const QWidget *widget) = 0;
+};
+
+Q_DECLARE_INTERFACE(TactileFeedbackInterface, "com.trolltech.Qt.TactileFeedbackInterface/1.0")
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
index b3f4160..b46f75e 100644
--- a/src/gui/styles/qs60style_p.h
+++ b/src/gui/styles/qs60style_p.h
@@ -387,6 +387,7 @@ private: //data members
class QFocusFrame;
class QProgressBar;
class QS60StyleAnimation;
+class TactileFeedbackInterface;
// Private class
#ifdef Q_OS_SYMBIAN
@@ -572,6 +573,8 @@ public:
void stopAnimation(QS60StyleEnums::SkinParts animation);
static QS60StyleAnimation* animationDefinition(QS60StyleEnums::SkinParts part);
static void removeAnimations();
+ //No support for tactile feedback in emulated style
+ void touchFeedback(QEvent *event, const QWidget *widget);
#endif
@@ -626,6 +629,7 @@ private:
#ifdef Q_WS_S60
//list of progress bars having animation running
QList<QProgressBar *> m_bars;
+ TactileFeedbackInterface *m_feedbackPlugin;
#endif
};
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 5dda42e..a1ea308 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -49,6 +49,10 @@
#include "private/qcore_symbian_p.h"
#include "qapplication.h"
+#include "qpluginloader.h"
+#include "qlibraryinfo.h"
+#include "private/qs60style_feedbackinterface_p.h"
+
#include <w32std.h>
#include <AknsConstants.h>
#include <aknconsts.h>
@@ -1143,13 +1147,25 @@ void QS60StylePrivate::setActiveLayout()
Q_GLOBAL_STATIC(QList<QS60StyleAnimation *>, m_animations)
-QS60StylePrivate::QS60StylePrivate()
+QS60StylePrivate::QS60StylePrivate() : m_feedbackPlugin(0)
{
//Animation defaults need to be created when style is instantiated
QS60StyleAnimation* progressBarAnimation = new QS60StyleAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim, 7, 100);
m_animations()->append(progressBarAnimation);
// No need to set active layout, if dynamic metrics API is available
setActiveLayout();
+
+ //Tactile feedback plugin is only available for touch devices.
+ if (isTouchSupported()) {
+ QString pluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ pluginsPath += QLatin1String("/feedback/qtactilefeedback.dll");
+
+ // Create plugin loader
+ QPluginLoader pluginLoader(pluginsPath);
+ // Load plugin and store pointer to the plugin implementation
+ if (pluginLoader.load())
+ m_feedbackPlugin = qobject_cast<TactileFeedbackInterface*>(pluginLoader.instance());
+ }
}
void QS60StylePrivate::removeAnimations()
@@ -1439,6 +1455,12 @@ void QS60StylePrivate::stopAnimation(QS60StyleEnums::SkinParts animationPart)
}
}
+void QS60StylePrivate::touchFeedback(QEvent *event, const QWidget *widget)
+{
+ if (m_feedbackPlugin)
+ m_feedbackPlugin->touchFeedback(event, widget);
+}
+
QVariant QS60StyleModeSpecifics::themeDefinition(
QS60StyleEnums::ThemeDefinitions definition, QS60StyleEnums::SkinParts part)
{
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index ce9d11a..9df32d9 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -55,6 +55,8 @@
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qpainterpath_p.h>
#include <QtGui/private/qstatictext_p.h>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
#include <QtCore/qmath.h>
#include <QDebug>
#include <QSet>
@@ -3060,6 +3062,21 @@ void qt_vg_drawVGImageStencil
vgDrawImage(vgImg);
}
+bool QVGPaintEngine::canVgWritePixels(const QImage &image) const
+{
+ Q_D(const QVGPaintEngine);
+ // vgWritePixels ignores masking, blending and xforms so we can only use it if
+ // ALL of the following conditions are true:
+ // - It is a simple translate, or a scale of -1 on the y-axis (inverted)
+ // - The opacity is totally opaque
+ // - The composition mode is "source" OR "source over" provided the image is opaque
+ return ( d->imageTransform.type() <= QTransform::TxScale
+ && d->imageTransform.m11() == 1.0 && qAbs(d->imageTransform.m22()) == 1.0)
+ && d->opacity == 1.0f
+ && (d->blendMode == VG_BLEND_SRC || (d->blendMode == VG_BLEND_SRC_OVER &&
+ !image.hasAlphaChannel()));
+}
+
void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
{
QPixmapData *pd = pm.pixmapData();
@@ -3074,9 +3091,18 @@ void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF
drawVGImage(d, r, vgpd->toVGImage(), vgpd->size(), sr);
else
drawVGImage(d, r, vgpd->toVGImage(d->opacity), vgpd->size(), sr);
- } else {
- drawImage(r, *(pd->buffer()), sr, Qt::AutoColor);
+
+ if(!vgpd->failedToAlloc)
+ return;
+
+ // try to reallocate next time if reasonable small pixmap
+ QSize screenSize = QApplication::desktop()->screenGeometry().size();
+ if (pm.size().width() <= screenSize.width()
+ && pm.size().height() <= screenSize.height())
+ vgpd->failedToAlloc = false;
}
+
+ drawImage(r, *(pd->buffer()), sr, Qt::AutoColor);
}
void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
@@ -3093,9 +3119,18 @@ void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
drawVGImage(d, pos, vgpd->toVGImage());
else
drawVGImage(d, pos, vgpd->toVGImage(d->opacity));
- } else {
- drawImage(pos, *(pd->buffer()));
+
+ if (!vgpd->failedToAlloc)
+ return;
+
+ // try to reallocate next time if reasonable small pixmap
+ QSize screenSize = QApplication::desktop()->screenGeometry().size();
+ if (pm.size().width() <= screenSize.width()
+ && pm.size().height() <= screenSize.height())
+ vgpd->failedToAlloc = false;
}
+
+ drawImage(pos, *(pd->buffer()));
}
void QVGPaintEngine::drawImage
@@ -3116,9 +3151,31 @@ void QVGPaintEngine::drawImage
QRectF(QPointF(0, 0), sr.size()));
}
} else {
- // Monochrome images need to use the vgChildImage() path.
- vgImg = toVGImage(image, flags);
- drawVGImage(d, r, vgImg, image.size(), sr);
+ if (canVgWritePixels(image) && (r.size() == sr.size()) && !flags) {
+ // Optimization for straight blits, no blending
+ int x = sr.x();
+ int y = sr.y();
+ int bpp = image.depth() >> 3; // bytes
+ int offset = 0;
+ int bpl = image.bytesPerLine();
+ if (d->imageTransform.m22() < 0) {
+ // inverted
+ offset = ((y + sr.height()) * bpl) - ((image.width() - x) * bpp);
+ bpl = -bpl;
+ } else {
+ offset = (y * bpl) + (x * bpp);
+ }
+ const uchar *bits = image.constBits() + offset;
+
+ QPointF mapped = d->imageTransform.map(r.topLeft());
+ vgWritePixels(bits, bpl, qt_vg_image_to_vg_format(image.format()),
+ mapped.x(), mapped.y() - sr.height(), r.width(), r.height());
+ return;
+ } else {
+ // Monochrome images need to use the vgChildImage() path.
+ vgImg = toVGImage(image, flags);
+ drawVGImage(d, r, vgImg, image.size(), sr);
+ }
}
vgDestroyImage(vgImg);
}
@@ -3127,10 +3184,21 @@ void QVGPaintEngine::drawImage(const QPointF &pos, const QImage &image)
{
Q_D(QVGPaintEngine);
VGImage vgImg;
- if (d->simpleTransform || d->opacity == 1.0f)
+ if (canVgWritePixels(image)) {
+ // Optimization for straight blits, no blending
+ bool inverted = (d->imageTransform.m22() < 0);
+ const uchar *bits = inverted ? image.constBits() + image.byteCount() : image.constBits();
+ int bpl = inverted ? -image.bytesPerLine() : image.bytesPerLine();
+
+ QPointF mapped = d->imageTransform.map(pos);
+ vgWritePixels(bits, bpl, qt_vg_image_to_vg_format(image.format()),
+ mapped.x(), mapped.y() - image.height(), image.width(), image.height());
+ return;
+ } else if (d->simpleTransform || d->opacity == 1.0f) {
vgImg = toVGImage(image);
- else
+ } else {
vgImg = toVGImageWithOpacity(image, d->opacity);
+ }
drawVGImage(d, pos, vgImg);
vgDestroyImage(vgImg);
}
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index 75cf053..dc98137 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -170,6 +170,7 @@ private:
bool isDefaultClipRegion(const QRegion& region);
bool isDefaultClipRect(const QRect& rect);
bool clearRect(const QRectF &rect, const QColor &color);
+ bool canVgWritePixels(const QImage &image) const;
};
QT_END_NAMESPACE
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index e8ec333..509882b 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -65,6 +65,7 @@ QVGPixmapData::QVGPixmapData(PixelType type)
recreate = true;
inImagePool = false;
inLRU = false;
+ failedToAlloc = false;
#if !defined(QT_NO_EGL)
context = 0;
qt_vg_register_pixmap(this);
@@ -155,6 +156,9 @@ void QVGPixmapData::resize(int wid, int ht)
void QVGPixmapData::fromImage
(const QImage &image, Qt::ImageConversionFlags flags)
{
+ if(image.isNull())
+ return;
+
QImage img = image;
createPixmapForImage(img, flags, false);
}
@@ -203,10 +207,19 @@ void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags
else
resize(image.width(), image.height());
- if (inPlace && image.data_ptr()->convertInPlace(sourceFormat(), flags))
+ QImage::Format format = sourceFormat();
+ int d = image.depth();
+ if (d == 1 || d == 16 || d == 24 || (d == 32 && !image.hasAlphaChannel()))
+ format = QImage::Format_RGB32;
+ else if (!(flags & Qt::NoOpaqueDetection) && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
+ format = sourceFormat();
+ else
+ format = QImage::Format_RGB32;
+
+ if (inPlace && image.data_ptr()->convertInPlace(format, flags))
source = image;
else
- source = image.convertToFormat(sourceFormat());
+ source = image.convertToFormat(format);
recreate = true;
}
@@ -278,7 +291,7 @@ QPaintEngine* QVGPixmapData::paintEngine() const
VGImage QVGPixmapData::toVGImage()
{
- if (!isValid())
+ if (!isValid() || failedToAlloc)
return VG_INVALID_HANDLE;
#if !defined(QT_NO_EGL)
@@ -294,11 +307,13 @@ VGImage QVGPixmapData::toVGImage()
if (vgImage == VG_INVALID_HANDLE) {
vgImage = QVGImagePool::instance()->createImageForPixmap
- (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this);
+ (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this);
// Bail out if we run out of GPU memory - try again next time.
- if (vgImage == VG_INVALID_HANDLE)
+ if (vgImage == VG_INVALID_HANDLE) {
+ failedToAlloc = true;
return VG_INVALID_HANDLE;
+ }
inImagePool = true;
} else if (inImagePool) {
@@ -309,7 +324,7 @@ VGImage QVGPixmapData::toVGImage()
vgImageSubData
(vgImage,
source.constBits(), source.bytesPerLine(),
- VG_sARGB_8888_PRE, 0, 0, w, h);
+ qt_vg_image_to_vg_format(source.format()), 0, 0, w, h);
}
recreate = false;
diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h
index 114d545..7ffdc85 100644
--- a/src/openvg/qpixmapdata_vg_p.h
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -143,7 +143,9 @@ private:
QVGPixmapData *nextLRU;
QVGPixmapData *prevLRU;
bool inLRU;
+ bool failedToAlloc;
friend class QVGImagePool;
+ friend class QVGPaintEngine;
#if !defined(QT_NO_EGL)
QVGPixmapData *next;
diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp
index 41b35fc..c608c81 100644
--- a/src/openvg/qvg_symbian.cpp
+++ b/src/openvg/qvg_symbian.cpp
@@ -164,7 +164,6 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
bool deleteSourceBitmap = false;
-
#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
// Rasterize extended bitmaps
diff --git a/src/plugins/s60/feedback/feedback.pro b/src/plugins/s60/feedback/feedback.pro
new file mode 100644
index 0000000..32ddf6f
--- /dev/null
+++ b/src/plugins/s60/feedback/feedback.pro
@@ -0,0 +1,16 @@
+include(../../qpluginbase.pri)
+
+TARGET = qtactilefeedback$${QT_LIBINFIX}
+
+INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+
+contains(S60_VERSION, 5.0)|contains(S60_VERSION, symbian3) {
+ HEADERS += qtactileFeedback.h
+ SOURCES += qtactileFeedback_s60.cpp
+
+ LIBS += -ltouchfeedback
+}
+
+load(data_caging_paths)
+
+TARGET.UID3=0x200315B4
diff --git a/src/plugins/s60/feedback/qtactileFeedback.h b/src/plugins/s60/feedback/qtactileFeedback.h
new file mode 100644
index 0000000..7c4cc29
--- /dev/null
+++ b/src/plugins/s60/feedback/qtactileFeedback.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QEvent>
+#include <QWidget>
+
+#include "private/qs60style_feedbackinterface_p.h"
+
+class QTactileFeedback : public TactileFeedbackInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(TactileFeedbackInterface)
+
+ public:
+ void touchFeedback(QEvent *event, const QWidget *widget);
+ };
diff --git a/src/plugins/s60/feedback/qtactileFeedback_s60.cpp b/src/plugins/s60/feedback/qtactileFeedback_s60.cpp
new file mode 100644
index 0000000..c2f1d34
--- /dev/null
+++ b/src/plugins/s60/feedback/qtactileFeedback_s60.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QObject>
+#include <QSlider>
+#include <QScrollBar>
+
+#include <QtCore/qplugin.h>
+#include "qtactileFeedback.h"
+
+#include <touchfeedback.h>
+
+void QTactileFeedback::touchFeedback(QEvent *event, const QWidget *widget)
+{
+ //Lets share the global instance for touch feedback (you are NOT allowed to try and delete it!).
+ MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+ //If the widget itself is not handling focus, try to use focusProxy widget.
+ const QWidget *w = ((widget->focusPolicy() == Qt::NoFocus) && (widget->focusProxy())) ? widget->focusProxy() : widget;
+
+ //Only give tactile feedback for enabled widgets that take focus.
+ if (feedback && w && w->isEnabled() && w->isWidgetType() && w->isVisible()) {
+ //Scrollbars are 'special' that they don't take focus (nor they have focusProxy), yet we'd like to have tactile feedback for them
+ if (w->focusPolicy() == Qt::NoFocus)
+ if (!qobject_cast<const QScrollBar *>(w))
+ return;
+
+ //Don't give tactile feedback for widgets that are outside topmost dialog.
+ QWidget *dialog = QApplication::activeModalWidget();
+ if (dialog) {
+ QList<const QWidget *> allChildren = dialog->findChildren<const QWidget *>();
+ if (!allChildren.contains(w))
+ return;
+ }
+
+ //Widget specific tactile feedback.
+ if (qobject_cast<const QSlider *>(w) || qobject_cast<const QScrollBar *>(w))
+ feedback->InstantFeedback(ETouchFeedbackSensitive);
+ else
+ feedback->InstantFeedback(ETouchFeedbackBasic);
+ }
+}
+
+Q_EXPORT_PLUGIN2("feedback", QTactileFeedback);
diff --git a/src/plugins/s60/s60.pro b/src/plugins/s60/s60.pro
index c999fff..ffcd170 100644
--- a/src/plugins/s60/s60.pro
+++ b/src/plugins/s60/s60.pro
@@ -6,6 +6,10 @@ symbian {
SUBDIRS += 3_1 3_2
}
+ contains(S60_VERSION, 5.0)|contains(S60_VERSION, symbian3) {
+ SUBDIRS += feedback
+ }
+
# 5.0 is used also for Symbian3 and later
SUBDIRS += 5_0
} \ No newline at end of file
diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def
index 7cc2752..c91b22c 100644
--- a/src/s60installs/bwins/QtGuiu.def
+++ b/src/s60installs/bwins/QtGuiu.def
@@ -12890,10 +12890,12 @@ EXPORTS
?lastRightBearing@QFontEngine@@IAE?AUQFixed@@ABUQGlyphLayout@@_N@Z @ 12889 NONAME ; struct QFixed QFontEngine::lastRightBearing(struct QGlyphLayout const &, bool)
?childrenBoundingRectHelper@QGraphicsItemPrivate@@QAEXPAVQTransform@@PAVQRectF@@PAVQGraphicsItem@@@Z @ 12890 NONAME ; void QGraphicsItemPrivate::childrenBoundingRectHelper(class QTransform *, class QRectF *, class QGraphicsItem *)
?setTimeout@QTapAndHoldGesture@@SAXH@Z @ 12891 NONAME ; void QTapAndHoldGesture::setTimeout(int)
- ?qmljsDebugArguments@QApplicationPrivate@@2VQString@@A @ 12892 NONAME ; class QString QApplicationPrivate::qmljsDebugArguments
+ ?qmljsDebugArguments@QApplicationPrivate@@2VQString@@A @ 12892 NONAME ABSENT ; class QString QApplicationPrivate::qmljsDebugArguments
?effectiveBoundingRect@QGraphicsItemPrivate@@QBE?AVQRectF@@PAVQGraphicsItem@@@Z @ 12893 NONAME ; class QRectF QGraphicsItemPrivate::effectiveBoundingRect(class QGraphicsItem *) const
?maxTextureHeight@QTextureGlyphCache@@UBEHXZ @ 12894 NONAME ; int QTextureGlyphCache::maxTextureHeight(void) const
?maxTextureWidth@QTextureGlyphCache@@UBEHXZ @ 12895 NONAME ; int QTextureGlyphCache::maxTextureWidth(void) const
- ?convertToPostscriptFontFamilyName@QFontEngine@@SA?AVQByteArray@@ABV2@@Z @ 12896 NONAME ; class QByteArray QFontEngine::convertToPostscriptFontFamilyName(class QByteArray const &)
- ?lastResortFont@QFont@@QBE?AVQString@@XZ @ 12897 NONAME ; class QString QFont::lastResortFont(void) const
+ ?qmljs_debug_arguments@QApplicationPrivate@@2VQString@@A @ 12896 NONAME ; class QString QApplicationPrivate::qmljs_debug_arguments
+ ?qmljsDebugArgumentsString@QApplicationPrivate@@SA?AVQString@@XZ @ 12897 NONAME ; class QString QApplicationPrivate::qmljsDebugArgumentsString(void)
+ ?convertToPostscriptFontFamilyName@QFontEngine@@SA?AVQByteArray@@ABV2@@Z @ 12898 NONAME ; class QByteArray QFontEngine::convertToPostscriptFontFamilyName(class QByteArray const &)
+ ?lastResortFont@QFont@@QBE?AVQString@@XZ @ 12899 NONAME ; class QString QFont::lastResortFont(void) const
diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def
index 4e867a3..f772bcc 100644
--- a/src/s60installs/eabi/QtGuiu.def
+++ b/src/s60installs/eabi/QtGuiu.def
@@ -12094,9 +12094,11 @@ EXPORTS
_ZN18QTapAndHoldGesture7timeoutEv @ 12093 NONAME
_ZN20QGraphicsItemPrivate26childrenBoundingRectHelperEP10QTransformP6QRectFb @ 12094 NONAME ABSENT
_ZN20QGraphicsItemPrivate14children_clearEP24QDeclarativeListPropertyI15QGraphicsObjectE @ 12095 NONAME
- _ZN19QApplicationPrivate19qmljsDebugArgumentsE @ 12096 NONAME DATA 4
+ _ZN19QApplicationPrivate19qmljsDebugArgumentsE @ 12096 NONAME DATA 4 ABSENT
_ZN20QGraphicsItemPrivate26childrenBoundingRectHelperEP10QTransformP6QRectFP13QGraphicsItem @ 12097 NONAME
_ZNK20QGraphicsItemPrivate21effectiveBoundingRectEP13QGraphicsItem @ 12098 NONAME
- _ZNK5QFont14lastResortFontEv @ 12099 NONAME
- _ZN11QFontEngine33convertToPostscriptFontFamilyNameERK10QByteArray @ 12100 NONAME
+ _ZN19QApplicationPrivate21qmljs_debug_argumentsE @ 12099 NONAME DATA 4
+ _ZN19QApplicationPrivate25qmljsDebugArgumentsStringEv @ 12100 NONAME
+ _ZNK5QFont14lastResortFontEv @ 12101 NONAME
+ _ZN11QFontEngine33convertToPostscriptFontFamilyNameERK10QByteArray @ 12102 NONAME
diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby
index 4afbf05..2b3be0a 100644
--- a/src/s60installs/qt.iby
+++ b/src/s60installs/qt.iby
@@ -60,6 +60,8 @@ file=ABI_DIR\BUILD_DIR\qsymbianbearer.dll SHARED_LIB_DIR\qsymbianbearer.dll
// so don't bother including those plugins
file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll
+file=ABI_DIR\BUILD_DIR\qtactilefeedback.dll SHARED_LIB_DIR\qtactilefeedback.dll
+
S60_APP_RESOURCE(s60main)
// imageformats stubs
@@ -105,6 +107,9 @@ data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplug
// bearer stub
data=\epoc32\data\z\resource\qt\plugins\bearer\qsymbianbearer.qtplugin resource\qt\plugins\bearer\qsymbianbearer.qtplugin
+// feedback
+data=\epoc32\data\z\resource\qt\plugins\feedback\qtactilefeedback.qtplugin resource\qt\plugins\feedback\qtactilefeedback.qtplugin
+
// Stub sis file
data=ZSYSTEM\install\qt_stub.sis System\Install\qt_stub.sis
data=ZSYSTEM\install\qtwebkit_stub.sis System\Install\qtwebkit_stub.sis
diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro
index 9559da6..65b8781 100644
--- a/src/s60installs/s60installs.pro
+++ b/src/s60installs/s60installs.pro
@@ -87,6 +87,12 @@ symbian: {
DEPLOYMENT += bearer_plugin
}
+ contains(S60_VERSION, 5.0)|contains(S60_VERSION, symbian3) {
+ feedback_plugin.sources = $$QT_BUILD_TREE/plugins/s60/feedback/qtactilefeedback$${QT_LIBINFIX}.dll
+ feedback_plugin.path = c:$$QT_PLUGINS_BASE_DIR/feedback
+ DEPLOYMENT += feedback_plugin
+ }
+
qtlibraries.pkg_postrules += qts60plugindeployment
qtlibraries.path = c:/sys/bin