001: /*
002: * Copyright (c) 2007, Sun Microsystems, Inc.
003: *
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * * Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: * * Neither the name of Sun Microsystems, Inc. nor the names of its
017: * contributors may be used to endorse or promote products derived
018: * from this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
023: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
024: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.mmademo;
033:
034: import java.util.*;
035: import java.io.*;
036: import javax.microedition.midlet.*;
037: import javax.microedition.lcdui.*;
038: import javax.microedition.media.*;
039: import javax.microedition.media.control.*;
040:
041: /**
042: * MMAPI player main window for media files, implemented as a Form
043: *
044: * @version 1.4
045: */
046: public class SimplePlayerForm extends Form implements
047: SimplePlayerGUI.Parent, Utils.ContentHandler,
048: Utils.Interruptable, Runnable {
049:
050: private SimplePlayerGUI gui; // default: null
051: private Utils.BreadCrumbTrail parent;
052:
053: private static Image spacerImage;
054: private ImageItem iiLogo;
055: private StringItem siFileTitle;
056: private StringItem siTime;
057: private StringItem siRate;
058: private StringItem siKaraoke;
059: private StringItem siFeedback;
060: private StringItem siStatus;
061:
062: private boolean karaokeShowing;
063:
064: private static int maxKaraokeLines = 2;
065:
066: private static void debugOut(String s) {
067: Utils.debugOut("SimplePlayerForm: " + s);
068: }
069:
070: public SimplePlayerForm(String title, Utils.BreadCrumbTrail parent) {
071: this (title, null, parent);
072: }
073:
074: public SimplePlayerForm(String title, SimplePlayerGUI spg,
075: Utils.BreadCrumbTrail parent) {
076: super (title);
077: this .parent = parent;
078: this .gui = spg;
079: siFileTitle = new StringItem("", "");
080: siTime = new StringItem("", "");
081: siRate = new StringItem("", "");
082: siKaraoke = new StringItem("", "");
083: siFeedback = new StringItem("", "");
084: siStatus = new StringItem("", "");
085: debugOut("constructor finished");
086: }
087:
088: private void appendNewLine(Item item) {
089: insertNewLine(size(), item);
090: }
091:
092: private void insertNewLine(int pos, Item item) {
093: insert(pos, (StringItem) item);
094:
095: Spacer spacer = new Spacer(3, 10);
096: spacer.setLayout(Item.LAYOUT_NEWLINE_BEFORE);
097: if (pos < 8) {
098: insert(pos++, spacer);
099: }
100: }
101:
102: private void setUpItems() {
103: // first delete all items
104: for (int i = size() - 1; i >= 0; i--) {
105: delete(i);
106: }
107: karaokeShowing = false;
108: getGUI();
109: if (!gui.hasGUIControls()) {
110: makeImageItem();
111: }
112: appendNewLine(siFileTitle);
113: appendNewLine(siTime);
114: if (gui.hasRateControl() || gui.hasTempoControl()) {
115: appendNewLine(siRate);
116: }
117: if (gui.hasGUIControls()) {
118: Control[] controls = gui.getControls();
119: if (controls != null) {
120: for (int i = 0; i < controls.length; i++) {
121: Control ctrl = controls[i];
122: if (ctrl instanceof GUIControl) {
123: Object guiItem = ((GUIControl) ctrl)
124: .initDisplayMode(
125: GUIControl.USE_GUI_PRIMITIVE,
126: null);
127: if (guiItem instanceof Item) {
128: append((Item) guiItem);
129: if (ctrl instanceof VideoControl) {
130: try {
131: ((VideoControl) ctrl)
132: .setDisplayFullScreen(false);
133: } catch (MediaException me) {
134: Utils.debugOut(me);
135: }
136: }
137: }
138: }
139: }
140: }
141: }
142: appendNewLine(siFeedback);
143: appendNewLine(siStatus);
144: }
145:
146: private void makeImageItem() {
147: if (gui != null && !gui.isFullScreen()) {
148: if (iiLogo == null) {
149: Image logo = gui.getLogo();
150: if (logo != null) {
151: iiLogo = new ImageItem("", logo,
152: ImageItem.LAYOUT_CENTER
153: | ImageItem.LAYOUT_NEWLINE_BEFORE
154: | ImageItem.LAYOUT_NEWLINE_AFTER,
155: "MMAPI logo");
156: }
157: }
158: if (iiLogo != null) {
159: insert(0, iiLogo);
160: }
161: }
162: }
163:
164: ////////////////////////////// interface Utils.BreadCrumbTrail /////////////////
165:
166: public Displayable go(Displayable d) {
167: return parent.go(d);
168: }
169:
170: public Displayable goBack() {
171: return parent.goBack();
172: }
173:
174: public Displayable replaceCurrent(Displayable d) {
175: return parent.replaceCurrent(d);
176: }
177:
178: public Displayable getCurrentDisplayable() {
179: return parent.getCurrentDisplayable();
180: }
181:
182: /////////////////////////// interface SimplePlayerGUI.Parent //////////////////
183:
184: public Utils.BreadCrumbTrail getParent() {
185: return parent;
186: }
187:
188: // called after the media is prefetched
189: public void setupDisplay() {
190: setUpItems();
191: }
192:
193: public void setStatus(String s) {
194: siStatus.setText(s);
195: }
196:
197: public void setFeedback(String s) {
198: siFeedback.setText(s);
199: }
200:
201: public void setFileTitle(String s) {
202: siFileTitle.setText(s);
203: }
204:
205: public void updateKaraoke() {
206: int[] karaokeParams = new int[4];
207: String[] lines = gui.getKaraokeStr(karaokeParams);
208: int currLine = karaokeParams[SimplePlayerGUI.KARAOKE_LINE];
209: int lineCount = karaokeParams[SimplePlayerGUI.KARAOKE_LINE_COUNT];
210: int syllLen = karaokeParams[SimplePlayerGUI.KARAOKE_SYLLABLE_LENGTH];
211: int currLinePos = karaokeParams[SimplePlayerGUI.KARAOKE_LINE_INDEX];
212:
213: int this Line = 0;
214: if (lineCount > maxKaraokeLines) {
215: this Line = currLine - 1;
216: if (this Line < 0) {
217: this Line = 0;
218: }
219: if (this Line + maxKaraokeLines > lineCount) {
220: this Line = lineCount - maxKaraokeLines;
221: } else if (lineCount - this Line > maxKaraokeLines) {
222: lineCount = this Line + maxKaraokeLines;
223: }
224: }
225: String text = "";
226: for (; this Line < lineCount; this Line++) {
227: text += lines[this Line] + "\n";
228: }
229:
230: siKaraoke.setText(text);
231: if (!karaokeShowing && !gui.isFullScreen()) {
232: // insert karaoke item before feedback line
233: for (int i = size() - 1; i >= 0; i--) {
234: if (get(i) == siFeedback) {
235: if (i > 0 && (get(i - 1) instanceof ImageItem)) {
236: i--;
237: }
238: insertNewLine(i, siKaraoke);
239: break;
240: }
241: }
242: // do not try to visualize siKaraoke again
243: karaokeShowing = true;
244: }
245:
246: }
247:
248: public void updateTime() {
249: if (gui != null) {
250: siTime.setText(gui.getMediaTimeStr());
251: }
252: }
253:
254: public void updateRate() {
255: if (getGUI().hasTempoControl()) {
256: siRate.setText(gui.getTempoStr());
257: } else {
258: siRate.setText(gui.getRateStr());
259: }
260: }
261:
262: public void updateDisplay() {
263: }
264:
265: public void fullScreen(boolean value) {
266: // nothing to do ?
267: }
268:
269: //////////////////////////////// interface Utils.ContentHandler ///////////////////////////////
270:
271: public synchronized void close() {
272: if (gui != null) {
273: gui.closePlayer();
274: gui = null;
275: }
276: }
277:
278: public boolean canHandle(String url) {
279: // TODO ?
280: return true;
281: }
282:
283: public void handle(String name, String url) {
284: Utils.debugOut("SimplePlayerForm: handle " + url);
285: getGUI().setParent(this );
286: gui.setSong(name, url);
287: doHandle();
288: }
289:
290: public void handle(String name, InputStream is, String contentType) {
291: getGUI().setParent(this );
292: gui.setSong(name, is, contentType);
293: doHandle();
294: }
295:
296: // ///////////////////////// interface Utils.ContentHandler //////////////// //
297:
298: private synchronized SimplePlayerGUI getGUI() {
299: if (gui == null) {
300: debugOut("create GUI");
301: gui = new SimplePlayerGUI();
302: gui.initialize(getTitle(), this );
303: gui.setTimerInterval(500);
304: makeImageItem();
305: }
306: return gui;
307: }
308:
309: private void doHandle() {
310: debugOut("doHandle");
311: setUpItems();
312: // IMPL NOTE:
313: // I want to display the player first, and THEN start prefetching.
314: // the only way I was able to achieve this was by creating a new thread.
315: new Thread(this ).start();
316: }
317:
318: public void run() {
319: gui.startPlayer();
320: }
321:
322: // /////////////////////////////////// Interface Utils.Interruptable ////////////////// //
323:
324: /**
325: * Called in response to a request to pause the MIDlet.
326: * This implementation will just call the same
327: * method in the GUI implementation.
328: */
329: public synchronized void pauseApp() {
330: if (gui != null) {
331: gui.pauseApp();
332: }
333: }
334:
335: /**
336: * Called when a MIDlet is asked to resume operations
337: * after a call to pauseApp(). This method is only
338: * called after pauseApp(), so it is different from
339: * MIDlet's startApp().
340: *
341: * This implementation will just call the same
342: * method in the GUI implementation.
343: */
344: public synchronized void resumeApp() {
345: if (gui != null) {
346: gui.resumeApp();
347: }
348: }
349:
350: // for debugging
351: public String toString() {
352: return "SimplePlayerForm";
353: }
354:
355: }
|