/**
* FMRadioDemoPlayer.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings. However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies. For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/
package com.rim.samples.device.fmradiodemo;
import java.io.IOException;
import javax.microedition.amms.control.tuner.RDSControl;
import javax.microedition.amms.control.tuner.TunerControl;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.control.VolumeControl;
/**
* A class which interacts with the FM Radio API
*/
public class FMRadioDemoPlayer implements PlayerListener {
private Player _player;
private FmTunerControl _fmTunerControl;
private RDSControl _rdsControl;
private VolumeControl _volumeControl;
private final FMRadioDemoScreen _screen;
private int _rssi = -90;
private int _volume = 50;
/**
* Creates a new FMRadioDemo Player object
*/
public FMRadioDemoPlayer(final FMRadioDemoScreen screen) {
_screen = screen;
// Set up the Player object
createPlayer();
realizePlayer();
prefetchPlayer();
}
/**
* Switches reception for RDS/RBDS on or off
*
* @param on
* True, if the reception for RDS/RBDS should be switched on;
* false, if reception should be switched off.
*/
public void switchRbds(final boolean on) {
final int state = _player.getState();
if (_fmTunerControl != null
&& (state == Player.STARTED || state == Player.PREFETCHED)) {
try {
_fmTunerControl.setRdsRbdsReceptionEnabled(on);
} catch (final MediaException m) {
FMRadioDemo.errorDialog("MediaException on switching RDBS:"
+ m.getMessage());
}
}
}
/**
* Takes the startFrequency as a basis, adds/subtracts an offset of 200kHz
* and seeks in the specified direction (up->higher frequencies / down ->
* lower frequencies) until a new station is found.
*
* @param startFrequency
* The frequency to start searching from.
* @param directionUp
* The direction to in which to seek: true, seek in upward
* direction; false, seek in downward direction
*
*/
public void seek(final int startFrequency, final boolean directionUp) {
if (_player != null && _fmTunerControl != null
&& checkFrequencyInRange(startFrequency)) {
// Add an offset to <code>startfrequency</code> to move off
// currently tuned frequency
final int fr = startFrequency + (directionUp ? 2000 : -2000);
int found = 0;
try {
// Start a seek in the given direction with the current RSSI
// value
found = _fmTunerControl.seek(fr, directionUp, _rssi)[0];
if (found == 0) // This happens if no station is found and seek
// times out after 5 seconds
{
_screen.updateLog("seek failed: f=" + fr);
_fmTunerControl.setMute(false); // Seek without station
// stays muted
tuneTo(startFrequency); // Tune back to previous frequency
}
} catch (final MediaException e) {
// No station found, tune to previous frequency
tuneTo(startFrequency);
try {
_fmTunerControl.setMute(false); // Seek without station
// stays muted
} catch (final MediaException e1) {
FMRadioDemo
.errorDialog("MediaException while seeking and trying to mute:"
+ e1.getMessage());
}
}
}
}
/**
* Tunes the radio to a given frequency. The frequency can only be set if it
* is within the band limits of the given locale.
*
* @param frequency
* The frequency to tune the radio to in 100Hz
*/
public void tuneTo(final int frequency) {
if (_player != null && _fmTunerControl != null) {
if (checkFrequencyInRange(frequency)) {
_fmTunerControl.setFrequency(frequency,
TunerControl.MODULATION_FM);
}
}
}
/**
* Utility method to check if a given frequency value is in the range of the
* current locale's band limits.
*
* @param frequency
* The frequency for which to check validity
* @return True, if the given frequency is within the currently supported
* band limits; false, otherwise.
*/
public boolean checkFrequencyInRange(final int frequency) {
if (_player != null && _fmTunerControl != null) {
final int min =
_fmTunerControl.getMinFreq(TunerControl.MODULATION_FM);
final int max =
_fmTunerControl.getMaxFreq(TunerControl.MODULATION_FM);
return frequency >= min && frequency <= max;
}
return false;
}
/**
* Get the currently tuned frequency from the tuner
*
* @return The frequency the tuner is set to in 100Hz or -1 if the
* Player/FmTunerControl is null
*/
public int getFrequency() {
if (_player != null && _fmTunerControl != null) {
return _fmTunerControl.getFrequency();
}
return -1;
}
/**
* Returns the station name identified via RDS/RBDS
*
* @return The station name decoded via RDS/RBDS or the String "NO RDS" if
* RDS is not used
*/
public String getRdsPS() {
if (_rdsControl != null) {
return _rdsControl.getPS();
}
return "NO RDS";
}
/**
* Gets the decoded group type as String for the current station. This works
* only if the radio plays back from that station and RDS is turned on.
*
* @return The genre String as defined in the RDS/RBDS standard for the RDS
* group type
*/
public String getRdsPty() {
if (_rdsControl != null) {
return _rdsControl.getPTYString(true);
}
return "NO RDS!";
}
/**
* Creates a player for FM radio playback
*/
public void createPlayer() {
try {
_player = Manager.createPlayer("capture://radio");
_player.addPlayerListener(this);
} catch (final IOException e) {
FMRadioDemo.errorDialog("IOException on createPlayer: "
+ e.getMessage());
closePlayer();
} catch (final SecurityException e) {
FMRadioDemo.errorDialog("SecurityException on createPlayer: "
+ e.getMessage());
closePlayer();
} catch (final MediaException m) {
FMRadioDemo.errorDialog("MediaException on createPlayer: "
+ m.getMessage());
closePlayer();
}
}
/**
* Realizes the player for FM radio playback. The player needs to be in
* Player.UNREALIZED state. This call also instantiates an FmTunerControl
* and an RDSControl.
*/
public void realizePlayer() {
if (_player != null) {
if (_player.getState() == Player.UNREALIZED) {
try {
_player.realize();
_fmTunerControl =
(FmTunerControl) _player.getControl("TunerControl");
_rdsControl = (RDSControl) _player.getControl("RDSControl");
} catch (final MediaException m) {
FMRadioDemo.errorDialog("MediaException on realizePlayer: "
+ m.getMessage());
closePlayer();
}
}
}
}
/**
* Prefetches the Player. The Player needs to be in the Player.REALIZED
* state before calling the method.
*/
public void prefetchPlayer() {
if (_player != null) {
if (_player.getState() == Player.REALIZED) {
try {
_player.prefetch();
} catch (final MediaException m) {
FMRadioDemo
.errorDialog("MediaException on prefetchPlayer: "
+ m.getMessage());
closePlayer();
}
}
}
}
/**
* Starts the Player. The Player needs to be in Player.PREFETCHED state.
*/
public void startPlayer() {
if (_player != null) {
if (_player.getState() == Player.PREFETCHED) {
try {
tuneTo(_screen.getFrequency());
_player.start();
_volumeControl =
(VolumeControl) _player
.getControl("javax.microedition.media.control.VolumeControl");
setVolume();
} catch (final MediaException m) {
FMRadioDemo.errorDialog("MediaException on startPlayer: "
+ m.getMessage());
closePlayer();
}
}
}
}
/**
* Stops the Player. The Player needs to be in the Player.STARTED state.
*/
public void stopPlayer() {
if (_player != null) {
if (_player.getState() == Player.STARTED) {
try {
_player.stop();
} catch (final MediaException m) {
FMRadioDemo.errorDialog("MediaException on stopPlayer: "
+ m.getMessage());
closePlayer();
}
}
}
}
/**
* Closes the Player
*/
public void closePlayer() {
_player.close();
}
/**
* Increases the volume
*/
public void increaseVolume() {
if (_volume < 100) {
_volume += 10;
setVolume();
}
}
/**
* Decreases the volume
*/
public void decreaseVolume() {
if (_volume > 0) {
_volume -= 10;
setVolume();
}
}
/**
* Sets the current volume
*/
private void setVolume() {
if (_player != null) {
if (_volumeControl != null) {
_volumeControl.setLevel(_volume);
}
}
}
/**
* @see javax.microedition.media.PlayerListener#playerUpdate(Player, String,
* Object)
*/
public void playerUpdate(final Player player, final String event,
final Object eventData) {
if (player != _player) {
return;
}
_screen.updateLog("playerUpdate() event = " + event);
if (event == PlayerListener.STARTED
&& _player.getState() != Player.STARTED) {
_screen.updateLog("playerUpdate() event = " + event
+ ", eventData = " + eventData);
} else if (event.equals(PlayerListener.STOPPED)) {
_screen.updateLog("playerUpdate() event = STOPPED, eventData = "
+ eventData);
} else if (event.equals(PlayerListener.DEVICE_UNAVAILABLE)) {
final int status = _player.getState();
if (status == Player.STARTED) {
_screen.updateLog("FMRadio: playerUpdate() event = DEVICE_UNAVAILABLE, eventData = "
+ eventData);
}
} else if (event.equals(PlayerListener.DEVICE_AVAILABLE)) {
_screen.updateLog("FMRadio: playerUpdate() event = DEVICE_AVAILABLE");
} else if (event.equals(RDSControl.RDS_NEW_DATA) && eventData != null) {
_screen.updateRDS();
_screen.updateLog("FMRadio: playerUpdate() event = RDS_NEW_DATA");
} else if (event.equals(PlayerListener.ERROR)) {
// This happens if the device is switched off while playing back
_screen.updateLog("FMRadio: playerUpdate() event = ERROR, eventData = "
+ eventData);
}
}
/**
* Gets the current RSSI value as String for representation in a Field
*
* @return The current RSSI value as String
*/
public String getRSSI() {
return Integer.toString(_rssi);
}
/**
* Increases the RSSI value by one
*/
public void increaseRSSI() {
_rssi++;
}
/**
* Decreases the RSSI value by one
*/
public void decreaseRSSI() {
_rssi--;
}
/**
* Gets the current Player state
*
* @return The player state as defined in the Player interface as one of:
* UNREALIZED, REALIZED, PREFETCHED, STARTED, CLOSED, or -1 if the
* Player is null
*/
public int getPlayerState() {
if (_player != null) {
return _player.getState();
}
return -1;
}
}