19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 2f04335f899f2cce69f843692a3cb9cec229683c2tturney * Copyright (C) 2017 The Android Open Source Project 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4f04335f899f2cce69f843692a3cb9cec229683c2tturney * Licensed under the Apache License, Version 2.0 (the "License"); 5f04335f899f2cce69f843692a3cb9cec229683c2tturney * you may not use this file except in compliance with the License. 6f04335f899f2cce69f843692a3cb9cec229683c2tturney * You may obtain a copy of the License at 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 8f04335f899f2cce69f843692a3cb9cec229683c2tturney * http://www.apache.org/licenses/LICENSE-2.0 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 11f04335f899f2cce69f843692a3cb9cec229683c2tturney * distributed under the License is distributed on an "AS IS" BASIS, 12f04335f899f2cce69f843692a3cb9cec229683c2tturney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f04335f899f2cce69f843692a3cb9cec229683c2tturney * See the License for the specific language governing permissions and 14f04335f899f2cce69f843692a3cb9cec229683c2tturney * limitations under the License. 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage com.googlecode.android_scripting.facade.media; 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.app.Service; 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.media.MediaPlayer; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.net.Uri; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.facade.EventFacade; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.facade.FacadeManager; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.jsonrpc.RpcReceiver; 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.rpc.Rpc; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.rpc.RpcDefault; 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.rpc.RpcParameter; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.HashMap; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Hashtable; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Map; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Set; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Map.Entry; 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * This facade exposes basic mediaPlayer functionality. <br> 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <br> 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <b>Usage Notes:</b><br> 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * mediaPlayerFacade maintains a list of media streams, identified by a user supplied tag. If the 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * tag is null or blank, this tag defaults to "default"<br> 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Basic operation is: mediaPlayOpen("file:///sdcard/MP3/sample.mp3","mytag",true)<br> 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * This will look for a media file at /sdcard/MP3/sample.mp3. Other urls should work. If the file 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * exists and is playable, this will return a true otherwise it will return a false. <br> 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * If play=true, then the media file will play immediately, otherwise it will wait for a 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * {@link #mediaPlayStart mediaPlayerStart} command. <br> 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * When done with the resource, use {@link #mediaPlayClose mediaPlayClose} <br> 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * You can get information about the loaded media with {@link #mediaPlayInfo mediaPlayInfo} This 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * returns a map with the following elements: 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <ul> 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"tag" - user supplied tag identifying this mediaPlayer. 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"loaded" - true if loaded, false if not. If false, no other elements are returned. 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"duration" - length of the media in milliseconds. 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"position" - current position of playback in milliseconds. Controlled by 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * {@link #mediaPlaySeek mediaPlaySeek} 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"isplaying" - shows whether media is playing. Controlled by {@link #mediaPlayPause 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * mediaPlayPause} and {@link #mediaPlayStart mediaPlayStart} 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"url" - the url used to open this media. 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>"looping" - whether media will loop. Controlled by {@link #mediaPlaySetLooping 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * mediaPlaySetLooping} 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * </ul> 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <br> 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * You can use {@link #mediaPlayList mediaPlayList} to get a list of the loaded tags. <br> 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * {@link #mediaIsPlaying mediaIsPlaying} will return true if the media is playing.<br> 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <b>Events:</b><br> 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * A playing media will throw a <b>"media"</b> event on completion. NB: In remote mode, a media file 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * will continue playing after the script has finished unless an explicit {@link #mediaPlayClose 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * mediaPlayClose} event is called. 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class MediaPlayerFacade extends RpcReceiver implements MediaPlayer.OnCompletionListener { 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Service mService; 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li static private final Map<String, MediaPlayer> mPlayers = new Hashtable<String, MediaPlayer>(); 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li static private final Map<String, String> mUrls = new Hashtable<String, String>(); 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final EventFacade mEventFacade; 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public MediaPlayerFacade(FacadeManager manager) { 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(manager); 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService = manager.getService(); 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade = manager.getReceiver(EventFacade.class); 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private String getDefault(String tag) { 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return (tag == null || tag.equals("")) ? "default" : tag; 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private MediaPlayer getPlayer(String tag) { 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li tag = getDefault(tag); 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mPlayers.get(tag); 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private String getUrl(String tag) { 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li tag = getDefault(tag); 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mUrls.get(tag); 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void putMp(String tag, MediaPlayer player, String url) { 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li tag = getDefault(tag); 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPlayers.put(tag, player); 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mUrls.put(tag, url); 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void removeMp(String tag) { 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li tag = getDefault(tag); 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = mPlayers.get(tag); 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player != null) { 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.stop(); 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.release(); 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPlayers.remove(tag); 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mUrls.remove(tag); 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Open a media file", returns = "true if play successful") 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlayOpen(@RpcParameter(name = "url", 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li description = "url of media resource") 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String url, @RpcParameter(name = "tag", description = "string identifying resource") 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag, @RpcParameter(name = "play", description = "start playing immediately") 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "true") 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Boolean play) { 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li removeMp(tag); 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player = MediaPlayer.create(mService, Uri.parse(url)); 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player != null) { 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li putMp(tag, player, url); 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.setOnCompletionListener(this); 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (play) { 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.start(); 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return player != null; 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "pause playing media file", returns = "true if successful") 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlayPause( 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.pause(); 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Start playing media file.", returns = "true if successful") 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlayStart( 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.start(); 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mediaIsPlaying(tag); 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Stop playing media file.", returns = "true if successful") 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlayStop( 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.stop(); 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return !mediaIsPlaying(tag) && player.getCurrentPosition() == 0; 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Stop all players.") 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void mediaPlayStopAll() { 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (MediaPlayer p : mPlayers.values()) { 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li p.stop(); 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Seek To Position", returns = "New Position (in ms)") 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized int mediaPlaySeek(@RpcParameter(name = "msec", 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li description = "Position in millseconds") 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Integer msec, @RpcParameter(name = "tag", description = "string identifying resource") 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return 0; 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.seekTo(msec); 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return player.getCurrentPosition(); 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Close media file", returns = "true if successful") 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlayClose( 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) throws Exception { 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!mPlayers.containsKey(tag)) { 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li removeMp(tag); 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Checks if media file is playing.", returns = "true if playing") 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaIsPlaying( 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return (player == null) ? false : player.isPlaying(); 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Information on current media", returns = "Media Information") 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized Map<String, Object> mediaPlayGetInfo( 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, Object> result = new HashMap<String, Object>(); 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("tag", getDefault(tag)); 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("loaded", false); 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("loaded", true); 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("duration", player.getDuration()); 2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("position", player.getCurrentPosition()); 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("isplaying", player.isPlaying()); 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("url", getUrl(tag)); 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result.put("looping", player.isLooping()); 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return result; 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Lists currently loaded media", returns = "List of Media Tags") 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Set<String> mediaPlayList() { 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mPlayers.keySet(); 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Set Looping", returns = "True if successful") 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized boolean mediaPlaySetLooping(@RpcParameter(name = "enabled") 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "true") 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Boolean enabled, @RpcParameter(name = "tag", description = "string identifying resource") 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag) { 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.setLooping(enabled); 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Checks if media file is playing.", returns = "true if playing") 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void mediaSetNext( 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "tag", description = "string identifying resource") 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcDefault(value = "default") 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag, 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "next", description = "tag of the next track to play.") 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String next) { 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = getPlayer(tag); 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer nPlayer = getPlayer(next); 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player == null) { 2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new NullPointerException("Non-existent player tag " + tag); 2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (nPlayer == null) { 2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new NullPointerException("Non-existent player tag " + next); 2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.setNextMediaPlayer(nPlayer); 2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public synchronized void shutdown() { 2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (String key : mPlayers.keySet()) { 2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MediaPlayer player = mPlayers.get(key); 2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (player != null) { 2829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.stop(); 2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player.release(); 2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li player = null; 2859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPlayers.clear(); 2889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mUrls.clear(); 2899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onCompletion(MediaPlayer player) { 2939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String tag = getTag(player); 2949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (tag != null) { 2959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Map<String, Object> data = new HashMap<String, Object>(); 2969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li data.put("action", "complete"); 2979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li data.put("tag", tag); 2989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("media", data); 2999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private String getTag(MediaPlayer player) { 3039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (Entry<String, MediaPlayer> m : mPlayers.entrySet()) { 3049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (m.getValue() == player) { 3059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return m.getKey(); 3069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 3099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 311