Author: gert
Date: 2007-11-07 10:56:33 -0500 (Wed, 07 Nov 2007)
New Revision: 89112
Added:
trunk/mcs/class/System/System.Media/Win32SoundPlayer.cs
trunk/mcs/class/System/Test/System.Media/ChangeLog
Modified:
trunk/mcs/class/System/ChangeLog
trunk/mcs/class/System/System.Media/AudioData.cs
trunk/mcs/class/System/System.Media/AudioDevice.cs
trunk/mcs/class/System/System.Media/ChangeLog
trunk/mcs/class/System/System.Media/SoundPlayer.cs
trunk/mcs/class/System/System.Media/SystemSound.cs
trunk/mcs/class/System/System.Media/SystemSounds.cs
trunk/mcs/class/System/System.dll.sources
trunk/mcs/class/System/Test/System.Media/SoundPlayerTest.cs
Log:
* SoundPlayer.cs: Addded support for playing WAV files on Windows.
Fixed ctor (Stream) to allow null argument. In LoadFromUri, first
reset mstream to support resetting Stream to null. Support playing
default sound. Allow Stream to be set to null. Reset AudioData and
WaveData when new stream is loaded.
* Win32SoundPlayer.cs: Wrapper for PlaySound Win32 API.
* System.dll.sources: Added Win32SoundPlayer.cs.
* SoundPlayerTest.cs: Added trivial ctor tests. Added test for
Stream property.
Modified: trunk/mcs/class/System/ChangeLog
===================================================================
--- trunk/mcs/class/System/ChangeLog 2007-11-07 15:33:47 UTC (rev 89111)
+++ trunk/mcs/class/System/ChangeLog 2007-11-07 15:56:33 UTC (rev 89112)
@@ -1,3 +1,7 @@
+2007-11-07 Gert Driesen <[EMAIL PROTECTED]>
+
+ * System.dll.sources: Added Win32SoundPlayer.cs.
+
2007-11-03 Gert Driesen <[EMAIL PROTECTED]>
* System_test.dll.sources: Added InvalidEnumArgumentExceptionTest.cs.
Property changes on: trunk/mcs/class/System/System.Media/AudioData.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/mcs/class/System/System.Media/AudioDevice.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/mcs/class/System/System.Media/ChangeLog
===================================================================
--- trunk/mcs/class/System/System.Media/ChangeLog 2007-11-07 15:33:47 UTC
(rev 89111)
+++ trunk/mcs/class/System/System.Media/ChangeLog 2007-11-07 15:56:33 UTC
(rev 89112)
@@ -1,3 +1,12 @@
+2007-11-07 Gert Driesen <[EMAIL PROTECTED]>
+
+ * SoundPlayer.cs: Addded support for playing WAV files on Windows.
+ Fixed ctor (Stream) to allow null argument. In LoadFromUri, first
+ reset mstream to support resetting Stream to null. Support playing
+ default sound. Allow Stream to be set to null. Reset AudioData and
+ WaveData when new stream is loaded.
+ * Win32SoundPlayer.cs: Wrapper for PlaySound Win32 API.
+
2007-11-06 Sebastien Pouliot <[EMAIL PROTECTED]>
* AudioData.cs: Reset stream to position 0 before playing (required
Modified: trunk/mcs/class/System/System.Media/SoundPlayer.cs
===================================================================
--- trunk/mcs/class/System/System.Media/SoundPlayer.cs 2007-11-07 15:33:47 UTC
(rev 89111)
+++ trunk/mcs/class/System/System.Media/SoundPlayer.cs 2007-11-07 15:56:33 UTC
(rev 89112)
@@ -43,12 +43,26 @@
Stream audiostream;
object tag = String.Empty;
MemoryStream mstream;
+ bool load_completed;
+ int load_timeout = 10000;
+
+ #region Only used for Alsa implementation
AudioDevice adev;
AudioData adata;
- bool load_completed;
bool stopped;
- int load_timeout = 10000;
+ #endregion
+ #region Only used for Win32 implementation
+ Win32SoundPlayer win32_player;
+ #endregion
+
+ static readonly bool use_win32_player;
+
+ static SoundPlayer ()
+ {
+ use_win32_player = (Environment.OSVersion.Platform !=
PlatformID.Unix);
+ }
+
public SoundPlayer ()
{
sound_location = String.Empty;
@@ -56,8 +70,6 @@
public SoundPlayer (Stream stream): this ()
{
- if (stream == null)
- throw new ArgumentNullException ("stream");
audiostream = stream;
}
@@ -84,30 +96,24 @@
mstream.Position = 0;
}
- [MonoLimitation("Doesn't play a default sound if nothing is
specified")]
- bool LoadFromUri(string location)
+ void LoadFromUri (string location)
{
+ mstream = null;
Stream data = null;
- if(string.IsNullOrEmpty(location)) {
- // FIXME: Play a default sound
- return false;
- }
+ if (string.IsNullOrEmpty (location))
+ return;
if(File.Exists(location))
data = new FileStream(location, FileMode.Open,
FileAccess.Read, FileShare.Read);
- else
- {
+ else {
System.Net.WebRequest request =
System.Net.WebRequest.Create(location);
data =
request.GetResponse().GetResponseStream();
}
- using(data)
- LoadFromStream(data);
-
- return true;
+ using (data)
+ LoadFromStream (data);
}
-
public void Load ()
{
// can this be reused to load the same file again
without re-setting the location?
@@ -116,13 +122,25 @@
if (audiostream != null) {
LoadFromStream (audiostream);
} else {
- LoadFromUri(sound_location);
+ LoadFromUri (sound_location);
}
+
+ // force recreate for new stream
+ adata = null;
+ adev = null;
+
load_completed = true;
AsyncCompletedEventArgs e = new AsyncCompletedEventArgs
(null, false, this);
OnLoadCompleted (e);
if (LoadCompleted != null)
LoadCompleted (this, e);
+
+ if (use_win32_player) {
+ if (win32_player == null)
+ win32_player = new Win32SoundPlayer
(mstream);
+ else
+ win32_player.Stream = mstream;
+ }
}
void AsyncFinished (IAsyncResult ar)
@@ -153,55 +171,97 @@
void Start ()
{
- stopped = false;
- if (adata != null)
- adata.IsStopped = false;
+ if (!use_win32_player) {
+ stopped = false;
+ if (adata != null)
+ adata.IsStopped = false;
+ }
if (!load_completed)
Load ();
}
public void Play ()
{
- ThreadStart async = new ThreadStart (PlaySync);
- async.BeginInvoke (AsyncFinished, async);
+ if (!use_win32_player) {
+ ThreadStart async = new ThreadStart (PlaySync);
+ async.BeginInvoke (AsyncFinished, async);
+ } else {
+ Start ();
+
+ if (mstream == null) {
+ SystemSounds.Beep.Play ();
+ return;
+ }
+
+ win32_player.Play ();
+ }
}
private void PlayLoop ()
{
Start ();
- while (!stopped) {
+
+ if (mstream == null) {
+ SystemSounds.Beep.Play ();
+ return;
+ }
+
+ while (!stopped)
PlaySync ();
- }
}
public void PlayLooping ()
{
- ThreadStart async = new ThreadStart (PlayLoop);
- async.BeginInvoke (AsyncFinished, async);
+ if (!use_win32_player) {
+ ThreadStart async = new ThreadStart (PlayLoop);
+ async.BeginInvoke (AsyncFinished, async);
+ } else {
+ Start ();
+
+ if (mstream == null) {
+ SystemSounds.Beep.Play ();
+ return;
+ }
+
+ win32_player.PlayLooping ();
+ }
}
- [MonoLimitation("Doesn't play a default sound if nothing is
specified")]
public void PlaySync ()
{
Start ();
- try {
- if (adata == null)
- adata = new WavData (mstream);
- if (adev == null)
- adev = AudioDevice.CreateDevice (null);
- if (adata != null) {
- adata.Setup (adev);
- adata.Play (adev);
+
+ if (mstream == null) {
+ SystemSounds.Beep.Play ();
+ return;
+ }
+
+ if (!use_win32_player) {
+ try {
+ if (adata == null)
+ adata = new WavData (mstream);
+ if (adev == null)
+ adev = AudioDevice.CreateDevice
(null);
+ if (adata != null) {
+ adata.Setup (adev);
+ adata.Play (adev);
+ }
+ } catch {
}
- } catch {
+ } else {
+ win32_player.PlaySync ();
}
}
public void Stop ()
{
- stopped = true;
- if (adata != null)
- adata.IsStopped = true;
+ if (!use_win32_player) {
+ stopped = true;
+ if (adata != null)
+ adata.IsStopped = true;
+ } else {
+ win32_player.Stop ();
+ }
}
void ISerializable.GetObjectData (SerializationInfo info,
StreamingContext context)
@@ -245,13 +305,13 @@
return audiostream;
}
set {
- if (value == null)
- throw new ArgumentNullException
("value");
- audiostream = value;
- load_completed = false;
- OnStreamChanged (EventArgs.Empty);
- if (StreamChanged != null)
- StreamChanged (this, EventArgs.Empty);
+ if (audiostream != value) {
+ audiostream = value;
+ load_completed = false;
+ OnStreamChanged (EventArgs.Empty);
+ if (StreamChanged != null)
+ StreamChanged (this,
EventArgs.Empty);
+ }
}
}
@@ -265,13 +325,9 @@
}
public event AsyncCompletedEventHandler LoadCompleted;
-
public event EventHandler SoundLocationChanged;
-
public event EventHandler StreamChanged;
-
}
}
#endif
-
Property changes on: trunk/mcs/class/System/System.Media/SoundPlayer.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/mcs/class/System/System.Media/SystemSound.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/mcs/class/System/System.Media/SystemSounds.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/mcs/class/System/System.Media/Win32SoundPlayer.cs
===================================================================
--- trunk/mcs/class/System/System.Media/Win32SoundPlayer.cs 2007-11-07
15:33:47 UTC (rev 89111)
+++ trunk/mcs/class/System/System.Media/Win32SoundPlayer.cs 2007-11-07
15:56:33 UTC (rev 89112)
@@ -0,0 +1,123 @@
+//
+// Mono.Audio.Win32SoundPlayer
+//
+// Authors:
+// Gert Driesen ([EMAIL PROTECTED])
+//
+// Copyright (C) 2007 Gert Driesen
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Mono.Audio
+{
+ internal class Win32SoundPlayer : IDisposable
+ {
+ public Win32SoundPlayer (Stream s)
+ {
+ if (s != null) {
+ _buffer = new byte [s.Length];
+ s.Read (_buffer, 0, _buffer.Length);
+ } else {
+ _buffer = new byte [0];
+ }
+ }
+
+ [DllImport ("winmm.dll", SetLastError = true)]
+ static extern bool PlaySound (
+ byte [] ptrToSound,
+ UIntPtr hmod,
+ SoundFlags flags);
+
+ public Stream Stream {
+ set {
+ Stop ();
+ if (value != null) {
+ _buffer = new byte [value.Length];
+ value.Read (_buffer, 0, _buffer.Length);
+ } else {
+ _buffer = new byte [0];
+ }
+ }
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ ~Win32SoundPlayer ()
+ {
+ Dispose (false);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (!_disposed) {
+ Stop ();
+ }
+ }
+
+ public void Play ()
+ {
+ PlaySound (_buffer, UIntPtr.Zero, SoundFlags.SND_ASYNC |
+ SoundFlags.SND_MEMORY);
+ }
+
+ public void PlayLooping ()
+ {
+ PlaySound (_buffer, UIntPtr.Zero, SoundFlags.SND_MEMORY
|
+ SoundFlags.SND_LOOP | SoundFlags.SND_ASYNC);
+ }
+
+ public void PlaySync ()
+ {
+ PlaySound (_buffer, UIntPtr.Zero, SoundFlags.SND_SYNC |
+ SoundFlags.SND_MEMORY |
SoundFlags.SND_NODEFAULT);
+ }
+
+ public void Stop ()
+ {
+ PlaySound ((byte []) null, UIntPtr.Zero,
SoundFlags.SND_SYNC);
+ }
+
+ enum SoundFlags : uint
+ {
+ SND_SYNC = 0x0000, // play synchronously
+ SND_ASYNC = 0x0001, // play asynchronously
+ SND_NODEFAULT = 0x0002, // do not play default
sound if sound not found
+ SND_MEMORY = 0x0004, // pszSound is loaded
in memory
+ SND_LOOP = 0x0008, // play repeatedly
until next PlaySound
+ SND_FILENAME = 0x00020000, // pszSound is a file
name
+ }
+
+ private byte [] _buffer;
+ private bool _disposed;
+ }
+}
+
+#endif
Property changes on: trunk/mcs/class/System/System.Media/Win32SoundPlayer.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/mcs/class/System/System.dll.sources
===================================================================
--- trunk/mcs/class/System/System.dll.sources 2007-11-07 15:33:47 UTC (rev
89111)
+++ trunk/mcs/class/System/System.dll.sources 2007-11-07 15:56:33 UTC (rev
89112)
@@ -600,6 +600,7 @@
System.Media/SoundPlayer.cs
System.Media/SystemSound.cs
System.Media/SystemSounds.cs
+System.Media/Win32SoundPlayer.cs
System.Net/AuthenticationManager.cs
System.Net/AuthenticationSchemes.cs
System.Net/AuthenticationSchemeSelector.cs
Added: trunk/mcs/class/System/Test/System.Media/ChangeLog
===================================================================
--- trunk/mcs/class/System/Test/System.Media/ChangeLog 2007-11-07 15:33:47 UTC
(rev 89111)
+++ trunk/mcs/class/System/Test/System.Media/ChangeLog 2007-11-07 15:56:33 UTC
(rev 89112)
@@ -0,0 +1,4 @@
+2007-11-07 Gert Driesen <[EMAIL PROTECTED]>
+
+ * SoundPlayerTest.cs: Added trivial ctor tests. Added test for
+ Stream property.
Property changes on: trunk/mcs/class/System/Test/System.Media/ChangeLog
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/mcs/class/System/Test/System.Media/SoundPlayerTest.cs
===================================================================
--- trunk/mcs/class/System/Test/System.Media/SoundPlayerTest.cs 2007-11-07
15:33:47 UTC (rev 89111)
+++ trunk/mcs/class/System/Test/System.Media/SoundPlayerTest.cs 2007-11-07
15:56:33 UTC (rev 89112)
@@ -1,18 +1,107 @@
//
// SoundPlayerTest.cs - NUnit Test Cases for System.Media.SoundPlayer
-//
+//
+// Authors:
+// Gert Driesen ([EMAIL PROTECTED])
+//
+// (C) 2007 Gert Driesen
+//
+#if NET_2_0
+
using System;
-using System.IO;
-using System.Reflection;
-using System.Text;
+using System.IO;
+using System.Media;
+
using NUnit.Framework;
namespace MonoTests.System.Media
{
[TestFixture]
public class SoundPlayerTest
- {
- // This is just a stub class
+ {
+ private int stream_changed;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ stream_changed = 0;
+ }
+
+ [Test] // ctor ()
+ public void Constructor0 ()
+ {
+ SoundPlayer player = new SoundPlayer ();
+ Assert.IsNull (player.Container, "#1");
+ Assert.IsFalse (player.IsLoadCompleted, "#2");
+ Assert.AreEqual (10000, player.LoadTimeout, "#3");
+ Assert.IsNull (player.Site, "#4");
+ Assert.IsNotNull (player.SoundLocation, "#5");
+ Assert.AreEqual (string.Empty, player.SoundLocation,
"#6");
+ Assert.IsNull (player.Stream, "#7");
+ Assert.IsNull (player.Tag, "#8");
+ }
+
+ [Test] // ctor (Stream)
+ public void Constructor1 ()
+ {
+ MemoryStream ms = new MemoryStream ();
+
+ SoundPlayer player = new SoundPlayer (ms);
+ Assert.IsFalse (player.IsLoadCompleted, "#A1");
+ Assert.IsNotNull (player.SoundLocation, "#A2");
+ Assert.AreEqual (string.Empty, player.SoundLocation,
"#A3");
+ Assert.AreSame (ms, player.Stream, "#A4");
+
+ player = new SoundPlayer ((Stream) null);
+ Assert.IsFalse (player.IsLoadCompleted, "#B1");
+ Assert.IsNotNull (player.SoundLocation, "#B2");
+ Assert.AreEqual (string.Empty, player.SoundLocation,
"#B3");
+ Assert.IsNull (player.Stream, "#B4");
+ }
+
+ [Test] // ctor (string)
+ public void Constructor2 ()
+ {
+ string location = "whatever";
+
+ SoundPlayer player = new SoundPlayer (location);
+ Assert.IsFalse (player.IsLoadCompleted, "#1");
+ Assert.AreSame (location, player.SoundLocation, "#2");
+ Assert.AreEqual ("whatever", player.SoundLocation,
"#3");
+ Assert.IsNull (player.Stream, "#4");
+ }
+
+ [Test]
+ public void Stream ()
+ {
+ MemoryStream ms = new MemoryStream ();
+
+ SoundPlayer player = new SoundPlayer ();
+ player.StreamChanged += new EventHandler
(StreamChangedCounter);
+ player.Stream = ms;
+ Assert.AreSame (ms, player.Stream, "#A1");
+ Assert.IsFalse (player.IsLoadCompleted, "#A2");
+ Assert.AreEqual (1, stream_changed, "#A3");
+ player.Stream = ms;
+ Assert.AreSame (ms, player.Stream, "#B1");
+ Assert.IsFalse (player.IsLoadCompleted, "#B2");
+ Assert.AreEqual (1, stream_changed, "#B3");
+ player.Stream = null;
+ Assert.IsNull (player.Stream, "#C1");
+ Assert.IsFalse (player.IsLoadCompleted, "#C2");
+ Assert.AreEqual (2, stream_changed, "#C3");
+ player.Stream = null;
+ Assert.IsNull (player.Stream, "#D1");
+ Assert.IsFalse (player.IsLoadCompleted, "#D2");
+ Assert.AreEqual (2, stream_changed, "#D3");
+ }
+
+ void StreamChangedCounter (object sender, EventArgs e)
+ {
+ stream_changed++;
+ }
}
}
+
+#endif
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches