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 javax.microedition.midlet.*;
035: import javax.microedition.lcdui.*;
036: import javax.microedition.media.*;
037: import javax.microedition.media.control.*;
038: import java.util.*;
039: import java.io.*;
040:
041: /**
042: * An example MIDlet for a generic Player for audio, MIDI media
043: * The top-level URLs are configured in the jad file:<br>
044: * <code>PlayerURL-n</code> defines the n'th URL<br>
045: * <code>PlayerTitle-n</code> defines the n'th title
046: * <p>
047: * Special URL "protocols" can be used:<br>
048: * <code>resource:</code> for media data from the jar<br>
049: * <code>rms:</code> for media data from RMS memory<br>
050: * <p>
051: * Examples:<br>
052: * <code>
053: * PlayerURL-1: http://server.com/ <br>
054: * PlayerTitle-1: Browse server.com <br>
055: * PlayerURL-2: resource:/audio/hello.wav <br>
056: * PlayerTitle-2: hello.wav from jar <br>
057: * PlayerURL-3: http://localhost/movie.mpg <br>
058: * PlayerTitle-3: Funny movie <br>
059: * PlayerURL-4: rms:/ <br>
060: * PlayerTitle-4: Browse Record Stores<br>
061: * PlayerURL-5: capture://audio <br>
062: * PlayerTitle-5: Capture Audio from default device<br>
063: * </code>
064: *
065: * @version 1.5
066: */
067: public class SimplePlayer extends BaseListMidlet implements
068: Utils.BreadCrumbTrail, Utils.QueryListener {
069:
070: private static final String manualEnterURL = "manual";
071: private static final String manualEnterTitle = "[enter URL]";
072: private String lastManualURL = "";
073:
074: private Vector titles;
075: private Vector urls;
076:
077: /* This can be put in the Utils file if necessary */
078: private static final String httpSupportedList = getSupportedList("http");
079: private static final String allSupportedList = getSupportedList(null);
080:
081: private static String getSupportedList(String protocol) {
082: String list[] = Manager.getSupportedContentTypes(protocol);
083: StringBuffer buffer = new StringBuffer();
084: for (int i = 0; i < list.length; i++) {
085: buffer.append(list[i]).append(",");
086: }
087: if (list.length > 0)
088: return buffer.toString();
089: else
090: return "";
091: }
092:
093: // SimplePlayerCanvas is the default player
094: private SimplePlayerCanvas simplePlayerCanvas = new SimplePlayerCanvas(
095: "MMAPI Player", this );
096:
097: private Utils.ContentHandler[] handlers = {
098: new SimpleHttpBrowser("MMAPI HTTP Browser", this ),
099: new SimpleRmsBrowser("MMAPI RMS Browser", this ),
100: simplePlayerCanvas,
101: //new SimplePlayerForm("MMAPI Player", this), // will be instantiated by SimplePlayer
102: };
103:
104: public SimplePlayer() {
105: super ("MMAPI Player");
106: }
107:
108: /* This can be put in the Utils file if necessary */
109: protected final static boolean isSupported(String url) {
110: if (!url.startsWith("capture:")) {
111: String contentType;
112: try {
113: contentType = Utils.guessContentType(url);
114: } catch (Exception e) {
115: contentType = "";
116: }
117: if (contentType.equals(""))
118: return false;
119: if (url.startsWith("resource:")) {
120: /**
121: * The MMAPI spec doesn't provide an api to
122: * query if a contentType is supported via
123: * InputStream. So we cannot handle the case
124: * where a contentType is supported in http
125: * protocol but not supported via InputStream.
126: * This will not be the case for Sun's MMAPI
127: * implementation.
128: * Even if this is the case in another MMAPI implementation,
129: * the player creation will fail with a message that
130: * the player couldn't be created.
131: */
132: if (allSupportedList.indexOf(contentType + ",") == -1)
133: return false;
134: } else if (url.startsWith("http:")) {
135: if (httpSupportedList.indexOf(contentType + ",") == -1)
136: return false;
137: }
138: }
139: return true;
140: }
141:
142: protected void fillList(List list) {
143: titles = new Vector();
144: urls = new Vector();
145: for (int n = 1; n < 100; n++) {
146: String nthURL = "PlayerURL-" + n;
147: String url = getAppProperty(nthURL);
148: if (url == null || url.length() == 0) {
149: break;
150: }
151: if (!isSupported(url))
152: continue;
153: String nthTitle = "PlayerTitle-" + n;
154: String title = getAppProperty(nthTitle);
155: if (title == null || title.length() == 0) {
156: title = url;
157: }
158: titles.addElement(title);
159: urls.addElement(url);
160: list.append(title, null);
161: }
162: // TODO: add MRU list here
163:
164: // manual enter of URL
165: titles.addElement(manualEnterTitle);
166: urls.addElement(manualEnterURL);
167: list.append(manualEnterTitle, null);
168:
169: list.addCommand(exitCommand);
170: list.addCommand(selectCommand);
171: }
172:
173: /**
174: * Main function that decides which class to display
175: * dependent on the url.
176: */
177: public void handle(String title, String url) {
178: try {
179: InputStream is = null;
180: String ct = "";
181: // first magic URL's
182: if (url.equals(manualEnterURL)) {
183: enterURL();
184: return;
185: } else if (url.startsWith("resource:")) {
186: is = getClass().getResourceAsStream(url.substring(9));
187: is.mark(is.available());
188: } else if (SimpleRmsBrowser.isRmsFile(url)) {
189: is = SimpleRmsBrowser.getRecordStoreStream(url);
190: }
191: // ringtone text file ?
192: if (Utils.guessContentType(url).equals("audio/x-txt")) {
193: RingToneConverter rtc;
194: if (is != null) {
195: rtc = new RingToneConverter(is, title);
196: } else {
197: rtc = new RingToneConverter(url, title);
198: }
199: Player tonePlayer = Manager
200: .createPlayer(Manager.TONE_DEVICE_LOCATOR);
201: tonePlayer.realize();
202: ToneControl tc = (ToneControl) tonePlayer
203: .getControl("ToneControl");
204: tc.setSequence(rtc.getSequence());
205: // do NOT prefetch this player. Otherwise SimplePlayerGUI will not initialize this player
206: go(simplePlayerCanvas);
207: simplePlayerCanvas.handle(rtc.getName(), tonePlayer);
208: return;
209: }
210: if (is != null) {
211: if (ct == "") {
212: ct = Utils.guessContentType(url);
213: }
214: go(simplePlayerCanvas);
215: simplePlayerCanvas.handle(title, is, ct);
216: return;
217: } else {
218: for (int i = 0; i < handlers.length; i++) {
219: if (handlers[i].canHandle(url)) {
220: go((Displayable) handlers[i]);
221: handlers[i].handle(title, url);
222: return;
223: }
224: }
225: }
226: Utils.error("No handler available!", this );
227: } catch (Exception e) {
228: Utils.error(e, this );
229: }
230: }
231:
232: protected void selectCommand(int index) {
233: if (index >= 0) {
234: if (index < titles.size()) {
235: handle((String) titles.elementAt(index), (String) urls
236: .elementAt(index));
237: }
238: }
239: }
240:
241: /**
242: * Display a prompt for a new URL
243: */
244: private void enterURL() {
245: Utils.query("Enter a URL", lastManualURL, 300, TextField.URL,
246: this , this );
247: }
248:
249: // //////////////////// interface Utils.QueryListener /////////////////// //
250: public void queryOK(String text) {
251: handle(text, text);
252: lastManualURL = text;
253: }
254:
255: public void queryCancelled() {
256: // don't do anything if query is cancelled.
257: // the previous visible Displayable will be
258: // displayed automatically
259: }
260:
261: // //////////////////// interface MIDlet /////////////////// //
262: public void destroyApp(boolean unconditional) {
263: Utils.ContentHandler p = getCurrentHandler();
264: if (p != null) {
265: p.close();
266: }
267: super .destroyApp(unconditional);
268: }
269:
270: // util method
271: private Utils.ContentHandler getCurrentHandler() {
272: Displayable d = getDisplay().getCurrent();
273: if (d instanceof Utils.ContentHandler) {
274: return (Utils.ContentHandler) d;
275: }
276: return null;
277: }
278:
279: // for debugging
280: public String toString() {
281: return "SimplePlayer";
282: }
283:
284: }
|