PlayerController.java revision ff0215dd64e5fd4ff366930747e7943fcc40c4ab
1bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
28ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik/*
38ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Copyright (C) 2014 The Android Open Source Project
48ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
58ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Licensed under the Apache License, Version 2.0 (the "License");
68ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * you may not use this file except in compliance with the License.
78ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * You may obtain a copy of the License at
88ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
98ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *      http://www.apache.org/licenses/LICENSE-2.0
108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Unless required by applicable law or agreed to in writing, software
128ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * distributed under the License is distributed on an "AS IS" BASIS,
138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * See the License for the specific language governing permissions and
158ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * limitations under the License.
168ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik */
17bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpackage com.android.onemedia;
18bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
1942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.MediaMetadata;
2042ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaController;
2142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSessionManager;
228ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.media.session.PlaybackState;
238ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.Bundle;
24bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.Handler;
25bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.IBinder;
26bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.RemoteException;
27bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.ComponentName;
28bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Context;
29bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Intent;
30bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.ServiceConnection;
31bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.util.Log;
32bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
33bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport com.android.onemedia.playback.RequestUtils;
34bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
35bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpublic class PlayerController {
368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    private static final String TAG = "PlayerController";
37bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
38bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public static final int STATE_DISCONNECTED = 0;
39bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public static final int STATE_CONNECTED = 1;
40bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
4142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    protected MediaController mController;
42bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    protected IPlayerService mBinder;
43c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik    protected MediaController.TransportControls mTransportControls;
44bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
45bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private final Intent mServiceIntent;
46bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private Context mContext;
47bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private Listener mListener;
48bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private SessionCallback mControllerCb;
4942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    private MediaSessionManager mManager;
50bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private Handler mHandler = new Handler();
51bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
52bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private boolean mResumed;
53bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
54bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public PlayerController(Context context, Intent serviceIntent) {
55bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mContext = context;
56bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (serviceIntent == null) {
57bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mServiceIntent = new Intent(mContext, PlayerService.class);
58bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        } else {
59bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mServiceIntent = serviceIntent;
60bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
61bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mControllerCb = new SessionCallback();
6242ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik        mManager = (MediaSessionManager) context
63bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                .getSystemService(Context.MEDIA_SESSION_SERVICE);
64bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
65bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mResumed = false;
66bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
67bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
68bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setListener(Listener listener) {
69bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mListener = listener;
70bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        Log.d(TAG, "Listener set to " + listener + " session is " + mController);
71bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (mListener != null) {
72bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mHandler = new Handler();
738ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mListener.onConnectionStateChange(
74bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                    mController == null ? STATE_DISCONNECTED : STATE_CONNECTED);
75bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
76bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
77bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
78bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void onResume() {
79bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mResumed = true;
80bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        Log.d(TAG, "onResume. Binding to service with intent " + mServiceIntent.toString());
81bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        bindToService();
82bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
83bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
84bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void onPause() {
85bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mResumed = false;
86bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        Log.d(TAG, "onPause, unbinding from service");
87bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        unbindFromService();
88bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
89bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
90bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void play() {
918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        if (mTransportControls != null) {
928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mTransportControls.play();
938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
94bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
95bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
96bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void pause() {
978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        if (mTransportControls != null) {
988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mTransportControls.pause();
998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
100bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
101bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
102bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setContent(String source) {
103bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder();
104bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        bob.setSource(source);
105bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        try {
106bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mBinder.sendRequest(RequestUtils.ACTION_SET_CONTENT, bob.build(), null);
107bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        } catch (RemoteException e) {
108bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            Log.d(TAG, "setContent failed, service may have died.", e);
109bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
110bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
111bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
112bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setNextContent(String source) {
113bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder();
114bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        bob.setSource(source);
115bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        try {
116bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mBinder.sendRequest(RequestUtils.ACTION_SET_NEXT_CONTENT, bob.build(), null);
117bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        } catch (RemoteException e) {
118bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            Log.d(TAG, "setNexctContent failed, service may have died.", e);
119bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
120bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
121bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
12207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    public void showRoutePicker() {
123ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown        // TODO
12407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    }
12507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
126bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private void unbindFromService() {
127bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mContext.unbindService(mServiceConnection);
128bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
129bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
130bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private void bindToService() {
131bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mContext.bindService(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
132bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
133bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
134bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    private ServiceConnection mServiceConnection = new ServiceConnection() {
135bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
136bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onServiceDisconnected(ComponentName name) {
137bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            if (mController != null) {
138bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                mController.removeCallback(mControllerCb);
139bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
140bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mBinder = null;
141bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mController = null;
1428ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mTransportControls = null;
143bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            Log.d(TAG, "Disconnected from PlayerService");
144bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
145bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            if (mListener != null) {
1468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onConnectionStateChange(STATE_DISCONNECTED);
147bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
148bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
149bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
150bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
151bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onServiceConnected(ComponentName name, IBinder service) {
152bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mBinder = IPlayerService.Stub.asInterface(service);
153bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            Log.d(TAG, "service is " + service + " binder is " + mBinder);
154bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            try {
15542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik                mController = MediaController.fromToken(mBinder.getSessionToken());
156bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            } catch (RemoteException e) {
157bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                Log.e(TAG, "Error getting session", e);
158bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                return;
159bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
160bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mController.addCallback(mControllerCb, mHandler);
161c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mTransportControls = mController.getTransportControls();
162bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            Log.d(TAG, "Ready to use PlayerService");
163bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
164bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            if (mListener != null) {
1658ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onConnectionStateChange(STATE_CONNECTED);
1668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                if (mTransportControls != null) {
167c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik                    mListener.onPlaybackStateChange(mController.getPlaybackState());
1688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                }
169bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
170bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
171bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    };
172bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
17342ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    private class SessionCallback extends MediaController.Callback {
174bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
1758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlaybackStateChanged(PlaybackState state) {
1768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (state == null) {
1778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                return;
1788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
1798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Received playback state change to state " + state.getState());
180bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            if (mListener != null) {
1818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlaybackStateChange(state);
182bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
183bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
1848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
1858ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        @Override
1868ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onMetadataChanged(MediaMetadata metadata) {
1878ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (metadata == null) {
1888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                return;
1898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
1908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Received metadata change, title is "
1918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    + metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
1928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
193bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
194bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
195bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public interface Listener {
1968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlaybackStateChange(PlaybackState state);
1978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onMetadataChange(MediaMetadata metadata);
1988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onConnectionStateChange(int state);
199bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
200bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
201bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik}
202