Vòng đời của Player
Vòng đời của Player bao gồm 5 trạng thái:

  • UNREALIZED
  • REALIZED
  • PREFETCHED
  • STARTED
  • CLOSED


Lớp Player còn cung cấp 6 phương thức để chuyển đổi trạng thái:

  • realize()
  • prefetch()
  • start()
  • stop()
  • deallocate()
  • close()

Sơ đồ biểu diễn việc chuyển đổi giữa các trạng thái

Trạng thái UNREALIZED

Khi Player được tạo ra, nó rời vào trạng thái UNREALIZED. Khi ở trạng thái này, nó không đủ thông tin để yêu cầu tất cả tài nguyên nó cần để hoạt động.

Ø Trạng thái REALIZED

Gọi phương thức relize() sẽ chuyển từ trạng thái UNREALIZED sang trạng thái REALIZED và khởi tạo thông tin mà Player cần để có tài nguyên media.

Một Player ở trong trạng REALIZED khi nó đã thu được các thông tin cần thiết để có được tài nguyên media.

Một khi Player đạt tới trạng thái REALIZED, nó có thể chuyển sang một trong 4 trạng thái sau: REALIZED , PREFETCHED, STARTED hay CLOSED. Player không bao giờ trả về trạng thái UNREALIZED.

Ø Trạng thái PREFETCHED

Khi ở trạng thái REALIZED, Player vẫn cần thực hiện một số công việc tiêu tốn thời gian trước khi nó được bắt đầu.

Ví dụ: nó có thể cần để có được các nguồn lực độc quyền, fill bộ đệm với dữ liệu media, thực hiện xử lý start-up khác, thiết lập kết nối mạng cho các luồng dữ liệu, hoặc thực hiện nhiệm vụ khởi tạo khác.

Việc gọi phương thức prefetch() sẽ chuyển từ trạng thái REALIZED sang trại thái PREFETCHED. Một khi Player đã ở trạng thái PREFETCHED, nó có thể được bắt đầu bằng cách gọi phương thức start(). Player sẽ trả về trạng thái PREFETCHED khi nó đang play hay nó đang ở cuối của media. Và gọi phương thức stop() sẽ làm cho Player dừng lại khi đang play và chuyển sang trạng thái PREFETCHED.

Ø Trạng thái STARTED

Khi Player đang ở trạng thái STARTED, có nghĩa là nó đang chạy và xử lý dữ liệu. Việc gọi phương thức start() sẽ làm cho Player chuyển từ trạng thái PREFETCHED sang trạng thái STARTED, và lúc đó nó thể bắt đầu xử lý dữ liệu.

Khi Player chuyển từ trạng thái PREFETCHED sang trạng thái STARTED, nó post một sự kiện STARTED.

Khi Player chuyển từ trạng thái STARTED sang trạng thái PREFETCHED, nó post một sự kiện STOPPED, END_OF_MEDIA hay STOP_AT_TIME phụ thuộc vào lý do mà nó dừng.

Ø Trạng thái CLOSED

Ở trạng thái CLOSED, Player giải phóng tất cả tài nguyên của nó và đối tượng Player lúc này cũng không thể được sử dụng lại.

Việc gọi phương thức close() sẽ làm cho Player chuyển từ trạng thái UNREALIZED, REALIZED, PREFETCHEDSTARTED sang trạng thái CLOSED.

Playing audio và video sử dụng MMAPI

Ø Playing audio

Nội dung có thể đọc từ server, JAR, file hệ thống hay RMS để có thể play nó trên thiết bị.

Ví dụ sau đây cho biết cách đọc một file từ file JAR.

Đọc một file audio từ file JAR bằng cách tạo một InputStream như sau:

/*Read audio file from resource */

InputStream inputStream = getClass().getResourceAsStream(“/music.mid”);

Sau khi đọc dữ liệu từ file JAR, tạo một player với đầu vào là InputStream và kiểu nội dung của file audio.

