1 |
/* |
2 |
* MediaPlayer.cs |
3 |
* Copyright (c) 2007-2009 kbinani |
4 |
* |
5 |
* This file is part of Boare.Lib.Media. |
6 |
* |
7 |
* Boare.Lib.Media is free software; you can redistribute it and/or |
8 |
* modify it under the terms of the BSD License. |
9 |
* |
10 |
* Boare.Lib.Media is distributed in the hope that it will be useful, |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
13 |
*/ |
14 |
using System; |
15 |
using System.Text; |
16 |
using System.Runtime.InteropServices; |
17 |
using System.Windows.Forms; |
18 |
|
19 |
namespace Boare.Lib.Media { |
20 |
|
21 |
/// <summary> |
22 |
/// Sound player using mciSendSring command operation |
23 |
/// </summary> |
24 |
public class MediaPlayer : IDisposable { |
25 |
private string m_filename = ""; |
26 |
const int FALSE = 0; |
27 |
const int TRUE = 1; |
28 |
bool pausing = false; |
29 |
int m_volume = 1000; |
30 |
bool mute = false; |
31 |
string m_alias = ""; |
32 |
bool m_loaded = false; |
33 |
float m_speed = 1.0f; |
34 |
bool m_playing = false; |
35 |
/// <summary> |
36 |
/// the number of Load failure |
37 |
/// </summary> |
38 |
int m_load_failed = 0; |
39 |
|
40 |
~MediaPlayer() { |
41 |
Dispose(); |
42 |
} |
43 |
|
44 |
public void Dispose() { |
45 |
if ( m_loaded ) { |
46 |
Close(); |
47 |
} |
48 |
m_playing = false; |
49 |
} |
50 |
|
51 |
/// <summary> |
52 |
/// Gets or Sets the speed |
53 |
/// </summary> |
54 |
public float Speed { |
55 |
get { |
56 |
return m_speed; |
57 |
} |
58 |
set { |
59 |
m_speed = value; |
60 |
SetSpeed( m_speed ); |
61 |
} |
62 |
} |
63 |
|
64 |
/// <summary> |
65 |
/// Sets the speed |
66 |
/// </summary> |
67 |
/// <param name="speed">the value of speed to set</param> |
68 |
private void SetSpeed( float speed ) { |
69 |
w_mciSendString( "set " + m_alias + " speed " + (int)(speed * 1000.0f) ); |
70 |
} |
71 |
|
72 |
/// <summary> |
73 |
/// Gets or Sets the volume (0 >= volume >= 1000) |
74 |
/// </summary> |
75 |
public int Volume { |
76 |
get { |
77 |
if ( mute ) { |
78 |
return 0; |
79 |
} else { |
80 |
return m_volume; |
81 |
} |
82 |
} |
83 |
set { |
84 |
m_volume = value; |
85 |
SetVolume( m_volume ); |
86 |
} |
87 |
} |
88 |
|
89 |
/// <summary> |
90 |
/// Sets the volume (0 >= volume >= 1000) |
91 |
/// </summary> |
92 |
/// <param name="value"></param> |
93 |
private void SetVolume( int value ) { |
94 |
ReLoad(); |
95 |
w_mciSendString( "setaudio " + m_alias + " volume to " + value ); |
96 |
} |
97 |
|
98 |
/// <summary> |
99 |
/// Gets the volume (0 <= volume <= 1000) |
100 |
/// </summary> |
101 |
/// <returns></returns> |
102 |
private int GetVolume() { |
103 |
ReLoad(); |
104 |
string str; |
105 |
bool ret = w_mciSendString( "status " + m_alias + " volume", out str ); |
106 |
int v = m_volume; |
107 |
if ( ret ) { |
108 |
int v1; |
109 |
if ( int.TryParse( str, out v1 ) ) { |
110 |
v = v1; |
111 |
} |
112 |
} |
113 |
#if DEBUG |
114 |
Console.WriteLine( "MediaPlayer+GetVolume()" ); |
115 |
Console.WriteLine( " str=" + str ); |
116 |
Console.WriteLine( " volume=" + v ); |
117 |
#endif |
118 |
return v; |
119 |
} |
120 |
|
121 |
/// <summary> |
122 |
/// Gets or Sets whether sound is muted or not |
123 |
/// </summary> |
124 |
public bool IsMuted { |
125 |
get { |
126 |
return mute; |
127 |
} |
128 |
set { |
129 |
bool old = mute; |
130 |
mute = value; |
131 |
if ( old != mute ) { |
132 |
if ( mute ) { |
133 |
SetVolume( 0 ); |
134 |
} else { |
135 |
SetVolume( m_volume ); |
136 |
} |
137 |
} |
138 |
} |
139 |
} |
140 |
|
141 |
/// <summary> |
142 |
/// Gets the pass of the sound file |
143 |
/// </summary> |
144 |
public string SoundLocation { |
145 |
get { |
146 |
return m_filename; |
147 |
} |
148 |
} |
149 |
|
150 |
/// <summary> |
151 |
/// external declaration of mciSendString |
152 |
/// </summary> |
153 |
/// <param name="s1">Command String</param> |
154 |
/// <param name="s2">Return String</param> |
155 |
/// <param name="i1">Return String Size</param> |
156 |
/// <param name="i2">Callback Hwnd</param> |
157 |
/// <returns>true when successed, false if not</returns> |
158 |
[DllImport( "winmm.dll" )] |
159 |
extern static int mciSendString( string s1, StringBuilder s2, int i1, int i2 ); |
160 |
|
161 |
/// <summary> |
162 |
/// mciSendString wrapper with exception handling |
163 |
/// </summary> |
164 |
/// <param name="command">command sending to MCI</param> |
165 |
/// <param name="result">returned string of mciSendString</param> |
166 |
/// <returns>command successedd or not</returns> |
167 |
static bool w_mciSendString( string command, out string result ) { |
168 |
StringBuilder sb = new StringBuilder( 32 ); |
169 |
int io_status = 0; |
170 |
result = ""; |
171 |
try { |
172 |
io_status = mciSendString( command, sb, sb.Capacity, 0 ); |
173 |
result = sb.ToString(); |
174 |
} catch { |
175 |
return false; |
176 |
} |
177 |
if ( io_status == 0 ) { |
178 |
return true; |
179 |
} else { |
180 |
return false; |
181 |
} |
182 |
} |
183 |
|
184 |
static bool w_mciSendString( string command ) { |
185 |
string ret; |
186 |
return w_mciSendString( command, out ret ); |
187 |
} |
188 |
|
189 |
/// <summary> |
190 |
/// Closes sound file temporary |
191 |
/// </summary> |
192 |
/// <returns></returns> |
193 |
public void UnLoad() { |
194 |
if ( m_filename != "" ) { |
195 |
Stop(); |
196 |
w_mciSendString( "close " + m_alias ); |
197 |
m_loaded = false; |
198 |
} |
199 |
} |
200 |
|
201 |
/// <summary> |
202 |
/// Opens sound file which was closed with "UnLoad" method |
203 |
/// </summary> |
204 |
/// <returns></returns> |
205 |
public void ReLoad() { |
206 |
if ( m_filename != "" && !m_loaded && m_load_failed < 10 ) { |
207 |
if ( Load( m_filename ) ) { |
208 |
m_loaded = true; |
209 |
if ( mute ) { |
210 |
SetVolume( 0 ); |
211 |
} else { |
212 |
SetVolume( m_volume ); |
213 |
} |
214 |
} |
215 |
} |
216 |
} |
217 |
|
218 |
/// <summary> |
219 |
/// Opens sound file |
220 |
/// </summary> |
221 |
/// <param name="filename">Path of sound file to open</param> |
222 |
/// <returns>successed opening the file or not</returns> |
223 |
public bool Load( string filename ) { |
224 |
#if DEBUG |
225 |
Console.WriteLine( "MediaPlayer+Load(String)" ); |
226 |
Console.WriteLine( " filename=" + filename ); |
227 |
#endif |
228 |
if ( m_filename != "" ) { |
229 |
Close(); |
230 |
} |
231 |
this.m_filename = filename; |
232 |
m_alias = bocoree.misc.getmd5( m_filename ); |
233 |
#if DEBUG |
234 |
Console.WriteLine( " m_alias=" + m_alias ); |
235 |
#endif |
236 |
bool ret = w_mciSendString( "open \"" + filename + "\" type MPEGVIDEO2 alias " + m_alias ); |
237 |
if ( !ret ) { |
238 |
ret = w_mciSendString( "open \"" + filename + "\" type MPEGVIDEO alias " + m_alias ); |
239 |
if ( !ret ) { |
240 |
ret = w_mciSendString( "open \"" + filename + "\" alias " + m_alias ); |
241 |
} |
242 |
} |
243 |
#if DEBUG |
244 |
Console.WriteLine( " w_mciSendString result=" + ret ); |
245 |
#endif |
246 |
if ( ret ) { |
247 |
m_loaded = true; |
248 |
} else { |
249 |
m_load_failed++; |
250 |
} |
251 |
#if DEBUG |
252 |
m_volume = GetVolume(); |
253 |
Console.WriteLine( " m_volume=" + m_volume ); |
254 |
#endif |
255 |
SetVolume( m_volume ); |
256 |
return ret; |
257 |
} |
258 |
|
259 |
/// <summary> |
260 |
/// Plays sound from specified second |
261 |
/// </summary> |
262 |
/// <param name="time">Sound position start to play</param> |
263 |
/// <returns>true if play command successed</returns> |
264 |
public bool PlayFrom( double time ) { |
265 |
if ( m_filename == "" ) { |
266 |
return false; |
267 |
} |
268 |
long position = (long)(time * 1000); |
269 |
if ( !m_loaded ) { |
270 |
ReLoad(); |
271 |
} |
272 |
/*if ( mute ) { |
273 |
EnterMute(); |
274 |
} else { |
275 |
ExitMute(); |
276 |
}*/ |
277 |
SetSpeed( m_speed ); |
278 |
m_playing = true; |
279 |
return w_mciSendString( "play " + m_alias + " from " + position.ToString() ); |
280 |
} |
281 |
|
282 |
/// <summary> |
283 |
/// Closes sound file |
284 |
/// </summary> |
285 |
/// <returns>true if successed closing sound file</returns> |
286 |
public bool Close() { |
287 |
if ( m_filename == "" ) { |
288 |
return false; |
289 |
} |
290 |
Stop(); |
291 |
m_filename = ""; |
292 |
m_loaded = false; |
293 |
return w_mciSendString( "close " + m_alias ); |
294 |
} |
295 |
|
296 |
/// <summary> |
297 |
/// Plays sound from time 0 second |
298 |
/// </summary> |
299 |
/// <returns>true if successed to play</returns> |
300 |
public bool Play() { |
301 |
if ( m_filename == "" ) { |
302 |
return false; |
303 |
} |
304 |
if ( !m_loaded ) { |
305 |
ReLoad(); |
306 |
} |
307 |
/*if ( mute ) { |
308 |
EnterMute(); |
309 |
} else { |
310 |
ExitMute(); |
311 |
}*/ |
312 |
SetSpeed( m_speed ); |
313 |
m_playing = true; |
314 |
if ( pausing ) { |
315 |
//return w_mciSendString( "resume \"" + m_filename + "\"", null, 0, 0 ); |
316 |
return w_mciSendString( "resume " + m_alias ); |
317 |
} else { |
318 |
//return w_mciSendString( "play \"" + m_filename + "\"", null, 0, 0 ); |
319 |
return w_mciSendString( "play " + m_alias ); |
320 |
} |
321 |
} |
322 |
|
323 |
/// <summary> |
324 |
/// Seeks to specified position |
325 |
/// </summary> |
326 |
/// <param name="pos_second">position to seek in second</param> |
327 |
/// <returns>true if successed to seek</returns> |
328 |
public bool Seek( double pos_second ) { |
329 |
if ( m_filename == "" ) { |
330 |
return false; |
331 |
} |
332 |
if ( !m_loaded ) { |
333 |
ReLoad(); |
334 |
} |
335 |
long position = (long)(pos_second * 1000.0); |
336 |
bool ret = w_mciSendString( "seek " + m_alias + " to " + position ); |
337 |
return ret; |
338 |
} |
339 |
|
340 |
/// <summary> |
341 |
/// Pauses sound |
342 |
/// </summary> |
343 |
/// <returns>true if successed to pause</returns> |
344 |
public bool Pause() { |
345 |
if ( m_filename == "" ) { |
346 |
return false; |
347 |
} |
348 |
if ( !m_loaded ) { |
349 |
ReLoad(); |
350 |
} |
351 |
m_playing = false; |
352 |
pausing = true; |
353 |
//return w_mciSendString( "pause \"" + m_filename + "\"", null, 0, 0 ); |
354 |
return w_mciSendString( "pause " + m_alias ); |
355 |
} |
356 |
|
357 |
/// <summary> |
358 |
/// Gets the current playing position in millisecond |
359 |
/// </summary> |
360 |
/// <returns>playing position in millisecond</returns> |
361 |
public int GetPosition() { |
362 |
if ( this.SoundLocation == "" ) { |
363 |
return -1; |
364 |
} |
365 |
if ( !m_loaded ) { |
366 |
ReLoad(); |
367 |
} |
368 |
string ret; |
369 |
w_mciSendString( "status " + m_alias + " position", out ret ); |
370 |
int pos; |
371 |
try { |
372 |
pos = int.Parse( ret ); |
373 |
} catch { |
374 |
pos = -1; |
375 |
} |
376 |
return pos; |
377 |
} |
378 |
|
379 |
/// <summary> |
380 |
/// Gets the sound length in millisecond |
381 |
/// </summary> |
382 |
/// <returns>Sound length in millisecond</returns> |
383 |
public int GetLength() { |
384 |
if ( this.SoundLocation == "" ) { |
385 |
return -1; |
386 |
} |
387 |
if ( !m_loaded ) { |
388 |
ReLoad(); |
389 |
} |
390 |
string ret; |
391 |
w_mciSendString( "status " + m_alias + " length", out ret ); |
392 |
int length = -1; |
393 |
if ( int.TryParse( ret, out length ) ) { |
394 |
return length; |
395 |
} else { |
396 |
return -1; |
397 |
} |
398 |
} |
399 |
|
400 |
/// <summary> |
401 |
/// Stops sound |
402 |
/// </summary> |
403 |
/// <returns>true if successed to stop</returns> |
404 |
public bool Stop() { |
405 |
m_playing = false; |
406 |
return w_mciSendString( "stop " + m_alias ); |
407 |
} |
408 |
|
409 |
public bool IsPlaying { |
410 |
get { |
411 |
return m_playing; |
412 |
} |
413 |
} |
414 |
} |
415 |
|
416 |
} |