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

Graphical UI for Audio Streaming

Hi,

 

I'm working on the 4.6 JDE.

 

I have built an audio streaming application which reads a remote MP3 file, but I have manually constructed the UI, that is the play pause stop next previous buttons.Is there a better way of doing this?

 

How do I add a seeker to display the progress of the media file playing, basically the duration and how much of the file has been already been downloaded.

 

 

 

Regards

 

New Developer
Posts: 10
Registered: ‎01-20-2010
My Device: BlackBerry Bold 9000
My Carrier: AT&T

Re: Graphical UI for Audio Streaming

I am doing something similar and would be interested in the answer.

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

Re: Graphical UI for Audio Streaming

Hi ceci,

 

You have to manually build it. You can use the buffered media example to see how the media is streamed, then you can add images as the controls. For the seekbar I used two gauge fields, however I couldn't make it seekable just shows how much is downloaded and the position of the current song. The first gauge field shows the amount that being downloaded, I used to photoshop and created an image that shows the outline of the downloaded amount and then used the gauge field to fill it up dynamically. On top of that was guage field which paints a particular image ontop of the other gauge field. It was a bit of a process. Let me know if you come up with a better solution.

 

 

 

New Developer
Posts: 10
Registered: ‎01-20-2010
My Device: BlackBerry Bold 9000
My Carrier: AT&T

Re: Graphical UI for Audio Streaming

Thank you for your reply.

 

I have gotten the graphical part to work, but am running into difficulties with the players.

 

More details: My UI has a forward, back, and play button (which changes to a pause button

when an mp3 file is playing).  Behind the UI is a Vector containing a list of mp3 file names.

The files are all up on a server.  Whenever the user presses "play," I create a player by

requesting the file from the server.  The user can press "next" at any time and get the next

file in the list, or "back" and hear again the previous file.  When the current file finishes playing,

the next file is retrieved from the server, it becomes current, and it begins playing.

 

The difficulties I'm having are:

 

1. The audios play with a stutter. Every 5 seconds, there is a rough-sounding patch in the audio

or the last syllable repeats several times before the audio resumes playing.

 

2. Short mp3 files play just fine.  Longer ones, usually over a minute, sometimes stop playing

before all the data has been retrieved from the server.  The player never asks for more data, and

the server never sends the end-of-data.

 

3. Because of #2, the application occasionally fails to start the next audio track because the

player listener never gets the end-of-media event.

 

4. Some mp3 files never load at all.  I create the player, but no request is ever sent to the server.

 

Below is the main body of the code that creates the player and starts it playing.

 

import javax.microedition.media.*;
import java.io.IOException;

