blob: 83c4bc0bdac6d2ed1aeaffcced98c1a33f8317bb [file] [log] [blame]
package com.googlecode.android_scripting.facade.media;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.SessionListener;
import android.media.session.PlaybackState;
import android.media.session.MediaSession.Callback;
import android.view.KeyEvent;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.MainThread;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcParameter;
/**
* Expose functionalities of MediaSession related classes
* like MediaSession, MediaSessionManager, MediaController.
*
*/
public class MediaSessionFacade extends RpcReceiver {
private final Service mService;
private final EventFacade mEventFacade;
private final MediaSession mSession;
private final MediaSessionManager mManager;
private final SessionListener mSessionListener;
private final Callback mCallback;
private List<MediaController> mActiveControllers = null;
public MediaSessionFacade(FacadeManager manager) {
super(manager);
mService = manager.getService();
mEventFacade = manager.getReceiver(EventFacade.class);
Log.d("Creating MediaSession.");
mSession = new MediaSession(mService, "SL4A");
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
mManager = (MediaSessionManager) mService.getSystemService(Context.MEDIA_SESSION_SERVICE);
mCallback = new MediaButtonCallback(mEventFacade);
mSessionListener = new MediaSessionListener(mService);
mManager.addActiveSessionsListener(mSessionListener,
new ComponentName(mService.getPackageName(), this.getClass().getName()));
mSession.setActive(true);
}
private class MediaSessionListener extends SessionListener {
public MediaSessionListener(Context context) {
super(context);
}
@Override
public void onActiveSessionsChanged(List<MediaController> controllers) {
Log.d("Active MediaSessions have changed. Update current controller.");
int size = controllers.size();
for (int i = 0; i < size; i++) {
MediaController controller = controllers.get(i);
long flags = controller.getFlags();
// We only care about sessions that handle transport controls,
// which will be true for apps using RCC
if ((flags & MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS) != 0) {
Log.d("The current active MediaSessions is " + controller.getTag());
return;
}
}
}
}
@Rpc(description = "Retrieve a list of active sessions.")
public List<String> mediaGetActiveSessions() {
mActiveControllers = mManager.getActiveSessions(null);
List<String> results = new ArrayList<String>();
for (MediaController mc : mActiveControllers) {
results.add(mc.getTag());
}
return results;
}
@Rpc(description = "Add callback to media session.")
public void mediaSessionAddCallback() {
MainThread.run(mService, new Callable<Object>() {
@Override
public Object call() throws Exception {
Log.d("Adding callback.");
mSession.setCallback(mCallback);
PlaybackState.Builder bob = new PlaybackState.Builder();
bob.setActions(PlaybackState.ACTION_PLAY |
PlaybackState.ACTION_PAUSE |
PlaybackState.ACTION_STOP);
bob.setState(PlaybackState.STATE_PLAYING, 0, 1);
mSession.setPlaybackState(bob.build());
return null;
}
});
}
@Rpc(description = "Whether current media session is active.")
public Boolean mediaSessionIsActive() {
return mSession.isActive();
}
@Rpc(description = "Simulate a media key press.")
public void mediaDispatchMediaKeyEvent(String key) {
int keyCode;
if (key.equals("Play")) {
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
} else if (key.equals("Pause")) {
keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE;
} else if (key.equals("Stop")) {
keyCode = KeyEvent.KEYCODE_MEDIA_STOP;
} else if (key.equals("Next")) {
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
} else if (key.equals("Previous")) {
keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
} else if (key.equals("Forward")) {
keyCode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
} else if (key.equals("Rewind")) {
keyCode = KeyEvent.KEYCODE_MEDIA_REWIND;
} else {
Log.d("Unrecognized media key.");
return;
}
KeyEvent keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
mManager.dispatchMediaKeyEvent(keyDown);
mManager.dispatchMediaKeyEvent(keyUp);
}
private MediaController getMediaController(int idx) {
return mActiveControllers.get(idx);
}
@Rpc(description = "Call Play on the currently active media session.")
public void mediaSessionPlay(@RpcParameter(name = "index") @RpcDefault(value = "0")
Integer idx) {
getMediaController(idx).getTransportControls().play();
}
@Rpc(description = "Call Pause on the currently active media session.")
public void mediaSessionPause(@RpcParameter(name = "index") @RpcDefault(value = "0")
Integer idx) {
getMediaController(idx).getTransportControls().pause();
}
@Rpc(description = "Call Stop on the currently active media session.")
public void mediaSessionStop(@RpcParameter(name = "index") @RpcDefault(value = "0")
Integer idx) {
getMediaController(idx).getTransportControls().stop();
}
@Rpc(description = "Call Next on the currently active media session.")
public void mediaSessionNext(@RpcParameter(name = "index") @RpcDefault(value = "0")
Integer idx) {
getMediaController(idx).getTransportControls().skipToNext();
}
@Override
public void shutdown() {
mSession.setCallback(null);
mSession.release();
}
}