Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Audio stream does not work the 2nd time

Hi guys,

 

I have an issue, I've built a music player. Everything works fine except for the fact that after I create the stream and play the first song, I try to set the stream to null and play another song. It doesn't download the 2nd song, the following code works fine in the simulator but not on the actual device. I think it is somehting to do with the ram being used up or the stream not being closed properly.

 

Here is the code,

 

 

package pyxle.phizuu.music;

import java.io.IOException;
import java.util.Timer;

import javax.microedition.media.Control;
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.GUIControl;
import javax.microedition.media.control.VolumeControl;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;


import net.rim.blackberry.api.invoke.Invoke;
import net.rim.blackberry.api.invoke.MessageArguments;
import net.rim.blackberry.api.mail.Address;
import net.rim.blackberry.api.mail.AddressException;
import net.rim.blackberry.api.mail.Folder;
import net.rim.blackberry.api.mail.Message;
import net.rim.blackberry.api.mail.MessagingException;
import net.rim.blackberry.api.mail.Session;
import net.rim.blackberry.api.mail.Store;
import net.rim.blackberry.api.mail.Transport;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.Display;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.GaugeField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.component.TextField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.PopupScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;
import pyxle.phizuu.*;
/**
* Provides a GUI interface for buffered media playback from a remotely
* streamed source.
*/
public final class BufferedPlayback extends MainScreen implements FieldChangeListener, PlayerListener
{

public static final long MICRO_SECONDS = 1000000;

/** A field used to enter the URL of the remote media file. */
private BasicEditField _urlField;

/** A field used to enter the MIME type of the remote media file. */
private String _mimeField;

/**
* A field used to display the number of bytes that have been loaded.
*/
private LabelField _loadStatusField;

/** A field used to display the current status of the media player. */
private TextField _playStatusField;

/**
* A field which contains the minimum number of bytes that must be
* buffered before the media file will begin playing.
*/
private int _startBufferField;

/**
* A field which contains the minimum forward byte buffer which
* must be maintained in order for the video to keep playing. If
* the forward buffer falls below this number, the playback will
* pause until the buffer increases.
*/
private int _pauseBytesField;

/**
* A field which contains the minimum forward byte buffer required
* to resume playback after a pause.
*/
private int _resumeBytesField;

/** A field which contains the maximum byte size of a single read. */
private int _readLimitField;

/** A button which starts the HTTP request and media playback. */
private PictureBackgroundButtonField _startPlayingButton;

/** A button which stops the HTTP request and media playback. */
private PictureBackgroundButtonField _stopPlayingButton;

/** A button which erases current request and playback progress. */
//private PictureBackgroundButtonField _resetField;

private PictureBackgroundButtonField _moveNextPlayingButton;

private PictureBackgroundButtonField _movePrevPlayingButton;

private ButtonField btnNextTrack;

private ButtonField btnPreviousTrack;

/** A stream for the resource we are retrieving. */
private LimitedRateStreamingSource _source;

/** A player for the media stream. */
private Player _player;

/** A thread which creates and starts the Player. */
private PlayerThread _playerThread;

private PlayerTimeThread mediaPlayerTime;

private VerticalFieldManager _progressBarHFM;

private HorizontalFieldManager albumArtContainer;

private VerticalFieldManager _mainContainer;

private Field _albumArt;

private GaugeField bufferDownloadBar=null;

private GaugeField timeLine=null;

private JSONArray trackDetails;

private String trackTitle;

private LabelField lbltrackName;

private JSONObject currTrack;

private JSONObject prevTrack;

private JSONObject nextTrack;

private String songURI;

private double totalDuration;

private double playerCurrentTime;

private boolean stopPlayerTime;

private VolumeControl _volumeControl;


//private PictureBackgroundButtonField picture;

private LabelField _moreInfo;

private Bitmap _defaultImage = Bitmap.getBitmapResource("img/default-cover.png");
private BitmapField _bitmapDefault = new BitmapField();
/**
* Constructor, creates the GUI.
*/

public BufferedPlayback(JSONObject currTrack, JSONArray trackDetails)
{

setCurrTrack(currTrack);
this.trackDetails = trackDetails;

Background bg = BackgroundFactory.createSolidBackground(Color.BLACK);
VerticalFieldManager temp = (VerticalFieldManager) getMainManager();
temp.setBackground(bg);

_bitmapDefault.setBitmap(_defaultImage);
//_albumArt = _bitmapDefault;

LabelField lblTitle = null;
try {
lblTitle = new LabelField(currTrack.get("title").toString(),LabelField.HCENTER | LabelField.USE_ALL_WIDTH){
public void paint(Graphics g){
g.setBackgroundColor(Color.BLACK);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.WHITE);
g.clear();
super.paint(g);
}
};
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

setTitle(lblTitle);

lbltrackName = new LabelField(trackTitle, lbltrackName.FIELD_HCENTER);

_mainContainer = new VerticalFieldManager(HorizontalFieldManager.FIELD_HCENTER);
_progressBarHFM = new VerticalFieldManager(HorizontalFieldManager.FIELD_HCENTER);
albumArtContainer = new HorizontalFieldManager(HorizontalFieldManager.FIELD_HCENTER);

initialiseJSONStream(currTrack);

//Create and add the field for the URL to be retrieved.
// albumArtContainer.add(_albumArt);

//Create and add the field for the MIME type of the remote file.
_mimeField = "audio/mpg";
//add(_mimeField);

bufferDownloadBar = new GaugeField(null,0,100,0, GaugeField.NO_TEXT) {

protected void paint (Graphics g)
{
g.drawBitmap(getValue()*4, 0, 100, 10, Bitmap.getBitmapResource("img/Arrow_Down.png"), 0, 0);
}
protected void layout(int width,int height){
setExtent(400,10);
}
};
_loadStatusField = new LabelField("0");

timeLine = new GaugeField(null,0,100,0,GaugeField.FIELD_VCENTER | GaugeField.NO_TEXT) {
protected void paint (Graphics g)
{
g.drawBitmap(0, 0, 400, 15, Bitmap.getBitmapResource("img/bar.png"), 0, 0);
g.setColor(Color.SILVER);
g.setBackgroundColor(Color.SILVER);
super.paint(g);
}
protected void layout(int width,int height){
setExtent(400,15);
}
};

_progressBarHFM.add(bufferDownloadBar);
_progressBarHFM.add(timeLine);

_moreInfo = new LabelField("more info",0, -1, Field.FIELD_RIGHT | LabelField.FOCUSABLE | LabelField.HIGHLIGHT_SELECT){
};

//Create the START, STOP and RESET buttons.

_startPlayingButton = new PictureBackgroundButtonField
("", ButtonField.CONSUME_CLICK | Field.FOCUSABLE,40,40,"img/playHightlight.png","img/play.png");
_stopPlayingButton = new PictureBackgroundButtonField
("", ButtonField.CONSUME_CLICK | Field.FOCUSABLE,40,40,"img/pausehighlight.png","img/pause.png");
//_resetField = new PictureBackgroundButtonField("", ButtonField.CONSUME_CLICK | Field.FOCUSABLE,40,40,"img/stopOn.png","img/stop.png");
_movePrevPlayingButton = new PictureBackgroundButtonField
("", ButtonField.CONSUME_CLICK | Field.FOCUSABLE,40,40,"img/backOn.png","img/previous.png");
_moveNextPlayingButton = new PictureBackgroundButtonField
("", ButtonField.CONSUME_CLICK | Field.FOCUSABLE,40,40,"img/nextOn.png","img/next.png");

_startPlayingButton.setChangeListener(this);
_stopPlayingButton.setChangeListener(this);
_movePrevPlayingButton.setChangeListener(this);
_moveNextPlayingButton.setChangeListener(this);


//Add the player control buttons to the screen.
HorizontalFieldManager buttonlist = new HorizontalFieldManager(HorizontalFieldManager.FIELD_HCENTER);

buttonlist.add(_movePrevPlayingButton);
buttonlist.add(_startPlayingButton);
buttonlist.add(_moveNextPlayingButton);


_mainContainer.add(albumArtContainer);
_mainContainer.add(_moreInfo);
_mainContainer.add(_progressBarHFM);
_mainContainer.add(new SeparatorField());
_mainContainer.add(buttonlist);
add(_mainContainer);

albumArtContainer.setBackground(bg);
_progressBarHFM.setBackground(bg);
_mainContainer.setBackground(bg);
buttonlist.setBackground(bg);

//Create and add the field with the load progress.
//add(_loadStatusField);

//Create and add the field with the player status.
_playStatusField = new TextField("Play: ","Stopped", 10, Field.NON_FOCUSABLE);
// add(_playStatusField);
//add(_volumeDisplay);
_startBufferField = 32000;
_pauseBytesField = 64000;
_resumeBytesField = 128000;
_readLimitField = 32000;

}

private JSONObject getNextTrack(){

if (this.getTrackDetails() != null){

JSONArray arr = this.getTrackDetails();

for(int curRecord=0;curRecord<getTrackDetails().length();curRecord++){
try {

JSONObject curr = arr.getJSONObject(curRecord);

if(getCurrTrack().get("title").equals(curr.get("title"))){
if(getTrackDetails().getJSONObject(curRecord + 1 ) != null){
this.nextTrack = getTrackDetails().getJSONObject(curRecord + 1);
}
return nextTrack;
}
}catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return nextTrack;
}


 

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

 

private JSONObject getPreviousTrack(){

		if (this.getTrackDetails() != null){

			JSONArray arr = this.getTrackDetails();

			for(int curRecord=0;curRecord<arr.length();curRecord++){
				try {

					JSONObject curr = arr.getJSONObject(curRecord);

					if(getCurrTrack().get("title").equals(curr.get("title"))){

						if(arr.getJSONObject(curRecord - 1 ) != null){

							this.prevTrack = arr.getJSONObject(curRecord - 1);
						}

						return prevTrack;
					}
				}catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return prevTrack; 
	}
	
	
	 protected boolean keyControl(char c, int status, int time){        		 
		 
	        // Capture volume control key press and adjust volume accordingly.
	        switch( c )
	        {
	            case Characters.CONTROL_VOLUME_DOWN:
	            	if(_volumeControl != null)
	                _volumeControl.setLevel(_volumeControl.getLevel() - 10);          
	                return true;
	                
	            case Characters.CONTROL_VOLUME_UP:
	            	if(_volumeControl != null)
	                _volumeControl.setLevel(_volumeControl.getLevel() + 10);                           
	                return true;
	        }	        
	        return super.keyControl( c, status, time );
	    }    
	    
	    /**
	     * @see javax.microedition.media.PlayerListener#playerUpdate(Player,String,Object)
	     */
	 public void playerUpdate(Player player, final String event, Object eventData)
	 {
		 UiApplication.getUiApplication().invokeLater(new Runnable()
		 {
			 public void run()
			 {
				 if (event.equals(VOLUME_CHANGED))
				 {	                	
					 Dialog.inform(Integer.toString(_volumeControl.getLevel()));
					 //  _volumeDisplay.setText("Volume : " + _volumeControl.getLevel());
				 }                           

			 }           
		 });
	 }
		
	protected boolean trackwheelRoll(int amount,
            int status,
            int time){
			
			return super.trackwheelRoll(amount, status, time);
	}
	

	public void initialiseJSONStream(JSONObject object){

		try {
			this.trackTitle = object.get("title").toString();
			 lbltrackName.setText(trackTitle);
			 setTitle(lbltrackName);

		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			
			/*if(_bitmapDefault != null){
			albumArtContainer.add(_bitmapDefault);
		}
		
		*/
		JSONObject asd = object.getJSONObject("image");

		if (_albumArt != null){
			albumArtContainer.delete(_albumArt);
		}		
		_albumArt = new WebBitmapField( asd.get("uri").toString().trim() + MainUI.connectionParameters, 205, 480,true,false,false);

		albumArtContainer.add(_albumArt);
		/*
		if(_bitmapDefault != null){
			albumArtContainer.add(_bitmapDefault);
		}*/
						
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 	
		try {
			this.setSongURI(object.getString("stream_uri"));
			System.out.println(object.getString("stream_uri"));
			
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
	
	protected void paint(Graphics graphics) {
		// TODO Auto-generated method stub
		graphics.setBackgroundColor(Color.BLACK);
		super.paint(graphics);
	}

	/**
	 * @return the trackDetails
	 */
	private JSONArray getTrackDetails() {
		return trackDetails;
	}

	/**
	 * @param songURI the songURI to set
	 */
	private void setSongURI(String songURI) {
		this.songURI = songURI;
	}	

	/**
	 * A common listener for all three player controls.
	 * @param field The field that changed.
	 * @param context Information specifying the origin of the change.
	 */
	public void fieldChanged(Field field, int context)
	{
		try
		{
			//If the START button was pressed, begin playback.
			if (field == _startPlayingButton)
			{
				//The player does not exist, we must initialize it.
				if (_player == null)
				{ 
					setPauseButton();
					//Create a stream using the remote file.
					if(_source == null){
						_source = new LimitedRateStreamingSource(getSongURI()+MainUI.connectionParameters);
					}else{
						if (_source != null)
						{
							_source.stop();
							_source.disconnect();
							_source = null;	
							_source = new LimitedRateStreamingSource(getSongURI()+MainUI.connectionParameters);
						}					
					}					
					_source.setContentType(_mimeField);
					_source.setStartBuffer(_startBufferField);
					_source.setReadLimit(_readLimitField);
					_source.setResumeBytes(_resumeBytesField);
					_source.setPauseBytes(_pauseBytesField);
					_source.setLoadStatus(_loadStatusField);
					_source.setPlayStatus(_playStatusField);
					//_source.set_progressStatusField(_progressStatusField);
					_source.setProgressBar1(bufferDownloadBar);
					_source.setTimeLine(timeLine);								
					//Create and run the player's thread.
					_playerThread = new PlayerThread();
					_playerThread.start();
					
				}
				//The player already exists, simply resume it.
				else
				{
					System.out.println(_loadStatusField);
					
					if(_startPlayingButton.get_getValue().equals("Pause")){
						
						if((Integer.parseInt(_loadStatusField.getText()) < 150000) || (Integer.parseInt(_loadStatusField.getText()) == 0) ){
							
							Dialog.alert("Initialising, Please Wait");
						}else{
							try {								
								_player.stop();
								setStartButton();
							} catch (MediaException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}	
						}						
					}else{						
						_player.start();
						setPauseButton();
					}
				}
				
			}else if(field == _movePrevPlayingButton){

				if(Integer.parseInt(_loadStatusField.getText()) < 150000 || Integer.parseInt(_loadStatusField.getText()) == 0){
					Dialog.alert("Initialising, Please Wait");
				}else{
					JSONObject temp = getPreviousTrack();
					if (temp != null) {
						setDefaultButton();
						setCurrTrack(temp);
						destroy();
						initialiseJSONStream(temp);
						_playStatusField.setText("Stopped");		
					}  
				}
			}else if(field == _moveNextPlayingButton){
				if( Integer.parseInt(_loadStatusField.getText()) < 150000 || Integer.parseInt(_loadStatusField.getText()) == 0 ){
					Dialog.alert("Initialising, Please Wait");
				}else{
					setDefaultButton();					
					JSONObject temp = getNextTrack();
					if (temp != null) {					
						setCurrTrack(temp);
						destroy();
						initialiseJSONStream(temp);					
						_playStatusField.setText("Stopped");
					}  
				}
			}
		}
		catch (Exception e)
		{
			System.err.println(e.getMessage());
		}
	}
	
	public void setPauseButton(){
		_startPlayingButton.set_onPicture(Bitmap.getBitmapResource("img/pausehighlight.png"));
		_startPlayingButton.set_offPicture(Bitmap.getBitmapResource("img/pause.png"));
		_startPlayingButton.reDraw();
		_startPlayingButton.set_getValue("Pause");
	}
	
	public void setStartButton(){
		_startPlayingButton.set_onPicture(Bitmap.getBitmapResource("img/playHightlight.png"));
		_startPlayingButton.set_offPicture(Bitmap.getBitmapResource("img/play.png"));
		_startPlayingButton.reDraw();
		_startPlayingButton.set_getValue("Start");
	}
	
	public void setDefaultButton(){
		_startPlayingButton.set_onPicture(Bitmap.getBitmapResource("img/playHightlight.png"));
		_startPlayingButton.set_offPicture(Bitmap.getBitmapResource("img/play.png"));
		_startPlayingButton.reDrawOff();
		_startPlayingButton.set_getValue("Start");		
	}
	
	

	protected boolean trackwheelClick(int status, int time) {
		if(_moreInfo.isFocus()){
			MoreInfoPopupScreen sc = new MoreInfoPopupScreen(currTrack);
			UiApplication.getUiApplication().pushScreen(sc);
			return true;
		}

		return super.trackwheelClick(status, time);
	}
	
	
	public void close()
	{
		try
		{
			setDefaultButton();
			//Destroy the Player and streams.
			if (_player != null)
			{
				if(Integer.parseInt(_loadStatusField.getText()) < 150000 || Integer.parseInt(_loadStatusField.getText()) == 0 ){
		
				}else{
				_player.stop();
				}
				stopTimeThread();
				_player = null;				
			}
			//Destroy the stream.
			if (_source != null)
			{
				_source.stop();
				_source.disconnect();
				_source = null;				
			}
		}catch (Exception e)
		{
			System.out.println(e.getMessage());
		}finally{
			super.close();
		}		
	}

	/**
	 * Prevent the save dialog from being displayed.
	 * @see net.rim.device.api.ui.container.MainScreen#onSavePrompt()
	 */
	public boolean onSavePrompt()
	{
		return true;
	}

	/**
	 * Destroy the Player and streams.
	 * @throws Exception
	 */
	public void destroy() throws Exception
	{		
			
		//Destroy the player.
		if (_player != null)
		{
			try {
				timeLine.setValue(0);
				bufferDownloadBar.setValue(0);
				stopTimeThread();
				_player.close();
				_player = null;
			}catch(Exception e){				
				System.out.println(e.getMessage());
			}
		}
		//Destroy the stream.
		if (_source != null)
		{
			try {
				_source.stop();
				_source.disconnect();
				_source = null;

			}catch(Exception e){
				System.out.println(e.getMessage());
			}
		}
	}
	/**
	 * @return the songURI
	 */
	private String getSongURI() {
		return songURI;
	}
	
	public VolumeControl getVolumeControl(Player pl)
    {
        Control[] m_controls = _player.getControls();
       
        int len = m_controls.length;
       
        for (int i = 0; i < len; i++){
            if (m_controls[i] instanceof VolumeControl)
                return (VolumeControl) m_controls[i];
        }
       
        return (VolumeControl) null;
    }
	

	public void setTotalDuration(double totalDuration) {
		this.totalDuration = totalDuration;
	}

	public double getTotalDuration() {
		return totalDuration;
	}


	public void setPlayerTime(double playerTime) {
		this.playerCurrentTime = playerTime;
	}

	public double getPlayerTime() {
		return playerCurrentTime;
	}
	
	
	private void stopTimeThread(){
		setStopPlayerTime(true);
	}	
	
	/**
	 * @param stopPlayerTime the stopPlayerTime to set
	 */
	private void setStopPlayerTime(boolean stopPlayerTime) {
		this.stopPlayerTime = stopPlayerTime;
	}

	/**
	 * @return the stopPlayerTime
	 */
	private boolean isStopPlayerTime() {
		return stopPlayerTime;
	}

	public void setCurrTrack(JSONObject currTrack) {
		this.currTrack = currTrack;
	}

	public JSONObject getCurrTrack() {
		return currTrack;
	}

	private class PlayerTimeThread extends Thread{
		public void run()
		{
			try
			{
				totalDuration = (_player.getDuration()/MICRO_SECONDS);
				double temp;
				do {
					if(_player != null ){
						
						if(isStopPlayerTime()){
							return;
						}else{						
							playerCurrentTime = (_player.getMediaTime()/MICRO_SECONDS);
							temp = (playerCurrentTime*100)/totalDuration;
							bufferDownloadBar.setValue((int) temp );
							sleep(500);
						}
					}				
					
				}while ( playerCurrentTime<totalDuration );
				
				return;
			}
			catch (final Exception e)
			{
				System.out.println("Error: " + e.getMessage());
			}

		}
	}
	/**
	 * A thread for the media player.
	 */
	private class PlayerThread extends Thread
	{
		/**
		 * Create and start the player.
		 */
		public void run()
		{
			try{
				_player = Manager.createPlayer(_source);
				_player.start();
			}catch (final Exception e){
				System.out.println("Couldn't start player");
			}
			try{
				_volumeControl = getVolumeControl(_player);
			}catch (final Exception e){
				System.out.println("Volume control");
			}
			try{
				_player.addPlayerListener(BufferedPlayback.this);
			}catch (final Exception e){
				System.out.println("Player listener");
			}
			try{
				setStopPlayerTime(false);
				mediaPlayerTime = new PlayerTimeThread();
				mediaPlayerTime.start();
			}catch (final Exception e){
				System.out.println("player timer error");
			}
			
		}
	}
	
	private MenuItem _sendEmail = new MenuItem("Send as Email", 120, 10) {
		public void run() {
			//ShareSongPopupScreen p = new ShareSongPopupScreen(getCurrTrack());
			//UiApplication.getUiApplication().pushScreen(p);
			String title = "";
			StringBuffer text = new StringBuffer();
			MessageArguments mArgs;
	
			try {
				text.append(currTrack.getString("title") + "-");
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
			try {
				
				if (!!getCurrTrack().getString("album_title").equals("") ){
					title = getCurrTrack().getString("album_title");
					text.append(currTrack.getString("album_title"));
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
					
			mArgs = new MessageArguments				
			(MessageArguments.ARG_NEW,"", title, 
					"Check out this hot track I'm listening to: " + text.toString());
			Invoke.invokeApplication(Invoke.APP_TYPE_MESSAGES, mArgs);			
			
		}
	};	
	
	protected void makeMenu(Menu menu, int instance) 
	{ 		
		menu.add(_sendEmail);		 
	}
	
}

 

 

Developer
Posts: 709
Registered: ‎09-10-2009
My Device: 8520, 8900, 9000, 9300, 9650, 9700, 9780, 9800, 9810, 9900, 9930
My Carrier: Verizon

Re: Audio stream does not work the 2nd time

I didn't read your code. But here is thing. The header of the first song tells the player the amount of data to play and length (in time to play). So, to play the second song, you might have to stop and restart the player. If that doesn't work, you might have to destroy the player and re-create it.

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

[ Edited ]

but it works fine on the simulator. I mean it plays it perfectly, track to track. The moment I put it onto the phone, it doesn't work. I tried debugging, but that gave me no clues either. Is there any of clearing the phone ram? or doing something like garbage collection? I really can't think of anything.

 

 

P.S - all the code isn't there, i didn't have time to post it cause i was going home.

Developer
Posts: 709
Registered: ‎09-10-2009
My Device: 8520, 8900, 9000, 9300, 9650, 9700, 9780, 9800, 9810, 9900, 9930
My Carrier: Verizon

Re: Audio stream does not work the 2nd time

I have no idea why it works on the simulator but not the phone. You might check if the OS version of the phone the same as the one on the simulator.

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

It's slightly different, I think I found the issue. After I play one song and close it(the screen), and move onto the video screen, I can't seem to play any videos from there as well. But if I don't play any song and move straight to the videos section all the videos play fine. So my conclusion is that the music player somehow doesn't release the resources. Any ideas around this?

Developer
Posts: 709
Registered: ‎09-10-2009
My Device: 8520, 8900, 9000, 9300, 9650, 9700, 9780, 9800, 9810, 9900, 9930
My Carrier: Verizon

Re: Audio stream does not work the 2nd time

After every song, you should stop, deallocate. When the next song comes, do a realize again and start. If that does not work, as I said before, you should close the player and re-create it.

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

I have an exception thrown when I try to stop the downloader thread, which I think is the main cause.

 

 

public final class LimitedRateStreamingSource extends DataSource
{
    /** The max size to be read from the stream at one time. */
    private static final int READ_CHUNK = 512; // bytes

    /** A reference to the field which displays the load status. */
    private LabelField _loadStatusField;

    /** A reference to the field which displays the player status. */
    private TextField _playStatusField;

    /**
     * The minimum number of bytes that must be buffered before the media file
     * will begin playing.
     */
    private int _startBuffer = 200000;

    /** The maximum size (in bytes) of a single read. */
    private int _readLimit = 32000;

    /**
     * The minimum forward byte buffer which must be maintained in order for
     * the video to keep playing. If the forward buffer falls below this
     * number, the playback will pause until the buffer increases.
     */
    private int _pauseBytes = 64000;

    /**
     * The minimum forward byte buffer required to resume
     * playback after a pause.
     */
    private int _resumeBytes = 128000;

    /** The stream connection over which media content is passed. */
    private ContentConnection _contentConnection;

    /** An input stream shared between several readers. */
    private SharedInputStream readAhead;

    /** A stream to the buffered resource. */
    private LimitedRateSourceStream _feedToPlayer;

    /** The MIME type of the remote media file. */
    private String _forcedContentType;

    /** A counter for the total number of buffered bytes */
    private volatile int _totalRead;

    /** A flag used to tell the connection thread to stop */
    private volatile boolean _stop = false;

    /**
     * A flag used to indicate that the initial buffering is complete. In
     * other words, that the current buffer is larger than the defined start
     * buffer size.
     */
    private volatile boolean _bufferingComplete = false;

    /** A flag used to indicate that the remote file download is complete. */
    private volatile boolean _downloadComplete = false;

    /** The thread which retrieves the remote media file. */
    private ConnectionThread _loaderThread;

    /** The local save file into which the remote file is written. */
    //private FileConnection _saveFile;

    /** A stream for the local save file. */
    //private OutputStream _saveStream;

	private ProgressField _progressStatusField;

	private GaugeField progressBar1;

	private GaugeField timeLine;

    private long _fileSize=0;
    
    /**
     * Constructor.
     * @param locator The locator that describes the DataSource.
     */
    LimitedRateStreamingSource(String locator)
    {
        super(locator);
    }

    /**
     * Open a connection to the locator.
     * @throws IOException
     */
    public void connect() throws IOException
    {
        //Open the connection to the remote file.
    	_contentConnection = (ContentConnection) Connector.open(getLocator(), Connector.READ_WRITE);
    	
        //Cache a reference to the locator.
        String locator = getLocator();
        
        //Report status.
        System.out.println("Loading: " + locator);
        System.out.println("Size: " + _contentConnection.getLength());

        //The name of the remote file begins after the last forward slash.
        int filenameStart = locator.lastIndexOf('/');

        //The file name ends at the first instance of a semicolon.
        int paramStart = locator.indexOf(';');

        //If there is no semicolon, the file name ends at the end of the line.
        if (paramStart < 0)
        {
            paramStart = locator.length();
        }

        //Extract the file name.
        String filename = locator.substring(filenameStart, paramStart);
        System.out.println("Filename: " + filename);
      
        _fileSize  = _contentConnection.getLength();
	    readAhead = SharedInputStream.getSharedInputStream(_contentConnection.openInputStream());
        _feedToPlayer = new LimitedRateSourceStream(readAhead, _contentConnection.getType());
}

    /**
     * Destroy and close all existing connections.
     */
    public void disconnect() {
    	
        try 
        {   
        	
        	_downloadComplete = true;
        	        	
        	if (readAhead != null)
            {
                 //Close the reader stream.
                 readAhead.close();
                 readAhead = null;   
             }       
             //Close the remote file connection.
             _contentConnection.close();
             //Close the stream to the player.                    
             _feedToPlayer.close();
        }
        catch (IOException e){
            System.err.println(e.getMessage());
            System.err.println("Does not Resets -.-");
        }
    }

    /**
     * Returns the content type of the remote file.
     * @return The content type of the remote file.
     */
    public String getContentType()
    {
        return _feedToPlayer.getContentDescriptor().getContentType();
    }

    /**
     * Returns a stream to the buffered resource.
     * @return A stream to the buffered resource.
     */
    public SourceStream[] getStreams()
    {
        return new SourceStream[] { _feedToPlayer };
    }

    /**
     * Starts the connection thread used to download the remote file.
     */
    public void start() throws IOException
    {
    	_loaderThread = new ConnectionThread();
    	_loaderThread.start();

    }
    /**
     * Stop the connection thread.
     */
    public void stop() throws IOException
    {
        //Set the boolean flag to stop the thread.
        _stop = true;
    }

    /**
     * @see javax.microedition.media.Controllable#getControl(String)
     */
    public Control getControl(String controlType)
    {
        // No implemented Controls.
        return null;
    }

    /**
     * @see javax.microedition.media.Controllable#getControls()
     */
    public Control[] getControls()
    {
        // No implemented Controls.
        return null;
    }

    /**
     * Force the lower level stream to a given content type. Must be called
     * before the connect function in order to work.
     * @param contentType The content type to use.
     */
    void setContentType(String contentType)
    {
        _forcedContentType = contentType;
    }

    /**
     * A stream to the buffered media resource.
     */
    private final class LimitedRateSourceStream implements SourceStream
    {
        /** A stream to the local copy of the remote resource. */
        private SharedInputStream _baseSharedStream;

        /** Describes the content type of the media file. */
        private ContentDescriptor _contentDescriptor;

        /**
         * Constructor. Creates a LimitedRateSourceStream from
         * the given InputStream.
         * @param inputStream The input stream used to create a new reader.
         * @param contentType The content type of the remote file.
         */
        LimitedRateSourceStream(InputStream inputStream, String contentType)
        {
            _baseSharedStream = SharedInputStream.getSharedInputStream(inputStream);
            _contentDescriptor = new ContentDescriptor(contentType);
        }

 

 

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

 

public ContentDescriptor getContentDescriptor()
        {
            return _contentDescriptor;
        }

        /**
         * Returns the length provided by the connection.
         * @return long The length provided by the connection.
         */
        public long getContentLength()
        {
            return _contentConnection.getLength();
        }

        /**
         * Returns the seek type of the stream.
         */
        public int getSeekType()
        {
            return SEEKABLE_TO_START;
        }

        /**
         * Returns the maximum size (in bytes) of a single read.
         */
        public int getTransferSize() 
        {
            return _readLimit;
        }

        /**
         * Writes bytes from the buffer into a byte array for playback.
         * @param bytes The buffer into which the data is read.
         * @param off The start offset in array b at which the data is written.
         * @param len The maximum number of bytes to read.
         * @return the total number of bytes read into the buffer, or -1 if
         * there is no more data because the end of the stream has been reached.
         * @throws IOException 
         */
        public int read(byte[] bytes, int off, int len) throws IOException
        {
        	System.out.println("Read Request for: " + len + " bytes");

        	//Limit bytes read to our readLimit.
        	int readLength = len;
        	if (readLength > getReadLimit())
        	{
        		readLength = getReadLimit();
        	}

        	//The number of available byes in the buffer.
        	int available;

        	//A boolean flag indicating that the thread should pause
        	//until the buffer has increased sufficiently.
        	boolean paused = false;

        	while(true)
        	{

        		available = _baseSharedStream.available();

        		if (_downloadComplete)
        		{
        			//Ignore all restrictions if downloading is complete.
        			System.out.println("Complete, Reading: " + len + " - Available: " + available);
        			return -1;
        		}
        		else if(_bufferingComplete)
        		{
        			if (paused && available > getResumeBytes())
        			{                       
        				System.out.println("Resuming - Available: " + available);                       
        				paused = false;
        				System.out.println("LimitedRateSourceStream --");
        				return _baseSharedStream.read(bytes, off, readLength);
        			}
        			else if(!paused && (available > getPauseBytes() || available > readLength))
        			{
        				if (available < getPauseBytes())
        				{
        					paused = true;
        					updatePlayStatus("Pausing " + available + " Bytes");
        				}
        				System.out.println("Reading: " + readLength + " - Available: " + available);

        				System.out.println("LimitedRateSourceStream +");

        				return _baseSharedStream.read(bytes, off, readLength);
        			}
        			else if(!paused)
        			{
        				paused = true;
        				System.out.println("Paused");
        			}                                      
        			System.out.println("LimitedRateSourceStream ++");
        		}
        		else
        		{
        			try
        			{
        				Thread.sleep(500);
        			}
        			catch (Exception e)
        			{
        				System.err.println(e.getMessage());
        			}
        		}
        	}
        }

        /**
         * @see javax.microedition.media.protocol.SourceStream#seek(long)
         */
        public long seek(long where) throws IOException
        {
            _baseSharedStream.setCurrentPosition((int) where);
            return _baseSharedStream.getCurrentPosition();
        }

        /**
         * @see javax.microedition.media.protocol.SourceStream#tell()
         */
        public long tell()
        {
            return _baseSharedStream.getCurrentPosition();
        }

        /**
         * Close the stream.
         * @throws IOException
         */
        void close()
        {
            try {
				_baseSharedStream.close();
			} catch (IOException e) {
				System.out.println("error with base shared stream");
				e.printStackTrace();
			}
            
        }

        /**
         * @see javax.microedition.media.Controllable#getControl(String)
         */
        public Control getControl(String controlType)
        {
            // No implemented controls.
            return null;
        }

        /**
         * @see javax.microedition.media.Controllable#getControls()
         */
        public Control[] getControls()
        {
            // No implemented controls.
            return null;
        }
    }

    /**
     * A thread which downloads the remote file and writes it to the local file.
     */
    private final class ConnectionThread extends Thread
    {
        /**
         * Download the remote media file, then write it to the local
         * file.
         * @see java.lang.Thread#run()
         */
        public void run()
        {
            try
            {
                byte[] data = new byte[READ_CHUNK];
                int len = 0;

                //Until we reach the end of the file.
                while (-1 != (len = readAhead.read(data)))
                {
                    _totalRead += len;
                    
                    updateLoadStatus(_totalRead);
                    updateProgressBar(_totalRead);
                    
                    if (!_bufferingComplete && _totalRead > getStartBuffer())
                    {
                        //We have enough of a buffer to begin playback.
                        _bufferingComplete = true;
                        System.out.println("Initial Buffering Complete");                      
                    }
                    if (_stop)
                    {   
                        System.out.println("Thread stoppped");
                    	
                        return;
                    }
                }
             }
            catch (Exception e) {
            	e.printStackTrace();
				System.out.println("Error with regard to media stream - Limited Stream Source"+e.getMessage());				             	
            }
        }
    }
    /**
     * Gets the minimum forward byte buffer which must be maintained in
     * order for the video to keep playing.
     * @return The pause byte buffer.
     */
    int getPauseBytes()
    {
        return _pauseBytes;
    }

    /**
     * Sets the minimum forward buffer which must be maintained in order
     * for the video to keep playing.
     * @param pauseBytes The new pause byte buffer.
     */
    void setPauseBytes(int pauseBytes)
    {
        _pauseBytes = pauseBytes;
    }

    /**
     * Gets the maximum size (in bytes) of a single read.
     * @return The maximum size (in bytes) of a single read.
     */ 
    int getReadLimit()
    {
        return _readLimit;
    }

    /**
     * Sets the maximum size (in bytes) of a single read.
     * @param readLimit The new maximum size (in bytes) of a single read.
     */
    void setReadLimit(int readLimit)
    {
        _readLimit = readLimit;
    }

    /**
     * Gets the minimum forward byte buffer required to resume
     * playback after a pause.
     * @return The resume byte buffer.
     */
    int getResumeBytes()
    {
        return _resumeBytes;
    }

    /**
     * Sets the minimum forward byte buffer required to resume
     * playback after a pause.
     * @param resumeBytes The new resume byte buffer.
     */
    void setResumeBytes(int resumeBytes)
    {
        _resumeBytes = resumeBytes;
    }

    /**
     * Gets the minimum number of bytes that must be buffered before the
     * media file will begin playing.
     * @return The start byte buffer.
     */
    int getStartBuffer()
    {
        return _startBuffer;
    }

    /**
     * Sets the minimum number of bytes that must be buffered before the
     * media file will begin playing.
     * @param startBuffer The new start byte buffer.
     */
    void setStartBuffer(int startBuffer)
    {
        _startBuffer = startBuffer;
    }

    /**
     * Gets a reference to the text field where load status updates
     * are written.
     * @return The load status text field.
     */
    LabelField getLoadStatus()
    {
        return _loadStatusField;
    }

    /**
     * Sets a reference to the text field where load status updates
     * are written.
     * @param statusField The new load status text field.
     */
    void setLoadStatus(LabelField statusField)
    {
        _loadStatusField = statusField;
    }

    /**
     * Gets a reference to the text field where player status
     * updates are written.
     * @return The player status text field.
     */
    TextField getPlayStatus()
    {
        return _playStatusField;
    }

    /**
     * Sets a reference to the text field where player status
     * updates are written.
     * @param playStatus The new player status text field.
     */
    void setPlayStatus(TextField playStatus)
    {
        _playStatusField = playStatus;
    }

    /**
     * Update the player status field.
     * @param text The new message to be displayed.
     */
    void updatePlayStatus(String text)
    {
        updateStatus(getPlayStatus(), text);
    }

    /**
     * Update the load status field.
     * @param text The new message to be displayed.
     */
    void updateLoadStatus(int amount)
    {
    	_loadStatusField.setText(Integer.toString(amount));    	
    }

    /**
     * Update a given status field.
     * @param field The field to be updated.
     * @param text The message to be displayed in the field.
     */
    void updateStatus(TextField field, String text)
    {
        synchronized (UiApplication.getEventLock())
        {
            field.setText(text);
        }
    }
    void updateProgressBar(long value)
    {
    		 long ff = _fileSize;
    		 double temp = ( (value * 100 )/ff) ;
    		 //progressBar1.setValue((int) temp);
    		 timeLine.setValue((int) temp);
    		 //_progressStatusField.moveProgress((int)value);
             
    }
	/**
	 * @param _progressStatusField the _progressStatusField to set
	 */
	public void set_progressStatusField(ProgressField _progressStatusField) {
		this._progressStatusField = _progressStatusField;
	}

	/**
	 * @return the _progressStatusField
	 */
	public ProgressField get_progressStatusField() {
		return _progressStatusField;
	}

	/**
	 * @param progressBar1 the progressBar1 to set
	 */
	public void setProgressBar1(GaugeField progressBar1) {
		this.progressBar1 = progressBar1;
	}

	/**
	 * @return the progressBar1
	 */
	public GaugeField getProgressBar1() {
		return progressBar1;
	}

	/**
	 * @param timeLine the timeLine to set
	 */
	public void setTimeLine(GaugeField timeLine) {
		this.timeLine = timeLine;
	}

	/**
	 * @return the timeLine
	 */
	public GaugeField getTimeLine() {
		return timeLine;
	}

	
	
}

 

 

Developer
Posts: 178
Registered: ‎08-26-2009
My Device: Not Specified

Re: Audio stream does not work the 2nd time

The exception is thrown in the thead "Connection Thread", which I think is the cause.

 

Any ideas? I've tried almost everything.