[System] Removal of the NET_2_0 in the source code
[mono.git] / mcs / class / System / System.Media / SoundPlayer.cs
1 //
2 // System.Media.SoundPlayer
3 //
4 // Authors:
5 //    Paolo Molaro (lupus@ximian.com)
6 //
7 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.IO;
30 using System.Threading;
31 using System.Runtime.Serialization;
32 using System.ComponentModel;
33 using Mono.Audio;
34
35 namespace System.Media {
36
37         [Serializable]
38         [ToolboxItem (false)]
39         public class SoundPlayer: Component, ISerializable {
40
41                 string sound_location;
42                 Stream audiostream;
43                 object tag = String.Empty;
44                 MemoryStream mstream;
45                 bool load_completed;
46                 int load_timeout = 10000;
47
48                 #region Only used for Alsa implementation
49                 AudioDevice adev;
50                 AudioData adata;
51                 bool stopped;
52                 #endregion
53
54                 #region Only used for Win32 implementation
55                 Win32SoundPlayer win32_player;
56                 #endregion
57
58                 static readonly bool use_win32_player;
59
60                 static SoundPlayer ()
61                 {
62                         use_win32_player = (Environment.OSVersion.Platform != PlatformID.Unix);
63                 }
64
65                 public SoundPlayer ()
66                 {
67                         sound_location = String.Empty;
68                 }
69
70                 public SoundPlayer (Stream stream): this ()
71                 {
72                         audiostream = stream;
73                 }
74
75                 public SoundPlayer (string soundLocation): this ()
76                 {
77                         if (soundLocation == null)
78                                 throw new ArgumentNullException ("soundLocation");
79                         sound_location = soundLocation;
80                 }
81
82                 protected SoundPlayer (SerializationInfo serializationInfo, StreamingContext context): this ()
83                 {
84                         throw new NotImplementedException ();
85                 }
86
87                 void LoadFromStream (Stream s)
88                 {
89                         mstream = new MemoryStream ();
90                         byte[] buf = new byte [4096];
91                         int count;
92                         while ((count = s.Read (buf, 0, 4096)) > 0) {
93                                 mstream.Write (buf, 0, count);
94                         }
95                         mstream.Position = 0;
96                 }
97                 
98                 void LoadFromUri (string location)
99                 {
100                         mstream = null;
101                         Stream data = null;
102                         if (string.IsNullOrEmpty (location))
103                                 return;
104
105                         if(File.Exists(location))
106                                 data = new FileStream(location, FileMode.Open, FileAccess.Read, FileShare.Read);
107                         else {
108                                 System.Net.WebRequest request = System.Net.WebRequest.Create(location);
109                                 data = request.GetResponse().GetResponseStream();
110                         }
111                         
112                         using (data)
113                                 LoadFromStream (data);
114                 }
115
116                 public void Load ()
117                 {
118                         // can this be reused to load the same file again without re-setting the location?
119                         if (load_completed)
120                                 return;
121                         if (audiostream != null) {
122                                 LoadFromStream (audiostream);
123                         } else {
124                                 LoadFromUri (sound_location);
125                         }
126
127                         // force recreate for new stream
128                         adata = null;
129                         adev = null;
130
131                         load_completed = true;
132                         AsyncCompletedEventArgs e = new AsyncCompletedEventArgs (null, false, this);
133                         OnLoadCompleted (e);
134                         if (LoadCompleted != null)
135                                 LoadCompleted (this, e);
136
137                         if (use_win32_player) {
138                                 if (win32_player == null)
139                                         win32_player = new Win32SoundPlayer (mstream);
140                                 else 
141                                         win32_player.Stream = mstream;
142                         }
143                 }
144
145                 void AsyncFinished (IAsyncResult ar)
146                 {
147                         ThreadStart async = ar.AsyncState as ThreadStart;
148                         async.EndInvoke (ar);
149                 }
150
151                 public void LoadAsync ()
152                 {
153                         if (load_completed)
154                                 return;
155                         ThreadStart async = new ThreadStart (Load);
156                         async.BeginInvoke (AsyncFinished, async);
157                 }
158
159                 protected virtual void OnLoadCompleted (AsyncCompletedEventArgs e)
160                 {
161                 }
162
163                 protected virtual void OnSoundLocationChanged (EventArgs e)
164                 {
165                 }
166
167                 protected virtual void OnStreamChanged (EventArgs e)
168                 {
169                 }
170
171                 void Start ()
172                 {
173                         if (!use_win32_player) {
174                                 stopped = false;
175                                 if (adata != null)
176                                         adata.IsStopped = false;
177                         }
178                         if (!load_completed)
179                                 Load ();
180                 }
181
182                 public void Play ()
183                 {
184                         if (!use_win32_player) {
185                                 ThreadStart async = new ThreadStart (PlaySync);
186                                 async.BeginInvoke (AsyncFinished, async);
187                         } else {
188                                 Start ();
189
190                                 if (mstream == null) {
191                                         SystemSounds.Beep.Play ();
192                                         return;
193                                 }
194
195                                 win32_player.Play ();
196                         }
197                 }
198
199                 private void PlayLoop ()
200                 {
201                         Start ();
202
203                         if (mstream == null) {
204                                 SystemSounds.Beep.Play ();
205                                 return;
206                         }
207
208                         while (!stopped)
209                                 PlaySync ();
210                 }
211
212                 public void PlayLooping ()
213                 {
214                         if (!use_win32_player) {
215                                 ThreadStart async = new ThreadStart (PlayLoop);
216                                 async.BeginInvoke (AsyncFinished, async);
217                         } else {
218                                 Start ();
219
220                                 if (mstream == null) {
221                                         SystemSounds.Beep.Play ();
222                                         return;
223                                 }
224
225                                 win32_player.PlayLooping ();
226                         }
227                 }
228
229                 public void PlaySync ()
230                 {
231                         Start ();
232
233                         if (mstream == null) {
234                                 SystemSounds.Beep.Play ();
235                                 return;
236                         }
237
238                         if (!use_win32_player) {
239                                 try {
240                                         if (adata == null)
241                                                 adata = new WavData (mstream);
242                                         if (adev == null)
243                                                 adev = AudioDevice.CreateDevice (null);
244                                         if (adata != null) {
245                                                 adata.Setup (adev);
246                                                 adata.Play (adev);
247                                         }
248                                 } catch {
249                                 }
250                         } else {
251                                 win32_player.PlaySync ();
252                         }
253                 }
254
255                 public void Stop ()
256                 {
257                         if (!use_win32_player) {
258                                 stopped = true;
259                                 if (adata != null)
260                                         adata.IsStopped = true;
261                         } else {
262                                 win32_player.Stop ();
263                         }
264                 }
265
266                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
267                 {
268                 }
269
270                 public bool IsLoadCompleted {
271                         get {
272                                 return load_completed;
273                         }
274                 }
275
276                 public int LoadTimeout {
277                         get {
278                                 return load_timeout;
279                         }
280                         set {
281                                 if (value < 0)
282                                         throw new ArgumentException ("timeout must be >= 0");
283                                 load_timeout = value;
284                         }
285                 }
286
287                 public string SoundLocation {
288                         get {
289                                 return sound_location;
290                         }
291                         set {
292                                 if (value == null)
293                                         throw new ArgumentNullException ("value");
294                                 sound_location = value;
295                                 load_completed = false;
296                                 OnSoundLocationChanged (EventArgs.Empty);
297                                 if (SoundLocationChanged != null)
298                                         SoundLocationChanged (this, EventArgs.Empty);
299                         }
300                 }
301
302                 public Stream Stream {
303                         get {
304                                 return audiostream;
305                         }
306                         set {
307                                 if (audiostream != value) {
308                                         audiostream = value;
309                                         load_completed = false;
310                                         OnStreamChanged (EventArgs.Empty);
311                                         if (StreamChanged != null)
312                                                 StreamChanged (this, EventArgs.Empty);
313                                 }
314                         }
315                 }
316
317                 public object Tag {
318                         get {
319                                 return tag;
320                         }
321                         set {
322                                 tag = value;
323                         }
324                 }
325
326                 public event AsyncCompletedEventHandler LoadCompleted;
327                 public event EventHandler SoundLocationChanged;
328                 public event EventHandler StreamChanged;
329         }
330 }
331