[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdepim/kalarm [POSSIBLY UNSAFE]
From:       David Jarvie <software () astrojar ! org ! uk>
Date:       2009-06-14 17:22:55
Message-ID: 1245000175.426584.13645.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 981995 by djarvie:

Bug 194745: fix crash crash when more than one alarm with audio is displayed
simultaneously, e.g. when alarms are redisplayed at startup.


 M  +5 -2      Changelog  
 M  +1 -1      kalarm.h  
 M  +51 -19    messagewin.cpp   [POSSIBLY UNSAFE: system]
 M  +6 -2      messagewin.h  


--- trunk/KDE/kdepim/kalarm/Changelog #981994:981995
@@ -1,8 +1,11 @@
 KAlarm Change Log
 
+=== Version 2.2.3 --- 14 June 2009 ===
+- Fix crash when more than one alarm with audio is displayed simultaneously.
+
 === Version 2.2.2 --- 10 June 2009 ===
-Fix email alarms sending multiple mails, when sent by KMail.
-Fix crash when closing remote calendars.
+- Fix email alarms sending multiple mails, when sent by KMail.
+- Fix crash when closing remote calendars.
 
 === Version 2.2.1 --- 25 May 2009 ===
 - Include new handbook translation: Ukrainian.
--- trunk/KDE/kdepim/kalarm/kalarm.h #981994:981995
@@ -23,7 +23,7 @@
 
 #undef QT3_SUPPORT
 
-#define KALARM_VERSION "2.2.2"
+#define KALARM_VERSION "2.2.3"
 #define KALARM_NAME "KAlarm"
 #define KALARM_DBUS_SERVICE  "org.kde.kalarm"  // D-Bus service name of KAlarm \
application  
--- trunk/KDE/kdepim/kalarm/messagewin.cpp #981994:981995
@@ -143,6 +143,11 @@
 
 QList<MessageWin*> MessageWin::mWindowList;
 QMap<QString, unsigned> MessageWin::mErrorMessages;
+// There can only be one audio thread at a time: trying to play multiple
+// sound files simultaneously would result in a cacophony, and besides
+// that, Phonon currently crashes...
+QPointer<AudioThread> MessageWin::mAudioThread;
+MessageWin*           MessageWin::mAudioOwner = 0;
 
 
 /******************************************************************************
@@ -177,7 +182,6 @@
 	  mConfirmAck(event->confirmAck()),
 	  mNoDefer(true),
 	  mInvalid(false),
-	  mAudioThread(0),
 	  mEvent(*event),
 	  mResource(AlarmCalendar::resources()->resourceForEvent(mEventID)),
 	  mEditButton(0),
@@ -265,7 +269,6 @@
 	  mShowEdit(false),
 	  mNoDefer(true),
 	  mInvalid(false),
-	  mAudioThread(0),
 	  mEvent(*event),
 	  mResource(0),
 	  mEditButton(0),
@@ -298,7 +301,6 @@
 */
 MessageWin::MessageWin()
 	: MainWindowBase(0, WFLAGS),
-	  mAudioThread(0),
 	  mEditButton(0),
 	  mDeferButton(0),
 	  mSilenceButton(0),
@@ -327,7 +329,7 @@
 MessageWin::~MessageWin()
 {
 	kDebug() << mEventID;
-	if (mAudioThread)
+	if (mAudioOwner == this  &&  mAudioThread)
 		mAudioThread->quit();
 	mErrorMessages.remove(mEventID);
 	mWindowList.removeAll(this);
@@ -1162,15 +1164,7 @@
 	{
 		if (!mVolume  &&  mFadeVolume <= 0)
 			return;    // ensure zero volume doesn't play anything
-		// An audio file is specified. Because initialising the sound system
-		// and loading the file may take some time, call it in a separate
-		// thread to allow the window to display first.
-		mAudioThread = new AudioThread(this, mAudioFile, mVolume, mFadeVolume, \
                mFadeSeconds, mAudioRepeat);
-		connect(mAudioThread, SIGNAL(readyToPlay()), SLOT(playReady()));
-		connect(mAudioThread, SIGNAL(finished()), SLOT(playFinished()));
-		if (mSilenceButton)
-			connect(mSilenceButton, SIGNAL(clicked()), mAudioThread, SLOT(quit()));
-		mAudioThread->start();
+		startAudio();    // play the audio file
 	}
 	else if (mSpeak)
 	{
@@ -1181,10 +1175,9 @@
 }
 
 /******************************************************************************
-*  Speak the message.
-*  Called asynchronously to avoid delaying the display of the message.
+* Speak the message.
+* Called asynchronously to avoid delaying the display of the message.
 */
-
 void MessageWin::slotSpeak()
 {
 	QString error;
@@ -1210,6 +1203,42 @@
 }
 
 /******************************************************************************
+* Called when another window's audio thread has been destructed.
+* Start playing this window's audio file. Because initialising the sound system
+* and loading the file may take some time, it is called in a separate thread to
+* allow the window to display first.
+*/
+void MessageWin::startAudio()
+{
+	if (mAudioThread)
+	{
+		// An audio file is already playing for another message
+		// window, so wait until it has finished.
+		connect(mAudioThread, SIGNAL(destroyed(QObject*)), SLOT(audioTerminating()));
+	}
+	else
+	{
+		kDebug() << QThread::currentThread();
+		mAudioThread = new AudioThread(this, mAudioFile, mVolume, mFadeVolume, \
mFadeSeconds, mAudioRepeat); +		mAudioOwner = this;
+		connect(mAudioThread, SIGNAL(readyToPlay()), SLOT(playReady()));
+		connect(mAudioThread, SIGNAL(finished()), SLOT(playFinished()));
+		if (mSilenceButton)
+			connect(mSilenceButton, SIGNAL(clicked()), mAudioThread, SLOT(quit()));
+		mAudioThread->start();
+	}
+}
+
+/******************************************************************************
+* Called when another window's audio thread is being destructed.
+* Wait until the destructor has finished.
+*/
+void MessageWin::audioTerminating()
+{
+	QTimer::singleShot(0, this, SLOT(startAudio()));
+}
+
+/******************************************************************************
 * Called when the audio file is ready to start playing.
 */
 void MessageWin::playReady()
@@ -1232,7 +1261,8 @@
 			clearErrorMessage(ErrMsg_AudioFile);
 		}
 	}
