|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Provides Sound API for playing tones and digitized audio. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 package com.nokia.mid.sound; |
|
20 |
|
21 import com.nokia.mj.impl.rt.support.Finalizer; |
|
22 import java.util.Vector; |
|
23 import com.nokia.mj.impl.utils.Logger; |
|
24 import java.lang.Thread; |
|
25 |
|
26 /** |
|
27 * <p> |
|
28 * Provides simple Sound API for playing tones and digitized audio. |
|
29 * </p><p> |
|
30 * Since MIDP doesn't have any Sound API for games there is a need |
|
31 * for proprietary sound extension to support devices audio |
|
32 * capabilities. Every implementation has capability to produce tone |
|
33 * sounds (e.g. ringing tones), this is the minimum support. Currently |
|
34 * some products support or will support also digitized audio formats. |
|
35 * The Game sound API will support both buzzer and digitized audio. |
|
36 * Buzzer must be supported by all implementations. If implementation |
|
37 * doesn't have buzzer the buzzer tones are emulated. |
|
38 * </p> |
|
39 * Since implementations have different audio capabilities, |
|
40 * application can query which audio formats are supported by |
|
41 * implementation by calling {@link #getSupportedFormats()}. |
|
42 * <p> |
|
43 * All implementations need to support at least tone based sounds |
|
44 * (type FORMAT_TONE) via {@link #Sound(int freq, long duration)} and |
|
45 * {@link #init(int freq, long duration)}. In addition all implementations |
|
46 * must support Smart messaging ringingtone format (type FORMAT_TONE) |
|
47 * via {@link #Sound(byte[] data, int type)} and |
|
48 * {@link #init(byte[] data, int type) }. |
|
49 * <p> |
|
50 * Note that there is also work going on with Multimedia API that |
|
51 * is done in JCP as |
|
52 * <a href="http://www.jcp.org/jsr/detail/135.jsp">JSR 135</a>. |
|
53 * The standard Multimedia API |
|
54 * will replace the proprietary Game Sound API when it is ready. However |
|
55 * Sound API will be supported also later on but probably it will be |
|
56 * stated as deprecated. |
|
57 * </p> |
|
58 * @version 1.1 |
|
59 * @see com.nokia.mid.ui.DeviceControl |
|
60 * @since 1.0 |
|
61 */ |
|
62 |
|
63 public class Sound |
|
64 { |
|
65 |
|
66 /** |
|
67 * Tone based format is used. |
|
68 * |
|
69 * init(int freq, int duration) puts sound into this format. |
|
70 * @since 1.0 |
|
71 * |
|
72 */ |
|
73 public static final int FORMAT_TONE = 1; |
|
74 |
|
75 /** |
|
76 * Content is in WAV format. |
|
77 * @since 1.0 |
|
78 * |
|
79 */ |
|
80 public static final int FORMAT_WAV = 5; |
|
81 |
|
82 /** |
|
83 * Sound is playing. |
|
84 * @since 1.0 |
|
85 * |
|
86 */ |
|
87 public static final int SOUND_PLAYING = 0; |
|
88 |
|
89 /** |
|
90 * Sound is stopped. |
|
91 * @since 1.0 |
|
92 * |
|
93 */ |
|
94 public static final int SOUND_STOPPED = 1; |
|
95 |
|
96 /** |
|
97 * Sound is uninitialized (released). |
|
98 * @since 1.0 |
|
99 */ |
|
100 public static final int SOUND_UNINITIALIZED = 3; |
|
101 |
|
102 /** |
|
103 * Sound is reinitialising |
|
104 */ |
|
105 private static final int SOUND_REINITIALISING = 4; |
|
106 |
|
107 private static final int FORMAT_BEEP = 2; |
|
108 private static final int NOT_SUPPORTED_ERROR = 3; |
|
109 |
|
110 private static final int ERR_NOT_READY = -18; |
|
111 |
|
112 private int iHandle; |
|
113 |
|
114 private Finalizer iFinalizer; |
|
115 private int iCurrentType; |
|
116 private int iState; |
|
117 private int iGain = -1; |
|
118 |
|
119 Vector iSoundListeners = new Vector(); |
|
120 |
|
121 private static Sound iPlayingSound; |
|
122 |
|
123 static |
|
124 { |
|
125 com.nokia.mj.impl.rt.support.Jvm.loadSystemLibrary("javanokiasound"); |
|
126 } |
|
127 |
|
128 /** |
|
129 * Constructors initialize the Sound object so that it is ready for |
|
130 * playback. This constructor is used for initializing Sound |
|
131 * object based on byte array data. The data should contain the data |
|
132 * presented in the data format specified by type parameter. The Sound |
|
133 * class defines also generally supported types as constants. |
|
134 * <p> |
|
135 * All implementations need to support at least Nokia |
|
136 * Smart Messaging, Over the Air (OTA) ringingtone format. |
|
137 * The type of this format is FORMAT_TONE. |
|
138 * <p> |
|
139 * Note: some implementations can't throw exceptions about |
|
140 * sound data being corrupted or illegal during construction. |
|
141 * This will result that IllagalArgumentException is delayed until |
|
142 * play(int loop) method is called. Applications thus need to except |
|
143 * that IllegalArgumentException is thrown in this method or during |
|
144 * play method call. |
|
145 * <p> |
|
146 * @throws java.lang.IllegalArgumentException if the data can not be |
|
147 recognized to |
|
148 * given type or the type is unsupported or unknown |
|
149 * @throws java.lang.NullPointerException if the data is null |
|
150 * @since 1.0 |
|
151 * |
|
152 */ |
|
153 public Sound(byte[] data, int type) |
|
154 { |
|
155 Logger.LOG(Logger.EJavaUI, Logger.EInfo, "Sound Constructor"); |
|
156 iFinalizer = registerForFinalization(); |
|
157 |
|
158 iHandle = _create(); |
|
159 |
|
160 iState = SOUND_UNINITIALIZED; |
|
161 |
|
162 init(data, type); |
|
163 } |
|
164 |
|
165 /** |
|
166 * Constructors initialize the Sound object so that it is ready for |
|
167 * playback. Sound is initialized as a simple tone based sound. |
|
168 * <p> |
|
169 * See method {@link #init(int freq, long duration)} for |
|
170 * freq value descriptions. See also a note on exceptions semantics in |
|
171 * {@link #init(int freq, long duration)}. |
|
172 * |
|
173 * @param freq a frequency value |
|
174 * @param duration the duration of the tone in milliseconds |
|
175 * @throws java.lang.IllegalArgumentException if parameter values are |
|
176 * illegal, freq is not in given range or duration is negative or zero |
|
177 * @since 1.0 |
|
178 */ |
|
179 public Sound(int freq, long duration) |
|
180 { |
|
181 |
|
182 iFinalizer = registerForFinalization(); |
|
183 iHandle = _create(); |
|
184 |
|
185 iState = SOUND_UNINITIALIZED; |
|
186 |
|
187 init(freq, duration); |
|
188 } |
|
189 |
|
190 /** |
|
191 * Called when this object is finalized, frees native resources |
|
192 */ |
|
193 |
|
194 public Finalizer registerForFinalization() |
|
195 { |
|
196 |
|
197 return new Finalizer() |
|
198 { |
|
199 public void finalizeImpl() |
|
200 { |
|
201 doFinalize(); |
|
202 } |
|
203 }; |
|
204 } |
|
205 |
|
206 void doFinalize() |
|
207 { |
|
208 |
|
209 if (iFinalizer == null) |
|
210 { |
|
211 return; |
|
212 } |
|
213 iFinalizer = null; |
|
214 |
|
215 if (iHandle > 0) |
|
216 { |
|
217 _dispose(iHandle); |
|
218 } |
|
219 } |
|
220 |
|
221 /** |
|
222 * Releases audio resources reserved by this object. After object |
|
223 * is released it goes to uninitialized state. This method should |
|
224 * be called when Sound object is not needed anymore. |
|
225 * @since 1.0 |
|
226 */ |
|
227 public void release() |
|
228 { |
|
229 if ((iState != SOUND_UNINITIALIZED) && |
|
230 (iState != SOUND_REINITIALISING)) |
|
231 { |
|
232 iState = SOUND_REINITIALISING; |
|
233 soundStateChanged(SOUND_UNINITIALIZED); |
|
234 } |
|
235 |
|
236 _release(iHandle); |
|
237 |
|
238 iState = SOUND_UNINITIALIZED; |
|
239 |
|
240 } |
|
241 |
|
242 /** |
|
243 * Initializes Sound to play a simple beep. |
|
244 * <p> |
|
245 * Note: some implementations may not support the full frequency |
|
246 * scale defined in table below. They will throw |
|
247 * IllegalArgumentException instead for unsupported values. The |
|
248 * exception may also be delayed |
|
249 * until the play(int loop) method is called. |
|
250 * <p> |
|
251 * Following table describes some freq argument |
|
252 * values: |
|
253 * <pre> |
|
254 * Description Frequency |
|
255 * Freq off 0 |
|
256 * Ring freq A0 220 |
|
257 * Ring freq B0b 233 |
|
258 * Ring freq B0 247 |
|
259 * Ring freq C0 262 |
|
260 * Ring freq D0b 277 |
|
261 * Ring freq D0 294 |
|
262 * Ring freq E0b 311 |
|
263 * Ring freq E0 330 |
|
264 * Ring freq F0 349 |
|
265 * Ring freq G0b 370 |
|
266 * Ring freq G0 392 |
|
267 * Ring freq A1b 416 |
|
268 * Ring freq A1 440 |
|
269 * Ring freq B1b 466 |
|
270 * Ring freq B1 494 |
|
271 * Ring freq C1 523 |
|
272 * Ring freq D1b 554 |
|
273 * Ring freq D1 587 |
|
274 * Ring freq E1b 622 |
|
275 * Ring freq E1 659 |
|
276 * Ring freq F1 698 |
|
277 * Ring freq G1b 740 |
|
278 * Ring freq G1 784 |
|
279 * Ring freq A2b 831 |
|
280 * Ring freq A2 880 |
|
281 * Ring freq B2b 932 |
|
282 * Ring freq B2 988 |
|
283 * Ring freq C2 1047 |
|
284 * Ring freq D2b 1109 |
|
285 * Ring freq D2 1175 |
|
286 * Ring freq E2b 1245 |
|
287 * Ring freq E2 1319 |
|
288 * Ring freq F2 1397 |
|
289 * Ring freq G2b 1480 |
|
290 * Ring freq G2 1568 |
|
291 * Ring freq A3b 1661 |
|
292 * Ring freq A3 1760 |
|
293 * Ring freq B3b 1865 |
|
294 * Ring freq B3 1976 |
|
295 * Ring freq C3 2093 |
|
296 * Ring freq D3b 2217 |
|
297 * Ring freq D3 2349 |
|
298 * Ring freq E3b 2489 |
|
299 * Ring freq E3 2637 |
|
300 * Ring freq F3 2794 |
|
301 * Ring freq G3b 2960 |
|
302 * Ring freq G3 3136 |
|
303 * Ring freq A4b 3322 |
|
304 * Ring freq A4 3520 |
|
305 * Ring freq B4b 3729 |
|
306 * Ring freq B4 3951 |
|
307 * Ring freq C4 4186 |
|
308 * Ring freq D4b 4434 |
|
309 * Ring freq D4 4698 |
|
310 * Ring freq E4b 4978 |
|
311 * Ring freq E4 5274 |
|
312 * Ring freq F4 5588 |
|
313 * Ring freq G4b 5920 |
|
314 * Ring freq G4 6272 |
|
315 * Ring freq A5b 6644 |
|
316 * Ring freq A5 7040 |
|
317 * Ring freq B5b 7458 |
|
318 * Ring freq B5 7902 |
|
319 * Ring freq C5 8372 |
|
320 * Ring freq D5b 8870 |
|
321 * Ring freq D5 9396 |
|
322 * Ring freq E5b 9956 |
|
323 * Ring freq E5 10548 |
|
324 * Ring freq F5 11176 |
|
325 * Ring freq G5b 11840 |
|
326 * Ring freq G5 12544 |
|
327 * Ring freq A6b 13288 |
|
328 * |
|
329 * </pre> |
|
330 * |
|
331 * @param duration length of the beep in milliseconds |
|
332 * @param freq frequency to be played |
|
333 * @throws java.lang.IllegalArgumentException if parameter values are |
|
334 * illegal, freq is not in given range or duration is negative or zero |
|
335 * @since 1.0 |
|
336 */ |
|
337 public void init(int freq, long duration) |
|
338 { |
|
339 if (duration < 1 || duration > 10000000) |
|
340 { |
|
341 throw(new IllegalArgumentException( |
|
342 "Bad duration value, must be 1-10000000")); |
|
343 } |
|
344 if (freq < 0 || freq > 15000) |
|
345 { |
|
346 throw(new IllegalArgumentException( |
|
347 "Bad frequency value, must be 0-15000")); |
|
348 } |
|
349 // if the uninitialised event is sent from native side, it reaches |
|
350 // listener too late in TCK test sound8004, thus we send the event |
|
351 // already here |
|
352 if ((iState != SOUND_UNINITIALIZED) && |
|
353 (iState != SOUND_REINITIALISING)) |
|
354 { |
|
355 iState = SOUND_REINITIALISING; |
|
356 soundStateChanged(SOUND_UNINITIALIZED); |
|
357 } // end of if (iState != SOUND_UNINITIALIZED) |
|
358 |
|
359 iCurrentType = FORMAT_BEEP; |
|
360 int err = _init(iHandle, iCurrentType, null, freq, duration); |
|
361 if (err == ERR_NOT_READY) |
|
362 { |
|
363 throw new RuntimeException(Integer.toString(err)); |
|
364 } |
|
365 iState = SOUND_STOPPED; |
|
366 } |
|
367 |
|
368 /** |
|
369 * Initializes Sound object based on byte |
|
370 * array data. The data should contain the data presented in the data |
|
371 * format specified by type parameter. The Sound class defines also |
|
372 * generally supported types as constants. |
|
373 * <p> |
|
374 * All implementations need to support at least Nokia |
|
375 * Smart Messaging, Over the Air (OTA) ringingtone format. |
|
376 * The type of this format is FORMAT_TONE. |
|
377 * <p> |
|
378 * Note: some implementations can't throw exceptions about |
|
379 * sound data being corrupted or illegal during this method call. |
|
380 * This will result that IllagalArgumentException is delayed until |
|
381 * play(int loop) method is called. Applications thus need to except |
|
382 * that IllegalArgumentException is thrown in this method or during |
|
383 * play method call. |
|
384 * <p> |
|
385 * @param data a byte array containing the data to be played |
|
386 * @param type type of the audio |
|
387 * @throws java.lang.IllegalArgumentException if the data can not be |
|
388 recognized to |
|
389 * given type or the type is unsupported or unknown |
|
390 * @throws java.lang.NullPointerException if the data is null |
|
391 * @since 1.0 |
|
392 */ |
|
393 public void init(byte[] data, int type) |
|
394 { |
|
395 if (!(type == FORMAT_WAV || type == FORMAT_TONE)) |
|
396 { |
|
397 throw(new IllegalArgumentException("Type is not supported")); |
|
398 } |
|
399 if (data == null) |
|
400 { |
|
401 throw(new NullPointerException("Data is null")); |
|
402 } |
|
403 |
|
404 if ((iState != SOUND_UNINITIALIZED) && |
|
405 (iState != SOUND_REINITIALISING)) |
|
406 { |
|
407 iState = SOUND_REINITIALISING; |
|
408 soundStateChanged(SOUND_UNINITIALIZED); |
|
409 } // end of if (iState != SOUND_UNINITIALIZED) |
|
410 |
|
411 iCurrentType = type; |
|
412 int err = _init(iHandle, iCurrentType, data, 0, 0); |
|
413 if (err == ERR_NOT_READY) |
|
414 { |
|
415 throw new IllegalArgumentException("Data is invalid"); |
|
416 } |
|
417 |
|
418 iState = SOUND_STOPPED; |
|
419 } |
|
420 |
|
421 |
|
422 /** |
|
423 * Get the current state of the Sound object. |
|
424 * |
|
425 * @return current state, SOUND_PLAYING, SOUND_STOPPED or |
|
426 SOUND_UNINITIALIZED |
|
427 * @since 1.0 |
|
428 * |
|
429 */ |
|
430 public int getState() |
|
431 { |
|
432 if (iState == SOUND_REINITIALISING) |
|
433 { |
|
434 return SOUND_UNINITIALIZED; |
|
435 } |
|
436 |
|
437 iState = _getState(iHandle); |
|
438 switch (iState) |
|
439 { |
|
440 case(0): // ENotReady |
|
441 case(4): // EInitialising |
|
442 iState = SOUND_UNINITIALIZED; |
|
443 break; |
|
444 case(1): // EReadyToPlay |
|
445 iState = SOUND_STOPPED; |
|
446 break; |
|
447 case(2): // EPlaying |
|
448 iState = SOUND_PLAYING; |
|
449 break; |
|
450 default: |
|
451 } |
|
452 return iState; |
|
453 } |
|
454 |
|
455 /** |
|
456 * This method is used for starting the playback from the beginning of a |
|
457 * sound object. The loop parameter defined the loop count for playback. |
|
458 * Argument zero (0) means continuos looping. For uninitialized sound the |
|
459 * play method doesn't do anything and silently returns. For stopped and |
|
460 * playing sounds the playback starts from beginning of the sound with new |
|
461 * looping information. |
|
462 * <p> |
|
463 * This method will throw IllegalStateException if playback cannot be |
|
464 * started since all channels are in use, or playback is not possible |
|
465 * because there is more higher priority system sounds being played. |
|
466 * <p> |
|
467 * If Sound playback is possible this method will return immediately and |
|
468 * thus will not block the calling thread during the playback. If any error |
|
469 * that prevents the playback is encountered during the playback, the |
|
470 * playback is silently stopped as if called to the stop method. |
|
471 * |
|
472 * @param number number of times audio is played. Value 0 plays audio in |
|
473 * continous loop. |
|
474 * @throws java.lang.IllegalStateException if the sound object cannot be |
|
475 * played because all the channels are already in use. |
|
476 * @throws java.lang.IllegalArgumentException if the loop value is negative, |
|
477 * or if sound values/date is illegal or corrupted. |
|
478 * @since 1.0 |
|
479 * |
|
480 */ |
|
481 public void play(int loop) throws IllegalArgumentException |
|
482 { |
|
483 if (loop < 0) |
|
484 { |
|
485 throw(new IllegalArgumentException("Negative loop value")); |
|
486 } |
|
487 if (iState == SOUND_REINITIALISING) |
|
488 { |
|
489 return; |
|
490 } // end of if (iState == SOUND_REINITIALISING) |
|
491 |
|
492 if (iPlayingSound != null) |
|
493 { |
|
494 if (iPlayingSound.getState() == SOUND_PLAYING) |
|
495 { |
|
496 iPlayingSound.stop(); |
|
497 } |
|
498 } // end of if (iPlayingSound != null) |
|
499 |
|
500 int error = _play(iHandle, loop); |
|
501 if ((error == NOT_SUPPORTED_ERROR)) |
|
502 { |
|
503 throw(new IllegalArgumentException("Sound is not supported")); |
|
504 } |
|
505 iPlayingSound = this; |
|
506 } |
|
507 |
|
508 /** |
|
509 * The method will stop the sound playback, storing the current position. |
|
510 * For sound that has never been started (may be uninitialized), or is |
|
511 * currently being stopped the method call doesn't do anything and returns |
|
512 * silently. |
|
513 * |
|
514 * Note that for tone based sounds it is not possible to resume from |
|
515 * position the sound was stopped at, to be specific, stop will reset |
|
516 * the position to the beginning of the sound. |
|
517 * @since 1.0 |
|
518 */ |
|
519 public void stop() |
|
520 { |
|
521 if (iState == SOUND_REINITIALISING) |
|
522 { |
|
523 return; |
|
524 } // end of if (iState == SOUND_REINITIALISING) |
|
525 _stop(iHandle); |
|
526 } |
|
527 |
|
528 /** |
|
529 * The method will continue the stopped sound object from the position it |
|
530 * was stopped to. For sound that has never been started (may be |
|
531 * uninitialized), or is currently being played the method call doesn't |
|
532 * do anything. |
|
533 * <p> |
|
534 * Note: For tone based sounds the resume starts the sound from the |
|
535 * beginning of the sound clip. |
|
536 * @since 1.0 |
|
537 * |
|
538 */ |
|
539 public void resume() |
|
540 { |
|
541 if (iState == SOUND_REINITIALISING) |
|
542 { |
|
543 return; |
|
544 } // end of if (iState == SOUND_REINITIALISING) |
|
545 _resume(iHandle); |
|
546 } |
|
547 |
|
548 /** |
|
549 * Sets the gain for the sound object. The gain is a value between |
|
550 * 0 and 255. Implementation scales the gain value to the limits it |
|
551 * supports. Notice that any gain value > 0 should result a gain |
|
552 * value > 0. If the gain is smaller than this minimum value then |
|
553 * gain is set to 0, if the gain greater than this maximum value |
|
554 * then the gain is set to maximum value (255). |
|
555 * |
|
556 * @param gain gain value: 0 - 255 |
|
557 * @throws java.lang.IllegalArgumentException if the gain not 0 - 255 |
|
558 * @since 1.0 |
|
559 */ |
|
560 public void setGain(int gain) |
|
561 { |
|
562 if (iState == SOUND_REINITIALISING) |
|
563 { |
|
564 return; |
|
565 } // end of if (iState == SOUND_REINITIALISING) |
|
566 if (gain < 0) |
|
567 { |
|
568 gain = 0; |
|
569 } |
|
570 else if (gain > 255) |
|
571 { |
|
572 gain = 255; |
|
573 } |
|
574 iGain = gain; |
|
575 _setVolume(iHandle, iGain); |
|
576 } |
|
577 |
|
578 /** |
|
579 * Get the gain (or volume) of Sound object. The gain is a value |
|
580 * between 0 and 255. System returns a scaled value based on the |
|
581 * limits it supports. Notice that any system gain value > 0 should |
|
582 * return a gain value > 0. |
|
583 * |
|
584 * @return gain value 0 - 255 |
|
585 * @since 1.0 |
|
586 * |
|
587 */ |
|
588 public int getGain() |
|
589 { |
|
590 if (iGain == -1) |
|
591 { |
|
592 return _volume(iHandle); |
|
593 } |
|
594 // we have previously set gain |
|
595 return iGain; |
|
596 } |
|
597 |
|
598 /** |
|
599 * Returns number of concurrent sounds the device can play for |
|
600 * specific audio type. Returns 1 if only one sound can be played |
|
601 * at a time. Notice that most types use same channel resources. |
|
602 * @return total number of available channels. |
|
603 * @param type the media type |
|
604 * @throws java.lang.IllegalArgumentException if the type is unsupported |
|
605 * or unknown |
|
606 * @since 1.0 |
|
607 */ |
|
608 public static int getConcurrentSoundCount(int type) |
|
609 { |
|
610 if ((type != FORMAT_TONE) && (type != FORMAT_WAV)) |
|
611 { |
|
612 throw(new IllegalArgumentException("Type is not supported")); |
|
613 } |
|
614 |
|
615 return 1; |
|
616 } |
|
617 |
|
618 /** |
|
619 * Returns the supported audio formats as an int array. |
|
620 * |
|
621 * @return an array containing supported audio formats as |
|
622 * int values (e.g. FORMAT_TONE, FORMAT_WAV), |
|
623 * or an empty array if no audio formats are supported. |
|
624 * @since 1.0 |
|
625 */ |
|
626 static public int[] getSupportedFormats() |
|
627 { |
|
628 return(new int[] { FORMAT_TONE, FORMAT_WAV }); |
|
629 } |
|
630 |
|
631 /** |
|
632 * Registeres a listener for playback state notifications. |
|
633 * @see com.nokia.mid.sound.SoundListener |
|
634 * @param listener a listener that is notified when state |
|
635 * changes occur or null if listener is to be |
|
636 * removed. |
|
637 * @since 1.0 |
|
638 * |
|
639 */ |
|
640 public void setSoundListener(SoundListener listener) |
|
641 { |
|
642 iSoundListeners.addElement(listener); |
|
643 } |
|
644 |
|
645 /** |
|
646 * Callback method when sound state changes |
|
647 * |
|
648 */ |
|
649 public void soundStateChanged(final int event) |
|
650 { |
|
651 /* |
|
652 for(int i = 0; i < iSoundListeners.size(); i++) |
|
653 { |
|
654 ((SoundListener)iSoundListeners.elementAt(i)).soundStateChanged(this, event); |
|
655 } |
|
656 */ |
|
657 //Notify SoundState Listeners in a separate thread, so that application doesn't |
|
658 //block main thread |
|
659 new Thread(new Runnable() |
|
660 { |
|
661 public void run() |
|
662 { |
|
663 notifySoundStateListeners(event); |
|
664 } |
|
665 }).start(); |
|
666 } |
|
667 |
|
668 /** |
|
669 * Notify Sound State Listeners |
|
670 */ |
|
671 public synchronized void notifySoundStateListeners(int event) |
|
672 { |
|
673 for (int i = 0; i < iSoundListeners.size(); i++) |
|
674 { |
|
675 ((SoundListener)iSoundListeners.elementAt(i)).soundStateChanged(this, event); |
|
676 } |
|
677 } |
|
678 |
|
679 private native void _dispose(int aHandle); |
|
680 private native int _create(); |
|
681 private native int _init(int aHandle, int aType, |
|
682 byte[] aData, |
|
683 int aFrequency, long aDuration); |
|
684 private native void _release(int aHandle); |
|
685 private native int _play(int aHandle, int aLoop); |
|
686 private native void _stop(int aHandle); |
|
687 private native void _resume(int aHandle); |
|
688 private native void _setVolume(int aHandle, int aVolume); |
|
689 private native int _volume(int aHandle); |
|
690 private native int _getState(int aHandle); |
|
691 |
|
692 } //End of Sound class |
|
693 |