public class RWTrackPlayer
    implements Runnable, PlayerListener
{
    //
    // Constructor
    //
    
    public RWTrackPlayer(RWTrackInfo track)
    {
        this.track = track;
    }
    
    //
    // PlayerListener interface implementation
    //

    public void playerUpdate(Player thePlayer, String event, Object eventData)
    {
        if (thePlayer != null) {
            StringBuffer buff = new StringBuffer();
            int state = thePlayer.getState();
            String playerState =
                (state == Player.UNREALIZED)
                    ? "Unrealized"
                    : (state == Player.REALIZED)
                        ? "Realized"
                        : (state == Player.PREFETCHED)
                            ? "Prefetched"
                            : (state == Player.STARTED)
                                ? "Started"
                                : (state == Player.CLOSED)
                                    ? "Closed"
                                    : "Unknown";
            buff.append(" player : " + playerState + " \n");
            System.out.println(buff.toString());
        }
        
        if (event == PlayerListener.END_OF_MEDIA) {
            System.out.println("   end of media");
            if (track != null) {
                track.updateHeardState(RWTrackInfo.HEARD);
            }
            // notify calling object that next track can be selected
            dismissPlayer();
        }
    
        else if (event == PlayerListener.ERROR) {
            System.out.println("  ERROR : " + (String)eventData);
            System.out.println(" player : " + player.toString());
        }
    
        else {
            System.out.println("  other : '" + event + "'");
        }
    }
    
    //
    // Runnable implementation
    //
    
    public void start()
    {
        Thread playerThread = new Thread(this);
        playerThread.start();
    }
    
    public void run()
    {
        System.out.println("\t RWTrackPlayer: starting run()");
        invokePlayer();
        System.out.println("\t RWTrackPlayer: ending run()");
    }
    
    private void invokePlayer()
    {
        String trackId = track.getId();
        if (trackId != null) {
            String[] params = { trackId };
            String   cmdUrl = RWCommandManager.getRequestUrl(RWCommandManager.GETAUDIO, params);
            if (cmdUrl != null) {
                cmdUrl = cmdUrl.concat(RWCommandManager.DEVICE_PARAM);  // adds ";deviceside=true"
                try {
                    System.out.println(" creating player for '" + trackId + "'");
                    player = Manager.createPlayer(cmdUrl);
                    player.addPlayerListener(this);
                    player.realize();
                    player.prefetch();
                    player.start();
                }
                catch (MediaException medEx) {
                    System.out.println(" ERROR starting player: '" + medEx.toString() + "'");
                    dismissPlayer();
                }
                catch (IOException ioEx) {
                    System.out.println(" IOExc starting player: '" + ioEx.toString() + "'");
                    
                }
            }
            else {
                dismissPlayer();
            }
        }
        else {
            dismissPlayer();
        }
    }
    
    public void dismissPlayer()
    {
        if (player != null) {
            int state = player.getState();
            // shut the player down in stages, based on its current state
            try {
                if (state == Player.STARTED) {
                    player.stop();
                }
                if (state == Player.PREFETCHED) {
                    player.deallocate();
                }
                if (state == Player.REALIZED || state == Player.UNREALIZED) {
                    player.close();
                }
                player = null;
            }
            catch (MediaException medEx) {
                player = null;
            }
        }
    }

    private Player      player = null;
    private RWTrackInfo track  = null;
}

If any part of this looks wrong to you, please let me know.

 

Thanks,

 

--Lou

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

Re: Graphical UI for Audio Streaming

Take a look at this,

 

http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/1089414/How_To...

 

 

also,

 

Shipped with the JDE is the bufferedplaybackdemo sample application. If you are using eclipse, the path is

 

C:\eclipse\plugins\net.rim.eide.componentpack4.6.1_4.6.1.27\components\samples\com\rim\samples\device

 

 

If you still have a problem, I'll give you my code.

New Developer
Posts: 10
Registered: ‎01-20-2010
My Device: BlackBerry Bold 9000
My Carrier: AT&T

Re: Graphical UI for Audio Streaming

I think I get the gist of it, but a code example would be most appreciated.  I am using

net.rim.eide.componentpack4.5.0_4.5.0.16, which, unfortunately, does not include the

buffereplaybackdemo sample code. 

 

I am surprised the RIM whitepaper seems to recommend downloading the entire data stream,

saving it to an SD card, and then playing the audio by reading it from the local file.  My application

continuously downloads audio files of between 30 seconds and 5 minutes in length, drawn from

multiple sources (pod casts, twitter-to-speech, music samples from Amazon, etc.).  The intent is to

provide a kind of audible ticker of new and interesting stuff, customized to the user's

interests.  If I use the approach recommended in the white paper, I'll be writing and

erasing files on the SD card at a prodigious rate.

Developer
Posts: 70
Registered: ‎11-24-2009
My Device: Not Specified

Re: Graphical UI for Audio Streaming

You dont need to download the file to an SD card for playing.

 

You may want to use SharedInputStream to do the trick for you..and it is available for JDE 4.5 component

Developer
Posts: 638
Registered: ‎07-02-2009
My Device: Not Specified