Player player = Manager.createPlayer(inputStream, "audio/midi");

Phương thức setLoopCount(int count) thiết lập số lần mà player sẽ play audio, nếu count được gán bằng -1, thí player sẽ lặp vô hạn.

player.setLoopCount(-1); // infinite playback

Khởi tạo player bằng cách gọi phương thức relize() như sau:

player.realize();

Chuyển sang trạng thái PREFETCHED như sau:

player.prefetch();

Thiết lập player lắng nghe các sự kiện:

player.addPlayerListener(this);

Bắt đầu play đoạn audio thông qua phương thức:

player.start();

Playing video

Thực hiện tương tự như audio cho đến khi thiết lập một listener cho player và nhận đối tượng điều khiển video mà video có thể được hiển thị trên form như là một item.

VideoControl videoControl = (VideoControl) Player.getControl("VideoControl");
if (videoControl != null) {
         Item videoItem = (Item)              
               videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
        append(videoItem);
}

Bắt đầu play video bằng cách gọi phương thức sau;

player.start();

Ví dụ

Ø Ví dụ mẫu về audio playback

import java.io.InputStream;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.midlet.MIDlet;
 
public class AudioMidlet extends MIDlet implements CommandListener, 
  PlayerListener, Runnable {
 
    private static final String EXIT   = "Exit";
    private static final String PAUSE  = "Pause";
    private static final String PLAY   = "Play";
 
    private Display display;
    private Form playerForm;
    private Thread thread;
    private Player player;
    private StringItem curStatus;
 
    /*this command is used to exit from the current application*/
    private final Command cmdExit = new Command(EXIT, Command.EXIT, 2);
    /*this command is used to bring the player in pause state*/
    private final Command cmdPause = new Command(PAUSE, Command.ITEM, 1);
    /*this command is used to play the player*/
    private final Command cmdPlay = new Command(PLAY, Command.ITEM, 1);
 
    public AudioMidlet() {
        display = Display.getDisplay(this);
        playerForm = new Form("MMAPI Audio");
        initAudio();
        curStatus = new StringItem("Player Status:", "Reading Content");
        playerForm.append(curStatus);
        playerForm.addCommand(cmdExit);
        playerForm.addCommand(cmdPause);
        playerForm.setCommandListener(this);
 
    }
 
    public void startApp() {
        display.setCurrent(playerForm);
    }
 
    public void pauseApp() {
        /*all interupts can be handled here*/
    }
 
    public void destroyApp(boolean unconditional) {
        playerClose();
    }
 
    public void exitMidlet() {
        destroyApp(true);
        notifyDestroyed();
    }
 
    public void initAudio() {
        /*recomeneded to start the players in a separate thread*/
        thread = new Thread(this);
        thread.start();
    }
 
    public void run() {
        try {
            /*gets the content from the JAR as a resource stream data*/
            InputStream inputStream = 
              getClass().getResourceAsStream("/piano.mid");
            /*create a player object*/
            player = Manager.createPlayer(inputStream, "audio/midi");
            /*this is used to set the loop count, here -1 is indefinite*/
            player.setLoopCount(-1);
            player.realize();
            player.prefetch();
            player.addPlayerListener(this);
        } catch (Exception ex) {
            if (player != null) {
                player.close();
                player = null;
            }
            System.err.println("Problem creating player" + ex);
        }
 
        startPlayer();
 
    }
 
    /*this method will responds to the player events*/
    public void playerUpdate(Player plyr, String evt, Object evtData) {
        if (evt == STARTED) {
            curStatus.setText("Started Playing Audio");
        } else if (evt == STOPPED) {
            curStatus.setText("Stopped Playing Audio");
        } else if (evt == CLOSED) {
            curStatus.setText("Closed Playing Audio");
        }
    }
 
    public void commandAction(Command cmd, Displayable disp) {
        if (cmd == cmdPause && disp == playerForm) {
            playerPause();
            playerForm.removeCommand(cmdPause);
            playerForm.addCommand(cmdPlay);
        } else if (cmd == cmdExit && disp == playerForm) {
            exitMidlet();
        } else if (cmd == cmdPlay && disp == playerForm) {
            playerForm.removeCommand(cmdPlay);
            playerForm.addCommand(cmdPause);
            startPlayer();
        }
    }
 
    public void startPlayer() {
        if (player != null) {
            try {
                player.start();
            } catch (MediaException me) {
                System.err.println(me);
            } catch (Exception ex) {
                System.err.println(ex);
            }
        }
    }
 
    public void playerPause() {
        if (player != null) {
            try {
                player.stop();
            } catch (MediaException me) {
                System.err.println(me);
            }
        }
    }
 
    public void playerClose() {
        synchronized (this) {
            playerPause();
            if (player != null) {
                player.close();
                player = null;
            }
        }
    }
}

