Index: psi/trunk/src/common.cpp
===================================================================
--- psi/trunk/src/common.cpp	(revision 53)
+++ psi/trunk/src/common.cpp	(revision 54)
@@ -45,4 +45,9 @@
 #include<qlibrary.h>
 #include<qstylesheet.h>
+
+#include<qthread.h>
+#include<qmutex.h>
+#include<qsemaphore.h>
+#include<qvaluelist.h>
 
 
@@ -1564,10 +1569,97 @@
 }
 
+class BeepThread : public QThread
+{
+public:
+	BeepThread() : sem(1), terminate(false) {}
+	~BeepThread() { while (sem.available() != sem.total()) sem--; }
+	void run() {
+		lock.lock();
+		while (!terminate) {
+			while (!terminate && queue.count()) {
+				Beep beep = queue.front();
+				queue.pop_front();
+				lock.unlock();
+#if defined(Q_WS_WIN)
+				if (beep.freq && beep.dur)
+					Beep(beep.freq, beep.dur);
+				else
+#elif defined(Q_WS_PM)
+				if (beep.freq && beep.dur)
+					DosBeep(beep.freq, beep.dur);
+				else
+#endif				
+					QApplication::beep();
+				lock.lock();
+			}
+			lock.unlock();
+			sem++;
+			lock.lock();
+		}
+		lock.unlock();
+	}
+	void add(ulong freq, ulong dur) {
+		lock.lock();
+		queue.push_back(Beep(freq, dur));
+		lock.unlock();
+		if (!sem.available())
+			sem--;
+	}
+	void stop() {
+		lock.lock();
+		terminate = true;
+		lock.unlock();
+		if (!sem.available())
+			sem--;
+		wait();
+	}
+private:
+	struct Beep {
+		Beep() : freq(0), dur(0) {}
+		Beep(ulong f, ulong d) : freq(f), dur(d) {}
+		const ulong freq;
+		const ulong dur;
+	};
+	QMutex lock;
+	QSemaphore sem;
+	QValueList<Beep> queue;
+	bool terminate;
+};
+
+static BeepThread *beepThread = 0;
+
+static void cleanupBeepThread()
+{
+	if (beepThread) {
+		beepThread->stop();
+		delete beepThread;
+		beepThread = 0;
+	}
+}
 
 void soundPlay(const QString &str)
 {
-	if(str == "!beep") {
-		QApplication::beep();
-		return;
+	if(str.startsWith("!beep")) {
+		QStringList list = QStringList::split(':',str);
+		if (list[0].length() == 5 /* strlen("!beep") */) {
+			ulong freq = 0, dur = 0;
+			if (list.count() == 3) {
+				freq = list[1].toULong();
+				dur = list[2].toULong();
+				if (freq < 0x25 || freq > 0x7FFF ||
+					dur == 0 || dur > 3000 /* 3s is the reasonable maximum */)
+					freq = dur = 0;
+			}
+			if (beepThread == 0) {
+				beepThread = new BeepThread();
+				if (beepThread) {
+					qAddPostRoutine(cleanupBeepThread);
+					beepThread->start();
+				}
+			}
+			if (beepThread)
+				beepThread->add(freq, dur);
+			return;
+		}
 	}
 
Index: psi/trunk/src/options/opt_sound-ui.ui
===================================================================
--- psi/trunk/src/options/opt_sound-ui.ui	(revision 53)
+++ psi/trunk/src/options/opt_sound-ui.ui	(revision 54)
@@ -103,5 +103,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -119,5 +119,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -135,5 +135,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -159,5 +159,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -207,5 +207,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -239,5 +239,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -319,5 +319,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -343,5 +343,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -351,5 +351,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -367,5 +367,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
Index: psi/trunk/src/options/opt_sound_events.ui
===================================================================
--- psi/trunk/src/options/opt_sound_events.ui	(revision 53)
+++ psi/trunk/src/options/opt_sound_events.ui	(revision 54)
@@ -68,5 +68,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -84,5 +84,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -140,5 +140,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -164,5 +164,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -212,5 +212,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -244,5 +244,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -252,5 +252,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
@@ -268,5 +268,5 @@
                     </property>
                     <property name="toolTip" stdset="0">
-                        <string>Enter a filename or !beep for a system beep</string>
+                        <string>Enter a filename or &lt;tt&gt;!beep[:freq:duration]&lt;/tt&gt; for a system beep</string>
                     </property>
                 </widget>