Re: Graphical UI for Audio Streaming

Hi, i also have the issue to work on... can any one tell me how to play the audio using the bufferedplaybackdemo shipped with the jde. am giving the default audio file taht is with the device to play, i gave the path udner MediaURL:,

but it is throwing the FileSystem error... how to fix this?

 

can i play an audio at remote location, using this demo?

 

now am testing this demo on hte BB curve 8520 model.

 

 

Thanks and Regards,
PraveenGoparaju.
Highlighted
Developer
Posts: 70
Registered: ‎11-24-2009
My Device: Not Specified

Re: Graphical UI for Audio Streaming

we can stream the audio mp3 file using the bufferred playback demo. It wrked for me, although I had to do some changes to make it compatible with 4.5 JDE component.

 

This is what I did to work and was able to stream the mp3 (http)

 

I did not use BufferedPlaybackResource.java and so removed all the calls

 

Also you dont need to write the file anywhere

 

 

BufferedPlayback.java

==================

package com.bufferedplayback;

import javax.microedition.media.Manager;
import javax.microedition.media.Player;

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.TextField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;

public class BufferedPlayback extends UiApplication {

    public BufferedPlayback() {
        BufferedPlaybackScreen screen = new BufferedPlaybackScreen();
        pushScreen(screen);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        BufferedPlayback app = new BufferedPlayback();
        app.enterEventDispatcher();

    }

    private class BufferedPlaybackScreen extends MainScreen implements FieldChangeListener {

        private BasicEditField url;

        private BasicEditField mime;

        private TextField loadStatus;

        private TextField playStatus;

        private BasicEditField startBuffer;

        private BasicEditField pauseBytes;

        private BasicEditField restartBytes;

        private BasicEditField readLimit;

        private ButtonField startplaying;

        private ButtonField stopplaying;

        private ButtonField reset;

        private LimitedRateStreamingSource source;

        private Player player;

        private PlayerThread playerThread;

//        private ResourceBundle _resources = ResourceBundle.getBundle(BufferedPlaybackResource.BUNDLE_ID,
//                BufferedPlaybackResource.BUNDLE_NAME);

