PlayerSession.java revision dba34ba35cd2042d9a8fecfda56e2abe7a680bad
18ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik/*
28ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Copyright (C) 2014 The Android Open Source Project
38ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
48ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Licensed under the Apache License, Version 2.0 (the "License");
58ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * you may not use this file except in compliance with the License.
68ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * You may obtain a copy of the License at
78ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
88ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *      http://www.apache.org/licenses/LICENSE-2.0
98ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Unless required by applicable law or agreed to in writing, software
118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * distributed under the License is distributed on an "AS IS" BASIS,
128ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * See the License for the specific language governing permissions and
148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * limitations under the License.
158ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik */
16bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpackage com.android.onemedia;
17bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
18bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Context;
19bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Intent;
2007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.Route;
2107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.RouteInfo;
2207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.RouteOptions;
2307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.RoutePlaybackControls;
2442ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSession;
2542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSessionManager;
268ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.media.session.PlaybackState;
27bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.Bundle;
28bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.util.Log;
29bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.view.KeyEvent;
30bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
31bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport com.android.onemedia.playback.LocalRenderer;
3207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport com.android.onemedia.playback.OneMRPRenderer;
33bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport com.android.onemedia.playback.Renderer;
3407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport com.android.onemedia.playback.RequestUtils;
3507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
3607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport java.util.ArrayList;
37bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
38bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpublic class PlayerSession {
398ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    private static final String TAG = "PlayerSession";
40bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
4142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    protected MediaSession mSession;
42bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    protected Context mContext;
4307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected Renderer mRenderer;
4442ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    protected MediaSession.Callback mCallback;
458ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected Renderer.Listener mRenderListener;
468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
478ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected PlaybackState mPlaybackState;
488ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected Listener mListener;
4907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected ArrayList<RouteOptions> mRouteOptions;
5007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected Route mRoute;
5107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected RoutePlaybackControls mRouteControls;
5207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected RouteListener mRouteListener;
5307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
5407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    private String mContent;
55bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
56bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public PlayerSession(Context context) {
57bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mContext = context;
58bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer = new LocalRenderer(context, null);
5907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mCallback = new SessionCb();
60bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderListener = new RenderListener();
618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        mPlaybackState = new PlaybackState();
628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
638ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                | PlaybackState.ACTION_PLAY);
64bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
65bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.registerListener(mRenderListener);
6607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
6707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        // TODO need an easier way to build route options
6807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mRouteOptions = new ArrayList<RouteOptions>();
6907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        RouteOptions.Builder bob = new RouteOptions.Builder();
7007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        bob.addInterface(RoutePlaybackControls.NAME);
7107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mRouteOptions.add(bob.build());
7207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mRouteListener = new RouteListener();
73bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
74bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
75bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void createSession() {
76bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (mSession != null) {
77bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mSession.release();
78bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
7942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik        MediaSessionManager man = (MediaSessionManager) mContext
80bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                .getSystemService(Context.MEDIA_SESSION_SERVICE);
81bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
82bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mSession = man.createSession("OneMedia");
83bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mSession.addCallback(mCallback);
84b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik        mSession.addTransportControlsCallback(new TransportCallback());
85c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik        mSession.setPlaybackState(mPlaybackState);
8642ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik        mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
8707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mSession.setRouteOptions(mRouteOptions);
88a8f951462791a16f47e8c07e552232f31dcefac5RoboErik        mSession.setActive(true);
89bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
90bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
91bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void onDestroy() {
92bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (mSession != null) {
93bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mSession.release();
94bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
95bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (mRenderer != null) {
96bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mRenderer.unregisterListener(mRenderListener);
97bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mRenderer.onDestroy();
98bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
99bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
100bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
1018ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    public void setListener(Listener listener) {
1028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        mListener = listener;
1038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
1048ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
105dba34ba35cd2042d9a8fecfda56e2abe7a680badJeff Brown    public MediaSession.Token getSessionToken() {
106bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        return mSession.getSessionToken();
107bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
108bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
109bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setContent(Bundle request) {
110bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.setContent(request);
11107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mContent = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
112bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
113bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
114bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setNextContent(Bundle request) {
115bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.setNextContent(request);
116bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
117bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
11807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    private void updateState(int newState) {
11979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik        float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0;
120f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik        long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
121f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik        mPlaybackState.setState(newState, position, rate);
122c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik        mSession.setPlaybackState(mPlaybackState);
12307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    }
12407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
1258ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    public interface Listener {
1268ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlayStateChanged(PlaybackState state);
1278ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
1288ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
1298ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    private class RenderListener implements Renderer.Listener {
130bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
131bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
132bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onError(int type, int extra, Bundle extras, Throwable error) {
1338ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
13479fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik            mPlaybackState.setState(PlaybackState.STATE_ERROR, -1, 0);
1358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (error != null) {
1368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mPlaybackState.setErrorMessage(error.getLocalizedMessage());
1378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
138c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
1398ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
1408ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
1418ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
142bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
143bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
144bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
145bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onStateChanged(int newState) {
1468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (newState != Renderer.STATE_ERROR) {
1478ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mPlaybackState.setErrorMessage(null);
1488ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
149f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            long position = -1;
150f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            if (mRenderer != null) {
151f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik                position = mRenderer.getSeekPosition();
152f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            }
1538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            switch (newState) {
1548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_ENDED:
1558ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_STOPPED:
15679fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0);
1578ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_INIT:
1598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PREPARING:
16079fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0);
1618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_ERROR:
16379fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
1648ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1658ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PAUSED:
16679fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
1678ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PLAYING:
16979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1);
1708ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1718ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                default:
17279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                    mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
1738ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    mPlaybackState.setErrorMessage("unkown state");
1748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
176c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
1778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
1788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
1798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
180bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
181bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
182bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
183bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onBufferingUpdate(int percent) {
184bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
185bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
186bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
187bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onFocusLost() {
1888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
189f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
19079fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik            mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
191c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
1928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
1938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
1948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
195bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
196bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
197bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
198bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onNextStarted() {
199bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
200bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
201bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
202bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
20342ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    private class SessionCb extends MediaSession.Callback {
204bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
20579fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik        public void onMediaButtonEvent(Intent mediaRequestIntent) {
206bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            if (Intent.ACTION_MEDIA_BUTTON.equals(mediaRequestIntent.getAction())) {
207bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                KeyEvent event = (KeyEvent) mediaRequestIntent
208bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        .getParcelableExtra(Intent.EXTRA_KEY_EVENT);
209bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                switch (event.getKeyCode()) {
210bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                    case KeyEvent.KEYCODE_MEDIA_PLAY:
211bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        Log.d(TAG, "play button received");
212bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        mRenderer.onPlay();
213bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        break;
214bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                    case KeyEvent.KEYCODE_MEDIA_PAUSE:
215bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        Log.d(TAG, "pause button received");
216bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        mRenderer.onPause();
217bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                        break;
218bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                }
219bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            }
220bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
22107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
22207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        @Override
22307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        public void onRequestRouteChange(RouteInfo route) {
22407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            if (mRenderer != null) {
22507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mRenderer.onStop();
22607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            }
22707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            if (route == null) {
22807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                // Use local route
22907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mRoute = null;
23007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mRenderer = new LocalRenderer(mContext, null);
23107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mRenderer.registerListener(mRenderListener);
23279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                updateState(PlaybackState.STATE_NONE);
23307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            } else {
23407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                // Use remote route
23507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mSession.connect(route, mRouteOptions.get(0));
23607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik                mRenderer = null;
23779fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik                updateState(PlaybackState.STATE_CONNECTING);
23807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            }
23907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        }
24007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
24107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        @Override
24207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        public void onRouteConnected(Route route) {
24307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            mRoute = route;
24407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            mRouteControls = RoutePlaybackControls.from(route);
24507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            mRouteControls.addListener(mRouteListener);
24607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            Log.d(TAG, "Connected to route, registering listener");
24707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            mRenderer = new OneMRPRenderer(mRouteControls);
24879fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik            updateState(PlaybackState.STATE_NONE);
24907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        }
25007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
25107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        @Override
25207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        public void onRouteDisconnected(Route route, int reason) {
25307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
25407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        }
255bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
256bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
257b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik    private class TransportCallback extends MediaSession.TransportControlsCallback {
2588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        @Override
2598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlay() {
2608ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mRenderer.onPlay();
2618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
2628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
2638ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        @Override
2648ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPause() {
2658ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mRenderer.onPause();
2668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
2678ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
2688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
26907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    private class RouteListener extends RoutePlaybackControls.Listener {
27007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        @Override
27107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        public void onPlaybackStateChange(int state) {
27207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            Log.d(TAG, "Updating state to " + state);
27307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik            updateState(state);
27407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        }
27507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    }
27607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
277bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik}
278