/*
* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Base class for modules.
*
*/
package com.nokia.amms;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.Control;
import com.nokia.microedition.media.PlayerImpl;
import com.nokia.microedition.media.NativeError;
import java.util.Vector;
import com.nokia.mj.impl.rt.support.Finalizer;
/**
* Base class for all modules.
*/
public class ModuleBase implements PlayerListener
{
/**
* Player is already in some other module.
*/
private static final int PLAYER_ALREADY_IN_MODULE = -123;
private static final int MIXING_NOT_SUPPORTED = -1234;
/**
* Current implementation does not support midi channels in modules.
*/
private static final String MIDI_CHANNELS_NOT_SUPPORTED =
"Adding MIDI channels is not supported.";
/**
* Contains all controls in the module. Package private.
*/
ControlContainer iControls;
/**
* Handle to native implemantation. Package private.
*/
int iModuleHandle;
/**
* Handle to native event source. Package private.
*/
int iEventSourceHandle;
/**
* Handle to native global mabager. Package private.
* Used to dispose native module.
*/
int iManagerHandle;
/**
* Java-side players. Package private.
*/
Vector iPlayers = new Vector();
private Finalizer mFinalizer;
/**
* Constructs new Module base. Package private.
* Module is registered for the finalization.
*
* @param aEventSourceHandle Handle to event source.
* @param aModuleHandle Handle to corresponding native object.
* @param aManagerHandle Handle to native global manager.
* @param aMana
*/
ModuleBase(int aEventSourceHandle,
int aModuleHandle,
int aManagerHandle)
{
// registeredFinalize() method is called when this class is finalized.
mFinalizer = new Finalizer()
{
public void finalizeImpl()
{
doFinalize();
}
};
iManagerHandle = aManagerHandle;
init(aEventSourceHandle,
aModuleHandle);
}
/**
* Constructs new Module base. Package private.
* Module is not registered for the finalization.
*/
ModuleBase()
{
}
/**
* Initialises module base. This method must be called before module can be
* used. Package private.
*
* @param aEventSourceHandle Handle to event source.
* @param aModuleHandle Handle to corresponding native object.
*/
final void init(int aEventSourceHandle,
int aModuleHandle)
{
iEventSourceHandle = aEventSourceHandle;
iModuleHandle = aModuleHandle;
iControls = ControlContainer.populateControls(
iEventSourceHandle,
iModuleHandle,
this);
}
private void doFinalize()
{
if (mFinalizer != null)
{
registeredFinalize();
mFinalizer = null;
}
}
/**
* This method is called when garbage collector finalizes this object.
*/
void registeredFinalize()
{
iControls.invalidateControls();
_dispose(iManagerHandle,
iModuleHandle);
}
/**
* <p>Adds an individual MIDI channel of a MIDI <code>Player</code>
* to the module.</p>
*
* <p>If the played MIDI file or MIDI stream contains information
* that is contradictory
* to what is specified via this <code>Module</code> the behavior
* will be implementation specific.</p>
*
* @param player The MIDI <code>Player</code> whose channel is to be added.
* @param channel The channel of the given <code>Player</code> to be added.
* The range is 0-15.
*
* @throws MediaException if adding of channels is not supported.
* @throws IllegalArgumentException if the <code>player</code> is not a MIDI player or the <code>player</code> is null
* or if the <code>player</code> is already part of the module.
* @throws IllegalArgumentException if <code>channel</code> > 15 or <code>channel</code> < 0.
* @throws IllegalStateException if some <code>Player</code>
* in the <code>Module</code> tree is not in
* <code>UNREALIZED</code> or <code>REALIZED</code> state.
*/
public void addMIDIChannel(Player aPlayer, int aChannel)
throws MediaException
{
// Midi channels are not supported modules.
throw new MediaException(MIDI_CHANNELS_NOT_SUPPORTED);
}
/**
* Removes a MIDI channel from the module.
*
* All channels can be removed at once by {@link #removePlayer removePlayer}
*
* @param player The MIDI <code>Player</code> whose channel is to be removed.
* @param channel The channel of the given MIDI <code>Player</code>
* to be removed.
* @throws IllegalArgumentException if the given <code>channel</code> is
* not part of the <code>Module</code> or if the <code>player</code> is null.
* @throws IllegalStateException if some <code>Player</code>
* in the <code>Module</code> tree is not in
* <code>UNREALIZED</code> or <code>REALIZED</code> state
*/
public void removeMIDIChannel(Player aPlayer, int aChannel)
{
// Midi channels are not supported modules.
throw new IllegalArgumentException(MIDI_CHANNELS_NOT_SUPPORTED);
}
/**
* Adds a <code>Player</code> to the module.
* @param player The <code>Player</code> to be added.
* @throws IllegalArgumentException if the <code>player</code> is null or
* if the <code>player</code> or some channels of
* the <code>player</code> already belong to the module.
* @throws MediaException if the <code>player</code> cannot be added.
* @throws IllegalStateException if some <code>Player</code>
* in the <code>Module</code> tree is not in
* <code>UNREALIZED</code> or <code>REALIZED</code> state.
*/
public void addPlayer(Player aPlayer) throws MediaException
{
if (aPlayer == null)
{
throw new IllegalArgumentException("Player is null.");
}
if (!(aPlayer instanceof PlayerImpl))
{
throw new MediaException("Player is not supported.");
}
// It is not reasonable to add a player that is in CLOSED state.
if (aPlayer.getState() == Player.CLOSED)
{
throw new IllegalStateException("Cannot add Player while it is in CLOSED state.");
}
int playerHandle = ((PlayerImpl)aPlayer).getPlayerHandle();
int err = _addPlayer(iEventSourceHandle,
iModuleHandle,
playerHandle);
// Throw IllegalArgumentException if the player or some channels of
// the player already belong to the module.
if (err == NativeError.KErrArgument)
{
throw new IllegalArgumentException("Player already belongs to the module.");
}
// Throw IllegalStateException if some Player in the Module
// (or the player to be added) is in PREFETCHED or STARTED state
if (err == NativeError.KErrNotReady)
{
throw new IllegalStateException("Cannot Add Player while any player in the module is in PREFETCHED or STARTED state");
}
// Throw MediaException if the player already exists in some
// other module.
if (err == PLAYER_ALREADY_IN_MODULE)
{
throw new MediaException("Player already in other module.");
}
// Throw MediaException if audio mixing is not supported (emulator).
if (err == MIXING_NOT_SUPPORTED)
{
throw new MediaException("Mixing is not supported in emulator.");
}
// Throw MediaException if the player cannot be added.
if (err < 0)
{
throw new MediaException(NativeError.errorMessage(err));
}
iPlayers.addElement(aPlayer);
aPlayer.addPlayerListener(this);
}
/**
* Removes a <code>Player</code> or all channels of a <code>Player</code>
* from the module.
* @param player The <code>Player</code> to be removed.
* @throws IllegalArgumentException if <code>player</code> is not part of
* the
* module or if <code>player</code> is null.
* @throws IllegalStateException if some <code>Player</code>
* in the <code>Module</code> tree is not in
* <code>UNREALIZED</code> or <code>REALIZED</code> state.
*/
public void removePlayer(Player aPlayer)
{
// Throw IllegalArgumentException if the player is null, incorrect
// type, or does not belong to the module.
if (aPlayer == null)
{
throw new IllegalArgumentException("Player is null.");
}
if (!(aPlayer instanceof PlayerImpl))
{
throw new IllegalArgumentException("Not supported player.");
}
// If the player is in CLOSED state, the native side player is
// already removed and destroyed.
if (aPlayer.getState() != Player.CLOSED)
{
// The player list does not contain CLOSED players, thus do not
// check the existence for these players.
if (!iPlayers.contains(aPlayer))
{
throw new IllegalArgumentException(
"Player does not belong to the module.");
}
int playerHandle = ((PlayerImpl)aPlayer).getPlayerHandle();
int err = _removePlayer(iEventSourceHandle,
iModuleHandle,
playerHandle);
if (err == NativeError.KErrNotReady)
{
throw new IllegalStateException(
"Cannot remove Player while any player in the module is in PREFETCHED or STARTED state");
}
NativeError.check(err);
aPlayer.removePlayerListener(this);
}
iPlayers.removeElement(aPlayer);
}
/**
* Obtain the object that implements the specified Control interface.
*
* @see javax.microedition.media.Controllable
* @param aControlType the class name of the Control. The class name should
* be given either as the fully-qualified name of the class; or if the
* package of the class is not given, the package
* javax.microedition.media.control is assumed.
* @return the object that implements the control, or null.
*/
public Control getControl(String aControlType)
{
// Delegate to ControlContainer
return iControls.getControl(aControlType);
}
/**
* Obtain the collection of Controls.
*
* @see javax.microedition.media.Controllable
* @return the collection of Control objects.
*/
public Control[] getControls()
{
// Delegate to ControlContainer
return iControls.getControls();
}
/**
* From PlayerListener.
*/
public void playerUpdate(Player aPlayer, String aEvent, Object aEventData)
{
// Remove the player from the vector in order to allow
// the garbage collector to dispose the player.
if (aEvent == PlayerListener.CLOSED)
{
iPlayers.removeElement(aPlayer);
}
}
/**
* Removes a Player from module.
* (The function is protected to allow inherited modules to remove
* CLOSED players which is not possible by removePlayer() function).
*
* @param aEventSourceHandle Handle to native event source.
* @param aModuleHandle Handle to native module object.
* @param aPlayerHandle Handle to native player object.
* @return Negative value if player does not exist in the module.
*/
static native protected int _removePlayer(int aEventSourceHandle,
int aModuleHandle,
int aPlayerHandle);
/**
* Adds a Player to module.
*
* @param aEventSourceHandle Handle to native event source.
* @param aModuleHandle Handle to native module object.
* @param aPlayerHandle Handle to native player object.
* @return Error code
*/
static native private int _addPlayer(int aEventSourceHandle,
int aModuleHandle,
int aPlayerHandle);
/**
* Disposes native module.
*
* @param aManagerHandle Handle to native global manager.
* @param aModuleHandle Handle to native module object.
*/
static native private void _dispose(int aManagerHandle,
int aModuleHandle);
}