diff options
author | Janne Anttila <janne.anttila@digia.com> | 2009-11-02 08:23:12 (GMT) |
---|---|---|
committer | Janne Anttila <janne.anttila@digia.com> | 2009-11-02 09:49:08 (GMT) |
commit | fc6822cb2c1a09b018189168965a8ade23cf1074 (patch) | |
tree | 27f6d2bd6008a5ba922b4587098678494b04a384 /src | |
parent | 8910b449dafcb3475ab8c6f90213cd632412da68 (diff) | |
download | Qt-fc6822cb2c1a09b018189168965a8ade23cf1074.zip Qt-fc6822cb2c1a09b018189168965a8ade23cf1074.tar.gz Qt-fc6822cb2c1a09b018189168965a8ade23cf1074.tar.bz2 |
Fix for static QSound::play in Symbian and code style fixes.
Static QSound::play(const QString& filename) API did work for Symbian,
since local stack variable was deleted before asynchronous play
completed. This happened with the following seqeunce:
- void QAuServer::play() is called and creates a QSound on the stack
- QAuBucketS60::play() is called
- m_prepared is false, so the actual play will happen a bit later
- The QSound created on the stack is deleted
-> Silence
This scenario is now fixed by making copy of QSound object to internal
list, and temp object is being deleted when play is completed either
successfully or unsuccessfully.
Added also manual test case for static play.
Task-number: QTBUG-5217
Reviewed-by: Miikka Heikkinen
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qsound_s60.cpp | 94 |
1 files changed, 56 insertions, 38 deletions
diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp index 352580e..e4b7cec 100644 --- a/src/gui/kernel/qsound_s60.cpp +++ b/src/gui/kernel/qsound_s60.cpp @@ -60,13 +60,13 @@ class QAuServerS60; class QAuBucketS60 : public QAuBucket, public MMdaAudioPlayerCallback { public: - QAuBucketS60( QAuServerS60 *server, QSound *sound); + QAuBucketS60(QAuServerS60 *server, QSound *sound); ~QAuBucketS60(); void play(); void stop(); - inline QSound* sound() const { return m_sound; } + inline QSound *sound() const { return m_sound; } public: // from MMdaAudioPlayerCallback void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration); @@ -77,88 +77,106 @@ private: QAuServerS60 *m_server; bool m_prepared; bool m_playCalled; - CMdaAudioPlayerUtility* m_playUtility; + CMdaAudioPlayerUtility *m_playUtility; }; class QAuServerS60 : public QAuServer { public: - QAuServerS60( QObject* parent ); + QAuServerS60(QObject *parent); - void init( QSound* s ) + void init(QSound *s) { - QAuBucketS60 *bucket = new QAuBucketS60( this, s ); - setBucket( s, bucket ); + QAuBucketS60 *bucket = new QAuBucketS60(this, s); + setBucket(s, bucket); } - void play( QSound* s ) + void play(QSound *s) { - bucket( s )->play(); + bucket(s)->play(); } - void stop( QSound* s ) + void stop(QSound *s) { - bucket( s )->stop(); + bucket(s)->stop(); } bool okay() { return true; } + void play(const QString& filename); + protected: - void playCompleted(QAuBucketS60* bucket, int error) - { - QSound *sound = bucket->sound(); - if(!error) { - // We need to handle repeats by ourselves, since with Symbian API we don't - // know how many loops have been played when user asks it - if( decLoop( sound ) ) { - play( sound ); - } - } else { - // We don't have a way to inform about errors -> just decrement loops - // in order that QSound::isFinished will return true; - while(decLoop(sound)) {} - } - } + void playCompleted(QAuBucketS60 *bucket, int error); protected: - QAuBucketS60* bucket( QSound *s ) + QAuBucketS60 *bucket(QSound *s) { - return (QAuBucketS60*)QAuServer::bucket( s ); + return (QAuBucketS60 *)QAuServer::bucket( s ); } friend class QAuBucketS60; + // static QSound::play(filename) cannot be stopped, meaning that playCompleted + // will get always called and QSound gets removed form this list. + QList<QSound *> staticPlayingSounds; }; -QAuServerS60::QAuServerS60(QObject* parent) : +QAuServerS60::QAuServerS60(QObject *parent) : QAuServer(parent) { setObjectName(QLatin1String("QAuServerS60")); } +void QAuServerS60::play(const QString& filename) +{ + QSound *s = new QSound(filename); + staticPlayingSounds.append(s); + play(s); +} + +void QAuServerS60::playCompleted(QAuBucketS60 *bucket, int error) +{ + QSound *sound = bucket->sound(); + if (!error) { + // We need to handle repeats by ourselves, since with Symbian API we don't + // know how many loops have been played when user asks it + if (decLoop(sound)) { + play(sound); + } else { + if (staticPlayingSounds.removeAll(sound)) + delete sound; + } + } else { + // We don't have a way to inform about errors -> just decrement loops + // in order that QSound::isFinished will return true; + while (decLoop(sound)) {} + if (staticPlayingSounds.removeAll(sound)) + delete sound; + } +} -QAuServer* qt_new_audio_server() +QAuServer *qt_new_audio_server() { return new QAuServerS60(qApp); } -QAuBucketS60::QAuBucketS60( QAuServerS60 *server, QSound *sound ) - : m_sound( sound ), m_server( server ), m_prepared(false), m_playCalled(false) +QAuBucketS60::QAuBucketS60(QAuServerS60 *server, QSound *sound) + : m_sound(sound), m_server(server), m_prepared(false), m_playCalled(false) { - QString filepath = QFileInfo( m_sound->fileName() ).absoluteFilePath(); + QString filepath = QFileInfo(m_sound->fileName()).absoluteFilePath(); filepath = QDir::toNativeSeparators(filepath); TPtrC filepathPtr(qt_QString2TPtrC(filepath)); TRAPD(err, m_playUtility = CMdaAudioPlayerUtility::NewL(*this); m_playUtility->OpenFileL(filepathPtr)); - if(err){ + if (err) { m_server->playCompleted(this, err); } } void QAuBucketS60::play() { - if(m_prepared) { + if (m_prepared) { // OpenFileL call is completed we can start playing immediately m_playUtility->Play(); } else { @@ -180,11 +198,11 @@ void QAuBucketS60::MapcPlayComplete(TInt aError) void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/) { - if(aError) { + if (aError) { m_server->playCompleted(this, aError); } else { m_prepared = true; - if(m_playCalled){ + if (m_playCalled){ play(); } } @@ -192,7 +210,7 @@ void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds QAuBucketS60::~QAuBucketS60() { - if(m_playUtility){ + if (m_playUtility){ m_playUtility->Stop(); m_playUtility->Close(); } |