        public BufferedPlaybackScreen() {
//            setTitle(_resources.getString(BufferedPlaybackResource.APPLICATION_TITLE));
            setTitle("Buffered Media Player");
//            url = new BasicEditField(_resources.getString(BufferedPlaybackResource.URL), _resources.getString(BufferedPlaybackResource.URL_INIT));
            url = new BasicEditField("Media URL: ","http://www.mfiles.org.uk/downloads/it-came-upon.mp3");
//            startplaying = new ButtonField(_resources.getString(BufferedPlaybackResource.PLAY_BUTTON), ButtonField.CONSUME_CLICK);
            startplaying = new ButtonField("Play", ButtonField.CONSUME_CLICK);
//            stopplaying = new ButtonField(_resources.getString(BufferedPlaybackResource.STOP_BUTTON), ButtonField.CONSUME_CLICK);
            stopplaying = new ButtonField("Stop", ButtonField.CONSUME_CLICK);
//            reset = new ButtonField(_resources.getString(BufferedPlaybackResource.RESET_BUTTON), ButtonField.CONSUME_CLICK);
            reset = new ButtonField("Reset", ButtonField.CONSUME_CLICK);
            startplaying.setChangeListener(this);
            stopplaying.setChangeListener(this);
            reset.setChangeListener(this);
            add(url);

//            mime = new BasicEditField(_resources.getString(BufferedPlaybackResource.MIME_LABEL), _resources
//                    .getString(BufferedPlaybackResource.FORCED_MIME));
            mime = new BasicEditField("Mime: ", "audio/mpeg");
            add(mime);

            // Player control buttons
            HorizontalFieldManager buttonlist = new HorizontalFieldManager();
            buttonlist.add(startplaying);
            buttonlist.add(stopplaying);
            buttonlist.add(reset);
            add(buttonlist);

            loadStatus = new TextField(1024);
            loadStatus.setText("0 Bytes");
            add(loadStatus);
            playStatus = new TextField(1024);
            playStatus.setText("Play: Stopped");
            add(playStatus);

//            startBuffer = new BasicEditField(_resources.getString(BufferedPlaybackResource.START_BUFFER_LABEL), _resources.getString(BufferedPlaybackResource.BUFFER_INIT), 10, BasicEditField.FILTER_INTEGER);
            startBuffer = new BasicEditField("Starting Buffer: ", "10000", 10, BasicEditField.FILTER_INTEGER);
//            pauseBytes = new BasicEditField(_resources.getString(BufferedPlaybackResource.PAUSE_LABEL), _resources.getString(BufferedPlaybackResource.PAUSE_INIT), 10, BasicEditField.FILTER_INTEGER);
            pauseBytes = new BasicEditField("Pause At: ", "64000", 10, BasicEditField.FILTER_INTEGER);
//            restartBytes = new BasicEditField(_resources.getString(BufferedPlaybackResource.RESTART_LABEL), _resources.getString(BufferedPlaybackResource.RESTART_INIT), 10, BasicEditField.FILTER_INTEGER);
            restartBytes = new BasicEditField("Restart At: ", "128000", 10, BasicEditField.FILTER_INTEGER);
//            readLimit = new BasicEditField(_resources.getString(BufferedPlaybackResource.READ_LABEL), _resources.getString(BufferedPlaybackResource.READ_INIT), 10, BasicEditField.FILTER_INTEGER);
            readLimit = new BasicEditField("Read Limit: ", "3200", 10, BasicEditField.FILTER_INTEGER);
            add(startBuffer);
            add(pauseBytes);
            add(restartBytes);
            add(readLimit);

        }

        public void fieldChanged(Field field, int context) {
            try {
                if (field == startplaying) {
                    if (player == null) {
                        source = new LimitedRateStreamingSource(url.getText());
                        source.setContentType(mime.getText());
                        source.setStartBuffer(Integer.parseInt(startBuffer.getText()));
                        source.setReadLimit(Integer.parseInt(readLimit.getText()));
                        source.setRestartBytes(Integer.parseInt(restartBytes.getText()));
                        source.setPauseBytes(Integer.parseInt(pauseBytes.getText()));
                        source.setLoadStatus(loadStatus);
                        source.setPlayStatus(playStatus);
//                        playStatus.setText(_resources.getString(BufferedPlaybackResource.PLAY_STARTED));
                        playStatus.setText("Started");
                        playerThread = new PlayerThread();
                        playerThread.start();
                    }
                    else
                    {
                        player.start();
                    }
                }
                else if (field == stopplaying && player != null)
                {
                    
                    player.stop();

                } else if (field == reset) {
                    if (player != null) {
                        player.stop();
                        player = null;
                    }
                    source.stop();
                    source.disconnect();
                    source = null;
//                    loadStatus.setText(_resources.getString(BufferedPlaybackResource.LOAD_INIT));
                    loadStatus.setText("0 Bytes");
//                    playStatus.setText(_resources.getString(BufferedPlaybackResource.PLAY_INIT));
                    playStatus.setText("Stopped");                    
                }
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }

        }

        public void close() {
            try {
                if (player != null) {
                    player.stop();
                }
            } catch (Exception e) {
                System.err.println(e.getMessage());
            } finally {
                System.exit(0);
            }
        }

        private class PlayerThread extends Thread {
            public void run() {
                try {
                    player = Manager.createPlayer(source);
                    player.start();
                } catch (Exception e) {
                    System.err.println(e.getMessage());
                }

            }
        }

    }

}

 

 

Developer
Posts: 70
Registered: ‎11-24-2009
My Device: Not Specified

Re: Graphical UI for Audio Streaming