-	mAudioThread->quit();
+	delete mAudioThread;
+	mAudioOwner = 0;
 }
 
 /******************************************************************************
@@ -1241,6 +1271,7 @@
 */
 AudioThread::~AudioThread()
 {
+	kDebug();
 	quit();   // stop playing and tidy up
 	wait();   // wait for run() to exit
 }
@@ -1256,6 +1287,7 @@
 		mMutex.unlock();
 		return;
 	}
+	kDebug() << QThread::currentThread() << mFile;
 	QString audioFile = mFile;
 	mFile.replace(QRegExp("^file:/*"), "/");
 	Phonon::MediaSource source(audioFile);
@@ -1278,8 +1310,8 @@
 		fader->fadeIn(mFadeSeconds);
 		mPath.insertEffect(fader);
 	}
-	connect(mAudioObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), \
                SLOT(playStateChanged(Phonon::State)));
-	connect(mAudioObject, SIGNAL(finished()), SLOT(checkAudioPlay()));
+	connect(mAudioObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), \
SLOT(playStateChanged(Phonon::State)), Qt::DirectConnection); +	connect(mAudioObject, \
SIGNAL(finished()), SLOT(checkAudioPlay()), Qt::DirectConnection);  mPlayedOnce = \
false;  mMutex.unlock();
 	emit readyToPlay();
--- trunk/KDE/kdepim/kalarm/messagewin.h #981994:981995
@@ -25,6 +25,7 @@
 
 #include <QList>
 #include <QMap>
+#include <QPointer>
 
 #include "mainwindowbase.h"
 #include "alarmevent.h"
@@ -91,6 +92,8 @@
 		void                slotShowKMailMessage();
 #endif
 		void                slotSpeak();
+		void                audioTerminating();
+		void                startAudio();
 		void                playReady();
 		void                playFinished();
 		void                enableButtons();
@@ -115,6 +118,9 @@
 
 		static QList<MessageWin*> mWindowList;  // list of existing message windows
 		static QMap<QString, unsigned> mErrorMessages;  // error messages currently \
displayed, by event ID +		// Sound file playing
+		static QPointer<AudioThread> mAudioThread;     // thread to play audio file
+		static MessageWin*           mAudioOwner;      // window which owns mAudioThread
 		// Properties needed by readProperties()
 		QString             mMessage;
 		QFont               mFont;
@@ -139,8 +145,6 @@
 		bool                mShowEdit;        // display the Edit button
 		bool                mNoDefer;         // don't display a Defer option
 		bool                mInvalid;         // restored window is invalid
-		// Sound file playing
-		AudioThread*        mAudioThread;     // thread to play audio file
 		// Miscellaneous
 		KAEvent             mEvent;           // the whole event, for updating the \
calendar file  AlarmResource*      mResource;        // resource which the event \
comes/came from


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic