001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * 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
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * 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.audiodemo;
033:
034: import java.io.*;
035:
036: import javax.microedition.lcdui.*;
037: import javax.microedition.media.*;
038: import javax.microedition.media.control.*;
039: import javax.microedition.midlet.*;
040: import javax.microedition.rms.*;
041:
042: /**
043: * The component for AudioPlayer.
044: * It will create a player for the selected url, play and display
045: * some properties of the player.
046: *
047: * Use star key to increase the volume, pound key to decrease the volume
048: *
049: **/
050: public class PlayerCanvas extends Canvas implements Runnable,
051: CommandListener {
052: private static final String RECORD_STORE_NAME = "adrms";
053: private Player player;
054: private Thread dThread;
055: private Object dThreadLock = new Object();
056: private Object pauseLock = new Object();
057: private boolean interrupted;
058: private boolean paused;
059: private Image logo = null;
060: private Display parentDisplay;
061: private Command backCommand = new Command("Back", Command.BACK, 1);
062: private Command playCommand = new Command("Play", Command.ITEM, 1);
063: private Command pauseCommand = new Command("Pause", Command.ITEM,
064: 10);
065: private String title;
066: private String url;
067: private String mtime;
068:
069: public PlayerCanvas(Display parentDisplay) {
070: super ();
071: this .parentDisplay = parentDisplay;
072: initialize();
073: }
074:
075: private void initialize() {
076: this .addCommand(backCommand);
077: this .addCommand(pauseCommand);
078:
079: setCommandListener(this );
080:
081: try {
082: logo = Image.createImage("/icons/Duke.png");
083: } catch (Exception ex) {
084: logo = null;
085: }
086:
087: if (logo == null) {
088: System.out.println("can not load Duke.png");
089: }
090: }
091:
092: /*
093: * simple implementation, not reflected actual state
094: * of player.
095: */
096: public void commandAction(Command c, Displayable s) {
097: if (s == this ) {
098: if (c == backCommand) {
099: stopSound();
100: removeCommand(playCommand);
101: addCommand(pauseCommand);
102: parentDisplay.setCurrent(AudioPlayer.getList());
103: } else if (c == playCommand) {
104: playSound();
105: removeCommand(playCommand);
106: addCommand(pauseCommand);
107: } else if (c == pauseCommand) {
108: pauseSound();
109: removeCommand(pauseCommand);
110: addCommand(playCommand);
111: }
112: }
113: }
114:
115: public void setParam(String url) {
116: this .url = url;
117:
118: int idx = url.lastIndexOf('/');
119: title = url.substring(idx + 1);
120: }
121:
122: public void playSound() {
123: if ((title == null) || (url == null)) {
124: return;
125: }
126:
127: // player was paused
128: if (player != null) {
129: // wake up paused thread
130: synchronized (pauseLock) {
131: paused = false;
132: pauseLock.notify();
133: }
134:
135: try {
136: player.start();
137: } catch (MediaException me) {
138: me.printStackTrace();
139: }
140:
141: return;
142: }
143:
144: // start new player
145: synchronized (dThreadLock) {
146: stopSound();
147: interrupted = false;
148: paused = false;
149: mtime = "";
150: dThread = new Thread(this );
151: dThread.start();
152: }
153: }
154:
155: public void stopSound() {
156: synchronized (dThreadLock) {
157: try {
158: interrupted = true;
159:
160: // wake up thread if it is paused
161: synchronized (pauseLock) {
162: pauseLock.notify();
163: }
164:
165: if (dThread != null) {
166: dThreadLock.wait();
167: }
168: } catch (InterruptedException ie) {
169: // nothing
170: }
171: }
172: }
173:
174: void pauseSound() {
175: try {
176: if (player != null) {
177: // pause player
178: player.stop();
179: paused = true;
180: }
181: } catch (MediaException ex) {
182: ex.printStackTrace();
183: }
184: }
185:
186: public boolean isPlaying() {
187: return (player != null)
188: && (player.getState() >= Player.STARTED);
189: }
190:
191: private static String guessContentType(String url) throws Exception {
192: String ctype;
193:
194: // some simple test for the content type
195: if (url.endsWith("wav")) {
196: ctype = "audio/x-wav";
197: } else if (url.endsWith("jts")) {
198: ctype = "audio/x-tone-seq";
199: } else if (url.endsWith("mid")) {
200: ctype = "audio/midi";
201: } else {
202: throw new Exception("Cannot guess content type from URL: "
203: + url);
204: }
205:
206: return ctype;
207: }
208:
209: void createPlayer() {
210: try {
211: if (url.startsWith("http:")) {
212: player = Manager.createPlayer(url);
213: } else if (url.startsWith("resource")) {
214: int idx = url.indexOf(':');
215: String loc = url.substring(idx + 1);
216: InputStream is = getClass().getResourceAsStream(loc);
217: String ctype = guessContentType(url);
218: player = Manager.createPlayer(is, ctype);
219: } else if (url.startsWith("rms:")) {
220: boolean created = false;
221: InputStream stream = null;
222:
223: while (stream == null) {
224: try {
225: RecordStore rs = RecordStore.openRecordStore(
226: RECORD_STORE_NAME, false);
227: byte[] adata = rs.getRecord(1);
228: rs.closeRecordStore();
229: stream = new ByteArrayInputStream(adata);
230:
231: break; // exit while loop
232: } catch (Exception ex) {
233: // record store not found
234: }
235:
236: if (created) {
237: // already tried to create record store!
238: throw new Exception(
239: "Could not create and open record store!");
240: }
241:
242: created = true;
243: createMyRecordStore(url, RECORD_STORE_NAME);
244: }
245:
246: String ctype = guessContentType(url);
247: player = Manager.createPlayer(stream, ctype);
248: }
249:
250: player.setLoopCount(-1);
251: } catch (Exception ex) {
252: if (player != null) {
253: player.close();
254: player = null;
255: }
256:
257: Alert alert = new Alert("Warning", "Cannot create player",
258: null, null);
259: alert.setTimeout(1000);
260: parentDisplay.setCurrent(alert);
261: }
262: }
263:
264: /**
265: * Create a record store for the given url
266: */
267: private void createMyRecordStore(String url, String name) {
268: try {
269: int idx = url.indexOf(':');
270: String loc = url.substring(idx + 1);
271: InputStream is = getClass().getResourceAsStream(loc);
272: ByteArrayOutputStream baos = new ByteArrayOutputStream();
273: byte[] tmp = new byte[1024];
274: int nread;
275:
276: while ((nread = is.read(tmp, 0, 1024)) > 0) {
277: baos.write(tmp, 0, nread);
278: }
279:
280: byte[] data = baos.toByteArray();
281:
282: is.close();
283:
284: // create a RecordStore
285: RecordStore rs = RecordStore.openRecordStore(name, true);
286: rs.addRecord(data, 0, data.length);
287: rs.closeRecordStore();
288: System.out.println("created record store '" + name
289: + "' with contents of " + loc);
290: } catch (Exception ex) {
291: ex.printStackTrace();
292: }
293: }
294:
295: public void paint(Graphics g) {
296: int w = getWidth();
297: int h = getHeight();
298:
299: g.setColor(0);
300: g.fillRect(0, 0, w, h);
301:
302: g.setColor(0xFF7f00);
303: g.drawString("Audio Player", w / 2, 8, Graphics.TOP
304: | Graphics.HCENTER);
305:
306: if (logo != null) {
307: g.drawImage(logo, w / 2, 30, Graphics.TOP
308: | Graphics.HCENTER);
309: }
310:
311: g.setColor(0xFF7f00);
312: g.drawString("Audio Player", w / 2, 8, Graphics.TOP
313: | Graphics.HCENTER);
314:
315: g.drawString(title, w / 2, 84, Graphics.TOP | Graphics.HCENTER);
316:
317: g.drawString(mtime, 0, 150, Graphics.TOP | Graphics.LEFT);
318: }
319:
320: public void run() {
321: /*
322: * method playSound() runs on GUI thread.
323: * Manager.createPlayer() will potentially invoke a blocking
324: * I/O. This is not the good practice recommended by MIDP
325: * programming style. So here we will create the
326: * Player in a separate thread.
327: */
328: createPlayer();
329:
330: if (player == null) {
331: // can't create player
332: synchronized (dThreadLock) {
333: dThread = null;
334: dThreadLock.notify();
335:
336: return;
337: }
338: }
339:
340: try {
341: player.realize();
342:
343: long dur = player.getDuration();
344:
345: if (dur != -1) {
346: title = title + " [" + timeFM(dur) + "]";
347: }
348:
349: player.start();
350: } catch (Exception ex) {
351: }
352:
353: // mtime update loop
354: while (!interrupted) {
355: try {
356: mtime = timeFM(player.getMediaTime());
357: repaint(0, 110, 100, 170);
358: Thread.sleep(100);
359: } catch (Exception ex) {
360: }
361:
362: // pause the loop if player paused
363: synchronized (pauseLock) {
364: if (paused) {
365: try {
366: pauseLock.wait();
367: } catch (InterruptedException ie) {
368: // nothing
369: }
370: }
371: }
372: }
373:
374: // terminating player and the thread
375: player.close();
376: player = null;
377:
378: synchronized (dThreadLock) {
379: dThread = null;
380: dThreadLock.notify();
381: }
382: }
383:
384: protected void keyPressed(int keycode) {
385: switch (keycode) {
386: case KEY_STAR:
387: changeVolume(-10);
388:
389: break;
390:
391: case KEY_POUND:
392: changeVolume(10);
393:
394: break;
395: }
396: }
397:
398: private void changeVolume(int diff) {
399: VolumeControl vc;
400:
401: if (player != null) {
402: vc = (VolumeControl) player.getControl("VolumeControl");
403:
404: if (vc != null) {
405: int cv = vc.getLevel();
406: cv += diff;
407: cv = vc.setLevel(cv);
408: }
409: }
410: }
411:
412: private String timeFM(long val) {
413: String ret = "";
414: int mval = (int) (val / 1000);
415: int sec = mval / 1000;
416: int min = sec / 60;
417:
418: if (min >= 10) {
419: ret = ret + min + ":";
420: } else if (min > 0) {
421: ret = "0" + min + ":";
422: } else {
423: ret = "00:";
424: }
425:
426: if (sec >= 10) {
427: ret = ret + sec + ".";
428: } else if (sec > 0) {
429: ret = ret + "0" + sec + ".";
430: } else {
431: ret = ret + "00.";
432: }
433:
434: mval = (mval % 1000) / 100;
435: ret = ret + mval;
436:
437: return (ret);
438: }
439: }
|