2.2.Mô hình trạng thái Player

Hình trên biểu diễn mô hình trạng thái của Player. Khi Player được tạo ra, nó ở trạng thái UNREALIZED, và thông thường nó chuyển tiếp sang các trạng thái lần lượt là: REALIZED, PREFETCHED, STARTED và CLOSED. Khi đang ở trạng thái STARTED, nếu chúng đạt đến cuối media hay gọi phương thức stop(), Player sẽ chuyển sang trạng thái PREFETCHED.
Bạn có thể kiểm tra trạng thái của Player bằng cách sử dụng phương thức getState(). Tuy nhiên, Player luôn thay đổi trạng thái hay các thread có thể làm thay đổi trạng thái của chúng, nên thời điểm getState() trả về, nó có thể phản ánh trạng thái của Player không chính xác.
Tương tự, bạn có thể nhận thông báo thay đổi trạng thái của player thông qua việc đăng ký PlayerListener với nó và sử dụng phương thức playerUpdate(). Nhưng lưu ý đặc tả MMAPI không đảm bảo rằng các sự kiện thay đổi trạng thái sẽ được thông báo đúng lúc. Vì vậy, khi bạn nhận sự kiện “started”, thì media có thể đã đi đến cuối của nó.
Một điểm phức tạp khác đó là thông báo bất đồng bộ, đó là sự kiện gọi lại(callback) có thể được gọi từ một thread khác đến thread giao diện người dùng thông thường, và nó có thể được gọi trong khi lớp của bạn đang xử lý sự kiện giao diện người dùng trong một thread khác. Để quay về mô hình sự kiện trình tự, việc gọi lại thay đổi trạng thái player trong ví dụ của bài này sử dụng phương thức callSerially() của lớp Display trong MIDP và đưa vào hàng đợi các sự kiện giao diện người dùng mới. Sau đó, các sự kiện mới này được xử lý trình tự với các sự kiện giao diện người dùng khác, hơn là có thể chồng chéo.
2.3.Các kiểu nội dung Player:
Bạn có thể tìm thấy danh sách các kiểu media được hỗ trợ trong MMAPI: lưu ý phần thực thi, và chúng được hỗ trợ bởi phương thức Manager.createPlayer(InputStream stream, String type).
Một Player được tạo ra từ Manager.createPlayer(Manger.TONE_DEVICE_LOCATOR) trả về kiểu nội dung của nó audio/x-tone-seq.
2.4.Kiểm tra tính sẵn có của API
Bắt đầu từ phiên bảnMMAPI 1.1, các API có thể được yêu cầu từ thuộc tính microedition.media.version. Nó chứa phiên bản API theo một chuỗi định dạng(ví dụ “1.1”). Trên các thiết bị hỗ trợ MMAPI 1.0, những thuộc tính khác như “audio.encodings” có thể được sử dụng để thay thế.
2.5.Playing Tones và Tone Sequences
Để play một âm đơn(single tone) sử dụng:
Manager.playTone(note, duration, volume)
2.5.1. Playing tone sequences
Để play một tone sequence, bạn phải sử dụng ToneControl. Tạo một Player sử dụng một locator đặc biệt, nhận ToneControl, thiết lập sequence của nó và bắt đầu Player:
Player player = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
player.realize();
ToneControl tc = (ToneControl)(player.getControl(“ToneControl”));
tc.setSequence(new byte[] { ToneControl.VERSION, 1, ToneControl.C4, 8
ToneControl.C4 + 2, 8 });  // D4
player.start();
Lưu ý: bạn phải gọi player.realize() trước khi nhận ToneControl. Bạn không thể nhận bất kỳ kiểu control nào trước khi relize nó.
ToneControl có các byte command cho việc playing các note, tạo và chơi các block note, và thay đổi âm lượng…
Một Player được tạo ra bởi tone sequence từ file có phần mở rộng “.JTS” cũng có thể được tạo sử dụng các giao thức http://,file://, https://.
2.5.2.Playing tones từ stream
Tones có thể được tạo ra từ stream tương tự như cách tạo ra audio và MIDIs.
Đầu tiên tạo InputStream và gán nó vào Player:
InputStream is = getClass().getResourceAsStream(“/ukkonooa.jts”);
Player player = Manager.createPlayer(is, “audio/x-tone-seq”);
Một khi Player được tạo ra, bạn có thể thêm một listener, sau đó realize và prefetch Player:
player.addPlayerListener(this);
player.realize();
player.prefetch();
2.6. Playing mẫu âm thanh(sampled sound) và MIDI
Sampled sound có nghĩa là các định dạng âm thanh như WAV, nơi mà dữ liệu là một stream các mẫu âm thanh đại diện cho một phần âm thanh của một dây. Mặc khác, MIDI – đó là một chuỗi các command cho một multi-instrument.
Để biểu diễn một file âm thanh thông qua HTTP, sử dụng:
Player player = Manager.createPlayer(“http://something.com/somefile.wav”);
player.start();  // implicitly calls realize() and prefetch()
Trong S60 platform, khi sử dụng tham số MIME là null trong khi tạo Player, phần thực thi có thể tìm kiếm codec phù hợp một cách tự động. Tuy nhiên, nó được khuyến cáo nên chỉ rõ kiểu MIME. Trong S40 platform, kiểu nội dung không được tự động phát hiện nên khi tạo Player từ InputStream, kiểu MIME phải được chỉ rõ.
Để biểu diễn một file âm thanh được lưu trong RMS, sử dụng như sau:
RecordStore rs = RecordStore.open(“name”);
byte[] data = rs.getRecord(id);
ByteArrayInputStream is = new ByteArrayInputStream(data);
Player player = Manager.createPlayer(is, “audio/x-wav”);
player.start();
Khi thiết bị được thiết lập ở chế độ im lặng, nó phụ thuộc vào thiết bị mà âm thạnh hoặc mute hoặc vẫn có thể nghe thấy khi sử dụng MMAPI. Một vài thiết bị trong S40 có một số thiết lập riêng biệt cho âm thanh trong game menu. S40 hỗ trợ chế độ im lặng từ 3rd Editon, FT1 trở lên.
Việc hỗ trợ trộn(mixing) đã được giới thiệu trong S60 3rd Edition. Trong S60 cũ chỉ có một player có thể play tại một thời điểm. Với MMAPI, điều này được thể hiện bằng một thông báo rằng việc trộn không được hỗ trợ. Việc trộn có thể kiểm tra thông qua thuộc tính “support.mixing”  và trả về giá trị true nếu mixing được hỗ trợ. Khi mixing không được hỗ trợ và có 2 player được start một cách tuần tự thì phương thức start() của player gọi sau sẽ làm player đầu tiên dừng lại và player thứ 2 sẽ được start( lưu ý đặc điểm này không hỗ trợ trong S40).
Trao đổi và nghe(swap and play)
Trong thực thi S40 có hỗ trợ chức năng “Swap and Play”. Đối với nội dung âm thanh nào đó, nó cho phép MIDlet prefetch nhiều hơn một player, và tạm dừng player trong khi nó nối lại player khác. Bằng cách này, một vài player kích hoạt có thể tồn tại ở một thời điểm.
Trong S40, việc gọi phương thức start() trên một player không tự động dừng một player đang chạy.
“Swap and Play” chỉ hỗ trợ trên một vài thiết bị 3rd Edition(chỉ 6280 và 7370) và hỗ trợ đầy đủ từ 3rd Edition FP1 trở lên.

2.7.Playing video
Việc playing video cũng tương tự như audio. Tuy nhiên, video player cần nơi để hiển thị video. Vì vậy, bạn nhận một VideoControl từ video player và hiển thị nó hoặc trên Form như một Item hoặc trên Canvas.
Để hiển thị video trên Form như một Item:
InputStream is = getClass().getResourceAsStream(“/somefile.3gp”);
Player player = Manager.createPlayer(is, “video/3gpp”);
player.realize();
VideoControl vc =
(VideoControl)player.getControl(“VideoControl”);
if (vc != null)
{
Item it = (Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
myForm.append(it);
p.start();
}
Để hiển thị video trên một Canvas:
InputStream is = getClass().getResourceAsStream(“/somefile.3gp”);
Player player = Manager.createPlayer(is, “video/3gpp”);
player.realize();
VideoControl vc = (VideoControl)player.getControl(“VideoControl”);
if (vc != null)
{
vc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, myCanvas);
vc.setVisible(true);
p.start();
}
Lưu ý: theo mặc định VideoControl hiển thị trong Canvas không visible.
Nếu chế độ hiển thị của VideoControl được thiết lập là USE_DIRECT_VIDEO, thì tham số thứ 2 của phương thức initDisplayMode() có thể là một Canvas hay một đối tượng tạo ra từ Canvas.
Trong phương thức setDisplaySize() của VideoControl, image sẽ được scale lại cho phù hợp nếu kích thước hiển thị yêu cầu khác với kích thước của video clip. Trong Canvas, phương thức setDisplayFullScreen(true) chỉ thiết lập hiển thị lên toàn bộ Canvas, chứ không phải toàn bộ màn hình. Giá trị trả về bởi phương thức getDisplayWidth() và getDisplayHeight() không ảnh hưởng tới lời gọi này, đó là chúng sẽ không trả về chiều rộng và chiều cao của toàn bộ màn hình.
Lưu ý: Việc scale video được hỗ trợ trong S40 3rd Editon, FP2 trở lên.
Lưu tài nguyên khi biểu diễn đoạn video nhiều lần
Các nội dung video thường lớn và chơi nó nhiều lần sẽ tiêu thụ một số lượng đáng kể bộ nhớ nếu một thể hiện Player mới được tạo ra cho mỗi hành động chơi. Một Player có thể được lưu giữ để sử dụng, vì vậy việc playing có thể được khởi động lại mà không cần tải các tài nguyên một lần nữa. Nếu bạn có thể giả định rằng bộ nhớ của thiết bị di động không chạy ra ngoài, bạn có thể lưu các player được tạo và khởi tạo đến một player pool. Điều đó làm cho nó khởi động lại video clip nhanh hơn, vì nội dung không cần phải load lại vào bộ nhớ.

Các bài liên quan:
Sử dụng Multimedia API trong Nokia – Phần 1
Sử dụng Multimedia API trong Nokia – Phần 3
Sử dụng Multimedia API trong Nokia – Phần cuối