/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package com.nokia.mid.sound;
import java.io.*;
import java.lang.ref.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
public class Sound extends Object
{
private static final class Helper extends WeakReference
implements PlayerListener, SoundListener
{
Helper(Sound thisSound)
{
super(thisSound);
}
public void playerUpdate(Player player, String event, Object data)
{
Sound thisSound;
SoundListener listener;
if((thisSound = (Sound) get()) == null)
{
return;
}
if(STARTED.equals(event) || STOPPED.equals(event) || CLOSED.equals(event))
{
if((listener = thisSound.listener) != null)
{
listener.soundStateChanged(thisSound, thisSound.state);
}
return;
}
if(END_OF_MEDIA.equals(event))
{
thisSound.state = SOUND_STOPPED;
if((listener = thisSound.listener) != null)
{
listener.soundStateChanged(thisSound, SOUND_STOPPED);
}
}
}
public void soundStateChanged(Sound sound, int event)
{
Object thisSound;
if((thisSound = get()) != null && thisSound instanceof SoundListener)
{
((SoundListener) thisSound).soundStateChanged(sound, event);
}
}
}
public static final int FORMAT_TONE = 1;
public static final int FORMAT_WAV = 5;
public static final int SOUND_PLAYING = 0;
public static final int SOUND_STOPPED = 1;
public static final int SOUND_UNINITIALIZED = 3;
public static int getConcurrentSoundCount(int type)
{
return 1;
}
public static int[] getSupportedFormats()
{
return new int[] {
FORMAT_TONE, FORMAT_WAV
};
}
private int state;
private Helper helper;
private Player implement;
private VolumeControl volume;
private SoundListener listener;
public Sound(int frequency, long duration)
{
this.state = SOUND_UNINITIALIZED;
this.helper = new Helper(this);
recreate(frequency, duration);
}
public Sound(byte[] src, int type)
{
this.state = SOUND_UNINITIALIZED;
this.helper = new Helper(this);
recreate(src, type);
}
public void init(int frequency, long duration)
{
synchronized(helper)
{
recreate(frequency, duration);
}
}
public void init(byte[] src, int type)
{
if(src == null)
{
throw new NullPointerException("Sound: " +
"параметр src равен нулевой ссылке.");
}
if(type == FORMAT_TONE)
{
throw new IllegalArgumentException("Sound: " +
"формат данных FORMAT_TONE не поддерживается этой реализацией. " +
"Этот формат устарел и в настоящее время не используется.");
}
synchronized(helper)
{
recreate(src, type);
}
}
public void release()
{
Player implement;
synchronized(helper)
{
if((implement = this.implement) != null)
{
implement.close();
this.implement = null;
this.volume = null;
this.state = SOUND_UNINITIALIZED;
}
}
}
public void resume()
{
Player implement;
try
{
if((implement = this.implement) != null)
{
implement.start();
this.state = SOUND_PLAYING;
}
}
catch(MediaException e)
{
e.printRealStackTrace();
}
}
public void play(int loopCount)
{
Player implement;
if(loopCount < 0)
{
throw new IllegalArgumentException("Sound.play: " +
"недопустимое значение параметра loop.");
}
if(loopCount >= 0xff)
{
return;
}
if(loopCount == 0)
{
loopCount = -1;
}
synchronized(helper)
{
try
{
if((implement = this.implement) != null)
{
implement.stop();
implement.setLoopCount(loopCount);
implement.start();
this.state = SOUND_PLAYING;
}
}
catch(MediaException e)
{
e.printRealStackTrace();
}
}
}
public void stop()
{
Player implement;
try
{
if((implement = this.implement) != null)
{
implement.stop();
this.state = SOUND_STOPPED;
}
}
catch(MediaException e)
{
e.printRealStackTrace();
}
}
public void setSoundListener(SoundListener listener)
{
this.listener = listener == this ? helper : listener;
}
public void setGain(int level)
{
VolumeControl volume;
level = level < 0 ? 0 : (level > 0xff ? 0xff : level);
if((volume = this.volume) != null)
{
volume.setLevel(level * 100 / 255);
}
}
public int getGain()
{
VolumeControl volume;
return (volume = this.volume) != null ? volume.getLevel() * 255 / 100 : -1;
}
public int getState()
{
return state;
}
private void recreate(int frequency, long duration)
{
System.out.println("Метод com.nokia.mid.sound.Sound.init(int, long) не реализован.");
}
private void recreate(byte[] src, int type)
{
Player implement;
VolumeControl volume;
if(src == null)
{
throw new NullPointerException("Sound: " +
"параметр src равен нулевой ссылке.");
}
switch(type)
{
case FORMAT_WAV:
try
{
if((implement = this.implement) != null)
{
implement.close();
}
(implement = Manager.createPlayer(new ByteArrayInputStream(src), "audio/x-wav")).
addPlayerListener(helper);
implement.prefetch();
volume = (VolumeControl) implement.getControl("VolumeControl");
this.implement = implement;
this.volume = volume;
this.state = SOUND_STOPPED;
}
catch(Exception e)
{
throw new IllegalArgumentException("Sound: " +
"не удалось декодировать данные согласно формату данных FORMAT_WAV.");
}
break;
case FORMAT_TONE:
throw new IllegalArgumentException("Sound: " +
"формат данных FORMAT_TONE не поддерживается этой реализацией. " +
"Этот формат устарел и в настоящее время не используется.");
default:
throw new IllegalArgumentException("Sound: " +
"недопустимое значение параметра type.");
}
}
}