Ví dụ mẫu về video playback

import java.io.InputStream;
 
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.StringItem;
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.VideoControl;
import javax.microedition.midlet.MIDlet;
 
public class VideoMidlet extends MIDlet implements CommandListener, 
  PlayerListener, Runnable {
 
    private static final String EXIT  = "Exit";
    private static final String PAUSE = "Pause";
    private static final String PLAY  = "Play";  
    
    private Display display;    
    private Form playerForm;    
    private Thread thread;    
    private Player player;    
    private StringItem curStatus;
    
    /*this command is used to exit from the current application*/
    private final Command cmdExit = new Command(EXIT, Command.EXIT, 2);
    /*this command is used to bring the player in pause state*/
    private final Command cmdPause = new Command(PAUSE, Command.ITEM, 1);
    /*this command is used to play the player*/
    private final Command cmdPlay = new Command(PLAY, Command.ITEM, 1);
 
    public VideoMidlet() {       
        display = Display.getDisplay(this);        
        playerForm = new Form("MMAPI Video");
        initAudio();        
        curStatus = new StringItem("Player Status:", "Reading Content");
        playerForm.append(curStatus);
        playerForm.addCommand(cmdExit);
        playerForm.addCommand(cmdPause);
        playerForm.setCommandListener(this);
    }
    
    public void startApp() {
        display.setCurrent(playerForm);
    }
 
    public void pauseApp() {
        /*all interupts can be handled here*/
    }
 
    public void destroyApp(boolean unconditional) {
    }
 
    public void exitMidlet() {
        destroyApp(true);
        notifyDestroyed();
    }
 
    public void initAudio() {
        /*recomeneded to start the players in a separate thread*/
        thread = new Thread(this);
        thread.start();
    }
 
    public void run() {
        try {
         /*gets the content from the JAR as a resource stream data*/
         InputStream inputStream = getClass().getResourceAsStream("/video.mpg");
         /*creates a player object from Manager by using factory mechanism*/
         player = Manager.createPlayer(inputStream, "video/mpeg");            
         player.realize();            
         player.prefetch();            
         player.addPlayerListener(this);            
         VideoControl videoControl = 
         (VideoControl) player.getControl("VideoControl");
         if (videoControl != null) {
            Item videoItem = (Item) 
            videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
            playerForm.append(videoItem);
         }
        } catch (Exception ex) {
            if (player != null) {
                player.close();
                player = null;
            }
            System.err.println("Problem creating player" + ex);
        }
        startPlayer();
    }
 
    public void commandAction(Command cmd, Displayable disp) {
        if (cmd == cmdPause && disp == playerForm) {
            playerPause();
            playerForm.removeCommand(cmdPause);
            playerForm.addCommand(cmdPlay);
        } else if (cmd == cmdExit && disp == playerForm) {
            exitMidlet();
        } else if (cmd == cmdPlay && disp == playerForm) {
            playerForm.removeCommand(cmdPlay);
            playerForm.addCommand(cmdPause);
            startPlayer();
        }
    }
    
    /*this method will responds to the player events*/
    public void playerUpdate(Player plyr, String evt, Object evtData) {
        if (evt == STARTED) {
            curStatus.setText("Started Playing Video");
        } else if (evt == STOPPED) {
            curStatus.setText("Stopped Playing Video");
        } else if (evt == CLOSED) {
            curStatus.setText("Closed Playing Video");
        }
        if (evt == END_OF_MEDIA) {
            try {
                player.setMediaTime(0);
                player.start();
            } catch (MediaException me) {
                System.err.println(me);
            }
        }
    }
 
    public void startPlayer() {
        if (player != null) {
            try {
                player.start();
            } catch (Exception ex) {
                System.out.println("Error in starting a player=" + ex);
            }
        }
    }
 
    public void playerPause() {
        if (player != null) {
            try {
                player.stop();
            } catch (MediaException me) {
                System.err.println(me);
            }
        }
    }
 
    public void playerClose() {
        synchronized (this) {
            playerPause();
            if (player != null) {
                player.close();
                player = null;
            }
        }
    }
}