package com.bufferedplayback;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.ContentConnection;
import javax.microedition.io.file.FileConnection;
import javax.microedition.media.Control;
import javax.microedition.media.protocol.ContentDescriptor;
import javax.microedition.media.protocol.DataSource;
import javax.microedition.media.protocol.SourceStream;

//import net.rim.device.api.i18n.ResourceBundle;
import net.rim.device.api.io.SharedInputStream;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.TextField;

public class LimitedRateStreamingSource extends DataSource
{

    private static final int READ_CHUNK = 2048; // bytes

    private TextField loadStatus;

    private TextField playStatus;

    private int startBuffer = 200000;

    private int readLimit = 32000;

    private int pauseBytes = 64000;

    private int restartBytes = 128000;

    private ContentConnection s;

    private SharedInputStream readAhead;

    private LimitedRateSourceStream feedToPlayer;

    private String forcedContentType;

    private volatile int totalRead;

    private volatile boolean _stop = false;

    private volatile boolean bufferingComplete = false;

    private volatile boolean downloadComplete = false;

    private ConnectionThread loaderThread;
    
//    private FileConnection saveFile;

//    private OutputStream saveStream;

    public LimitedRateStreamingSource(String locator)
    {
        super(locator);
    }

    /**
     * Open a connection to the locator
     *
     * @throws IOException
     */
    public void connect() throws IOException
    {
        // Get the http URL
        System.out.println("Loading: " + getLocator());
        String sUrl = getLocator();
        
        // For removing errors like
        // Refreshing connection on send
        // Running refresh
        // Local port: 19780
        // APN: 'rim.net.gprs'
        // APN username: 'null'
        // APN password: 'null'
        // Connection does not exist
        

        sUrl = sUrl + ";deviceside=true";
        System.out.println("Final URL " + sUrl);
        
        // Dont know why we need this READ_WRITE
        s = (ContentConnection) Connector.open(sUrl, Connector.READ_WRITE);
        System.out.println("Size: " + s.getLength());
        
        // Fetch the song file name from the URL
        int filenameStart = getLocator().lastIndexOf('/');
        int paramStart = getLocator().indexOf(';');
        if (paramStart < 0)
        {
            paramStart = getLocator().length();
        }
        String filename = getLocator().substring(filenameStart, paramStart);
        System.out.println("Filename: " + filename);

        // Get the location for saving the file on the disk
//        saveFile = (FileConnection) Connector.open("file:///store/home/user/audio" + filename, Connector.READ_WRITE);
//        if (!saveFile.exists())
//        {
//            System.out.println("Creating the local file");
//            saveFile.create();
//        }
//        else
//        {
//            System.out.println("Local file exists");
//        }

//        saveFile.setReadable(true);
//        SharedInputStream fileStream = SharedInputStream.getSharedInputStream(saveFile.openInputStream());
//        fileStream.setCurrentPosition(0);
        
//        System.out.println("Local File Size: " + saveFile.fileSize());
        
//        if (saveFile.fileSize() < s.getLength())
//        {
//            saveFile.setWritable(true);
//            System.out.println("Setting saveStream to save the file to the disk");
//            saveStream = saveFile.openOutputStream();
            System.out.println("Setting readAhead to SharedInputStream");
            readAhead = SharedInputStream.getSharedInputStream(s.openInputStream());
//        }
//        else
//        {
//            System.out.println("File is fully saved in the disk");
//            downloadComplete = true;
//            System.out.println("Setting readAhead to SharedInputStream");
//            readAhead = fileStream;
//            s.close();
//        }

//        if (forcedContentType != null)
//        {
//            feedToPlayer = new LimitedRateSourceStream(readAhead, forcedContentType);
//        }
//        else
//        {
//            feedToPlayer = new LimitedRateSourceStream(readAhead, s.getType());
//        }

        feedToPlayer = new LimitedRateSourceStream(readAhead, "audio/mpeg");
    }