1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.media.session;
18
19import android.app.PendingIntent;
20import android.content.Context;
21import android.media.AudioAttributes;
22import android.media.AudioManager;
23import android.media.MediaMetadata;
24import android.media.Rating;
25import android.media.session.MediaController;
26import android.media.session.MediaSession;
27import android.media.session.PlaybackState;
28import android.os.Bundle;
29import android.os.Handler;
30import android.os.ResultReceiver;
31import android.view.KeyEvent;
32
33import java.util.ArrayList;
34import java.util.List;
35
36class MediaControllerCompatApi21 {
37    public static Object fromToken(Context context, Object sessionToken) {
38        return new MediaController(context, (MediaSession.Token) sessionToken);
39    }
40
41    public static Object createCallback(Callback callback) {
42        return new CallbackProxy<Callback>(callback);
43    }
44
45    public static void registerCallback(Object controllerObj, Object callbackObj, Handler handler) {
46        ((MediaController) controllerObj).registerCallback(
47                (MediaController.Callback)callbackObj, handler);
48    }
49
50    public static void unregisterCallback(Object controllerObj, Object callbackObj) {
51        ((MediaController) controllerObj)
52                .unregisterCallback((MediaController.Callback) callbackObj);
53    }
54
55    public static Object getTransportControls(Object controllerObj) {
56        return ((MediaController)controllerObj).getTransportControls();
57    }
58
59    public static Object getPlaybackState(Object controllerObj) {
60        return ((MediaController)controllerObj).getPlaybackState();
61    }
62
63    public static Object getMetadata(Object controllerObj) {
64        return ((MediaController)controllerObj).getMetadata();
65    }
66
67    public static List<Object> getQueue(Object controllerObj) {
68        List<MediaSession.QueueItem> queue = ((MediaController) controllerObj).getQueue();
69        if (queue == null) {
70            return null;
71        }
72        List<Object> queueObjs = new ArrayList<Object>(queue);
73        return queueObjs;
74    }
75
76    public static CharSequence getQueueTitle(Object controllerObj) {
77        return ((MediaController) controllerObj).getQueueTitle();
78    }
79
80    public static Bundle getExtras(Object controllerObj) {
81        return ((MediaController) controllerObj).getExtras();
82    }
83
84    public static int getRatingType(Object controllerObj) {
85        return ((MediaController) controllerObj).getRatingType();
86    }
87
88    public static long getFlags(Object controllerObj) {
89        return ((MediaController) controllerObj).getFlags();
90    }
91
92    public static Object getPlaybackInfo(Object controllerObj) {
93        return ((MediaController) controllerObj).getPlaybackInfo();
94    }
95
96    public static PendingIntent getSessionActivity(Object controllerObj) {
97        return ((MediaController) controllerObj).getSessionActivity();
98    }
99
100    public static boolean dispatchMediaButtonEvent(Object controllerObj, KeyEvent event) {
101        return ((MediaController) controllerObj).dispatchMediaButtonEvent(event);
102    }
103
104    public static void setVolumeTo(Object controllerObj, int value, int flags) {
105        ((MediaController) controllerObj).setVolumeTo(value, flags);
106    }
107
108    public static void adjustVolume(Object controllerObj, int direction, int flags) {
109        ((MediaController) controllerObj).adjustVolume(direction, flags);
110    }
111
112    public static void sendCommand(Object controllerObj,
113            String command, Bundle params, ResultReceiver cb) {
114        ((MediaController) controllerObj).sendCommand(command, params, cb);
115    }
116
117    public static String getPackageName(Object controllerObj) {
118        return ((MediaController) controllerObj).getPackageName();
119    }
120
121    public static class TransportControls {
122        public static void play(Object controlsObj) {
123            ((MediaController.TransportControls)controlsObj).play();
124        }
125
126        public static void pause(Object controlsObj) {
127            ((MediaController.TransportControls)controlsObj).pause();
128        }
129
130        public static void stop(Object controlsObj) {
131            ((MediaController.TransportControls)controlsObj).stop();
132        }
133
134        public static void seekTo(Object controlsObj, long pos) {
135            ((MediaController.TransportControls)controlsObj).seekTo(pos);
136        }
137
138        public static void fastForward(Object controlsObj) {
139            ((MediaController.TransportControls)controlsObj).fastForward();
140        }
141
142        public static void rewind(Object controlsObj) {
143            ((MediaController.TransportControls)controlsObj).rewind();
144        }
145
146        public static void skipToNext(Object controlsObj) {
147            ((MediaController.TransportControls)controlsObj).skipToNext();
148        }
149
150        public static void skipToPrevious(Object controlsObj) {
151            ((MediaController.TransportControls)controlsObj).skipToPrevious();
152        }
153
154        public static void setRating(Object controlsObj, Object ratingObj) {
155            ((MediaController.TransportControls)controlsObj).setRating((Rating)ratingObj);
156        }
157
158        public static void playFromMediaId(Object controlsObj, String mediaId, Bundle extras) {
159            ((MediaController.TransportControls) controlsObj).playFromMediaId(mediaId, extras);
160        }
161
162        public static void playFromSearch(Object controlsObj, String query, Bundle extras) {
163            ((MediaController.TransportControls) controlsObj).playFromSearch(query, extras);
164        }
165
166        public static void skipToQueueItem(Object controlsObj, long id) {
167            ((MediaController.TransportControls) controlsObj).skipToQueueItem(id);
168        }
169
170        public static void sendCustomAction(Object controlsObj, String action, Bundle args) {
171            ((MediaController.TransportControls) controlsObj).sendCustomAction(action, args);
172        }
173    }
174
175    public static class PlaybackInfo {
176        public static int getPlaybackType(Object volumeInfoObj) {
177            return ((MediaController.PlaybackInfo)volumeInfoObj).getPlaybackType();
178        }
179
180        public static AudioAttributes getAudioAttributes(Object volumeInfoObj) {
181            return ((MediaController.PlaybackInfo) volumeInfoObj).getAudioAttributes();
182        }
183
184        public static int getLegacyAudioStream(Object volumeInfoObj) {
185            AudioAttributes attrs = getAudioAttributes(volumeInfoObj);
186            return toLegacyStreamType(attrs);
187        }
188
189        public static int getVolumeControl(Object volumeInfoObj) {
190            return ((MediaController.PlaybackInfo)volumeInfoObj).getVolumeControl();
191        }
192
193        public static int getMaxVolume(Object volumeInfoObj) {
194            return ((MediaController.PlaybackInfo)volumeInfoObj).getMaxVolume();
195        }
196
197        public static int getCurrentVolume(Object volumeInfoObj) {
198            return ((MediaController.PlaybackInfo)volumeInfoObj).getCurrentVolume();
199        }
200
201        // This is copied from AudioAttributes.toLegacyStreamType. TODO This
202        // either needs to be kept in sync with that one or toLegacyStreamType
203        // needs to be made public so it can be used by the support lib.
204        private static final int FLAG_SCO = 0x1 << 2;
205        private static final int STREAM_BLUETOOTH_SCO = 6;
206        private static final int STREAM_SYSTEM_ENFORCED = 7;
207        private static int toLegacyStreamType(AudioAttributes aa) {
208            // flags to stream type mapping
209            if ((aa.getFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
210                    == AudioAttributes.FLAG_AUDIBILITY_ENFORCED) {
211                return STREAM_SYSTEM_ENFORCED;
212            }
213            if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
214                return STREAM_BLUETOOTH_SCO;
215            }
216
217            // usage to stream type mapping
218            switch (aa.getUsage()) {
219                case AudioAttributes.USAGE_MEDIA:
220                case AudioAttributes.USAGE_GAME:
221                case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
222                case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
223                    return AudioManager.STREAM_MUSIC;
224                case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
225                    return AudioManager.STREAM_SYSTEM;
226                case AudioAttributes.USAGE_VOICE_COMMUNICATION:
227                    return AudioManager.STREAM_VOICE_CALL;
228                case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
229                    return AudioManager.STREAM_DTMF;
230                case AudioAttributes.USAGE_ALARM:
231                    return AudioManager.STREAM_ALARM;
232                case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
233                    return AudioManager.STREAM_RING;
234                case AudioAttributes.USAGE_NOTIFICATION:
235                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
236                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
237                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
238                case AudioAttributes.USAGE_NOTIFICATION_EVENT:
239                    return AudioManager.STREAM_NOTIFICATION;
240                case AudioAttributes.USAGE_UNKNOWN:
241                default:
242                    return AudioManager.STREAM_MUSIC;
243            }
244        }
245    }
246
247    public static interface Callback {
248        public void onSessionDestroyed();
249        public void onSessionEvent(String event, Bundle extras);
250        public void onPlaybackStateChanged(Object stateObj);
251        public void onMetadataChanged(Object metadataObj);
252    }
253
254    static class CallbackProxy<T extends Callback> extends MediaController.Callback {
255        protected final T mCallback;
256
257        public CallbackProxy(T callback) {
258            mCallback = callback;
259        }
260
261        @Override
262        public void onSessionDestroyed() {
263            mCallback.onSessionDestroyed();
264        }
265
266        @Override
267        public void onSessionEvent(String event, Bundle extras) {
268            mCallback.onSessionEvent(event, extras);
269        }
270
271        @Override
272        public void onPlaybackStateChanged(PlaybackState state) {
273            mCallback.onPlaybackStateChanged(state);
274        }
275
276        @Override
277        public void onMetadataChanged(MediaMetadata metadata) {
278            mCallback.onMetadataChanged(metadata);
279        }
280    }
281}
282