Code

Các bài liên quan:
Mobile Media API (MMAPI) – JSR 135 - Phần 1

Trạng thái UNREALIZED

Khi Player được tạo ra, nó rời vào trạng thái UNREALIZED. Khi ở trạng thái này, nó không đủ thông tin để yêu cầu tất cả tài nguyên nó cần để hoạt động.
  • Trạng thái REALIZED
Gọi phương thức relize() sẽ chuyển từ trạng thái UNREALIZED sang trạng thái REALIZED và khởi tạo thông tin mà Player cần để có tài nguyên media.
Một Player ở trong trạng REALIZED khi nó đã thu được các thông tin cần thiết để có được tài nguyên media.
Một khi Player đạt tới trạng thái REALIZED, nó có thể chuyển sang một trong 4 trạng thái sau: REALIZED , PREFETCHED, STARTED hay CLOSED. Player không bao giờ trả về trạng thái UNREALIZED.
  • Trạng thái PREFETCHED
Khi ở trạng thái REALIZED, Player vẫn cần thực hiện một số công việc tiêu tốn thời gian trước khi nó được bắt đầu.
Ví dụ: nó có thể cần để có được các nguồn lực độc quyền, fill bộ đệm với dữ liệu media, thực hiện xử lý start-up khác, thiết lập kết nối mạng cho các luồng dữ liệu, hoặc thực hiện nhiệm vụ khởi tạo khác.
Việc gọi phương thức prefetch() sẽ chuyển từ trạng thái REALIZED sang trại thái PREFETCHED. Một khi Player đã ở trạng thái PREFETCHED, nó có thể được bắt đầu bằng cách gọi phương thức start(). Player sẽ trả về trạng thái PREFETCHED khi nó đang play hay nó đang ở cuối của media. Và gọi phương thức stop() sẽ làm cho Player dừng lại khi đang play và chuyển sang trạng thái PREFETCHED.
  • Trạng thái STARTED
Khi Player đang ở trạng thái STARTED, có nghĩa là nó đang chạy và xử lý dữ liệu. Việc gọi phương thức start() sẽ làm cho Player chuyển từ trạng thái PREFETCHED sang trạng thái STARTED, và lúc đó nó thể bắt đầu xử lý dữ liệu.
Khi Player chuyển từ trạng thái PREFETCHED sang trạng thái STARTED, nó post một sự kiện STARTED.
Khi Player chuyển từ trạng thái STARTED sang trạng thái PREFETCHED, nó post một sự kiện STOPPED, END_OF_MEDIA hay STOP_AT_TIME phụ thuộc vào lý do mà nó dừng.
  • Trạng thái CLOSED
Ở trạng thái CLOSED, Player giải phóng tất cả tài nguyên của nó và đối tượng Player lúc này cũng không thể được sử dụng lại.
Việc gọi phương thức close() sẽ làm cho Player chuyển từ trạng thái UNREALIZED, REALIZED, PREFETCHEDSTARTED sang trạng thái CLOSED.