ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Committer:
TMBOY
Date:
Tue Jul 18 16:34:48 2017 +0800
Revision:
45:2aa9f933c8d2
?

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TMBOY 45:2aa9f933c8d2 1 /*
TMBOY 45:2aa9f933c8d2 2 * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
TMBOY 45:2aa9f933c8d2 3 *
TMBOY 45:2aa9f933c8d2 4 * Licensed under the Apache License, Version 2.0 (the "License");
TMBOY 45:2aa9f933c8d2 5 * you may not use this file except in compliance with the License.
TMBOY 45:2aa9f933c8d2 6 * You may obtain a copy of the License at
TMBOY 45:2aa9f933c8d2 7 *
TMBOY 45:2aa9f933c8d2 8 * http://www.apache.org/licenses/LICENSE-2.0
TMBOY 45:2aa9f933c8d2 9 *
TMBOY 45:2aa9f933c8d2 10 * Unless required by applicable law or agreed to in writing, software
TMBOY 45:2aa9f933c8d2 11 * distributed under the License is distributed on an "AS IS" BASIS,
TMBOY 45:2aa9f933c8d2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
TMBOY 45:2aa9f933c8d2 13 * See the License for the specific language governing permissions and
TMBOY 45:2aa9f933c8d2 14 * limitations under the License.
TMBOY 45:2aa9f933c8d2 15 */
TMBOY 45:2aa9f933c8d2 16 package com.baidu.duer.dcs.devicemodule.audioplayer;
TMBOY 45:2aa9f933c8d2 17
TMBOY 45:2aa9f933c8d2 18 import com.baidu.duer.dcs.devicemodule.audioplayer.message.ClearQueuePayload;
TMBOY 45:2aa9f933c8d2 19 import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
TMBOY 45:2aa9f933c8d2 20 import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStatePayload;
TMBOY 45:2aa9f933c8d2 21 import com.baidu.duer.dcs.devicemodule.audioplayer.message.StopPayload;
TMBOY 45:2aa9f933c8d2 22 import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayStateReport;
TMBOY 45:2aa9f933c8d2 23 import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerProgressReporter;
TMBOY 45:2aa9f933c8d2 24 import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerTimer;
TMBOY 45:2aa9f933c8d2 25 import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
TMBOY 45:2aa9f933c8d2 26 import com.baidu.duer.dcs.framework.BaseDeviceModule;
TMBOY 45:2aa9f933c8d2 27 import com.baidu.duer.dcs.framework.IMessageSender;
TMBOY 45:2aa9f933c8d2 28 import com.baidu.duer.dcs.framework.message.ClientContext;
TMBOY 45:2aa9f933c8d2 29 import com.baidu.duer.dcs.framework.message.Directive;
TMBOY 45:2aa9f933c8d2 30 import com.baidu.duer.dcs.framework.message.Header;
TMBOY 45:2aa9f933c8d2 31 import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
TMBOY 45:2aa9f933c8d2 32 import com.baidu.duer.dcs.util.LogUtil;
TMBOY 45:2aa9f933c8d2 33
TMBOY 45:2aa9f933c8d2 34 import java.util.ArrayList;
TMBOY 45:2aa9f933c8d2 35 import java.util.Collections;
TMBOY 45:2aa9f933c8d2 36 import java.util.LinkedList;
TMBOY 45:2aa9f933c8d2 37 import java.util.List;
TMBOY 45:2aa9f933c8d2 38
TMBOY 45:2aa9f933c8d2 39 /**
TMBOY 45:2aa9f933c8d2 40 * 音乐播放的端能力实现,处理指令:Play,Stop,ClearQueue
TMBOY 45:2aa9f933c8d2 41 * <p>
TMBOY 45:2aa9f933c8d2 42 * Created by guxiuzhong@baidu.com on 2017/5/31.
TMBOY 45:2aa9f933c8d2 43 */
TMBOY 45:2aa9f933c8d2 44 public class AudioPlayerDeviceModule extends BaseDeviceModule {
TMBOY 45:2aa9f933c8d2 45 private static final String TAG = AudioPlayerDeviceModule.class.getSimpleName();
TMBOY 45:2aa9f933c8d2 46 // 播放列表,先进先出
TMBOY 45:2aa9f933c8d2 47 private LinkedList<PlayPayload.Stream> playQueue = new LinkedList<>();
TMBOY 45:2aa9f933c8d2 48 // 当前stream的token
TMBOY 45:2aa9f933c8d2 49 private String latestStreamToken = "";
TMBOY 45:2aa9f933c8d2 50 // 当前manager的播放器
TMBOY 45:2aa9f933c8d2 51 private IMediaPlayer mediaPlayer;
TMBOY 45:2aa9f933c8d2 52 // 播放上报
TMBOY 45:2aa9f933c8d2 53 private AudioPlayStateReport audioPlayStateReport;
TMBOY 45:2aa9f933c8d2 54 // 开始时的缓冲时间
TMBOY 45:2aa9f933c8d2 55 private long bufferingStartMilliseconds;
TMBOY 45:2aa9f933c8d2 56 // 结束时的缓冲时间
TMBOY 45:2aa9f933c8d2 57 private long bufferingEndMilliseconds;
TMBOY 45:2aa9f933c8d2 58 // 用来统计状态的时间间隔offsetInMilliseconds
TMBOY 45:2aa9f933c8d2 59 private AudioPlayerTimer timer;
TMBOY 45:2aa9f933c8d2 60 // 播放状态的上报eg:暂停,完成等
TMBOY 45:2aa9f933c8d2 61 private AudioPlayerProgressReporter progressReporter;
TMBOY 45:2aa9f933c8d2 62 // 回调接口
TMBOY 45:2aa9f933c8d2 63 private List<IMediaPlayer.IMediaPlayerListener> audioPlayerListeners;
TMBOY 45:2aa9f933c8d2 64
TMBOY 45:2aa9f933c8d2 65 public AudioPlayerDeviceModule(IMediaPlayer mediaPlayer,
TMBOY 45:2aa9f933c8d2 66 IMessageSender messageSender) {
TMBOY 45:2aa9f933c8d2 67 super(ApiConstants.NAMESPACE, messageSender);
TMBOY 45:2aa9f933c8d2 68 this.mediaPlayer = mediaPlayer;
TMBOY 45:2aa9f933c8d2 69 this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
TMBOY 45:2aa9f933c8d2 70 this.audioPlayStateReport = new AudioPlayStateReport(getNameSpace(),
TMBOY 45:2aa9f933c8d2 71 messageSender,
TMBOY 45:2aa9f933c8d2 72 audioPlayStateReportListener);
TMBOY 45:2aa9f933c8d2 73 this.timer = new AudioPlayerTimer();
TMBOY 45:2aa9f933c8d2 74 this.progressReporter = new AudioPlayerProgressReporter(
TMBOY 45:2aa9f933c8d2 75 new ProgressReportDelayEventRunnable(audioPlayStateReport),
TMBOY 45:2aa9f933c8d2 76 new ProgressReportIntervalEventRunnable(audioPlayStateReport), timer);
TMBOY 45:2aa9f933c8d2 77 this.audioPlayerListeners = Collections.synchronizedList(
TMBOY 45:2aa9f933c8d2 78 new ArrayList<IMediaPlayer.IMediaPlayerListener>());
TMBOY 45:2aa9f933c8d2 79 }
TMBOY 45:2aa9f933c8d2 80
TMBOY 45:2aa9f933c8d2 81 @Override
TMBOY 45:2aa9f933c8d2 82 public ClientContext clientContext() {
TMBOY 45:2aa9f933c8d2 83 String namespace = ApiConstants.NAMESPACE;
TMBOY 45:2aa9f933c8d2 84 String name = ApiConstants.Events.PlaybackState.NAME;
TMBOY 45:2aa9f933c8d2 85 Header header = new Header(namespace, name);
TMBOY 45:2aa9f933c8d2 86 PlaybackStatePayload payload = new PlaybackStatePayload(latestStreamToken,
TMBOY 45:2aa9f933c8d2 87 mediaPlayer.getCurrentPosition(),
TMBOY 45:2aa9f933c8d2 88 audioPlayStateReport.getState().name());
TMBOY 45:2aa9f933c8d2 89 return new ClientContext(header, payload);
TMBOY 45:2aa9f933c8d2 90 }
TMBOY 45:2aa9f933c8d2 91
TMBOY 45:2aa9f933c8d2 92 @Override
TMBOY 45:2aa9f933c8d2 93 public void handleDirective(Directive directive) throws HandleDirectiveException {
TMBOY 45:2aa9f933c8d2 94 LogUtil.d(TAG, "dcs-play-directive:" + directive.rawMessage);
TMBOY 45:2aa9f933c8d2 95 String directiveName = directive.getName();
TMBOY 45:2aa9f933c8d2 96 LogUtil.d(TAG, "dcs-play-directiveName:" + directiveName);
TMBOY 45:2aa9f933c8d2 97 if (ApiConstants.Directives.Play.NAME.equals(directiveName)) {
TMBOY 45:2aa9f933c8d2 98 handlePlay((PlayPayload) directive.getPayload());
TMBOY 45:2aa9f933c8d2 99 } else if (ApiConstants.Directives.Stop.NAME.equals(directiveName)) {
TMBOY 45:2aa9f933c8d2 100 handleStop((StopPayload) directive.getPayload());
TMBOY 45:2aa9f933c8d2 101 } else if (ApiConstants.Directives.ClearQueue.NAME.equals(directiveName)) {
TMBOY 45:2aa9f933c8d2 102 handleClearQueue((ClearQueuePayload) directive.getPayload());
TMBOY 45:2aa9f933c8d2 103 } else {
TMBOY 45:2aa9f933c8d2 104 String message = "audioPlayer cannot handle the directive";
TMBOY 45:2aa9f933c8d2 105 throw (new HandleDirectiveException(
TMBOY 45:2aa9f933c8d2 106 HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
TMBOY 45:2aa9f933c8d2 107 }
TMBOY 45:2aa9f933c8d2 108 }
TMBOY 45:2aa9f933c8d2 109
TMBOY 45:2aa9f933c8d2 110 /**
TMBOY 45:2aa9f933c8d2 111 * 处理播放指令(Play)
TMBOY 45:2aa9f933c8d2 112 *
TMBOY 45:2aa9f933c8d2 113 * @param payload payload
TMBOY 45:2aa9f933c8d2 114 */
TMBOY 45:2aa9f933c8d2 115 private void handlePlay(PlayPayload payload) {
TMBOY 45:2aa9f933c8d2 116 PlayPayload.AudioItem item = payload.audioItem;
TMBOY 45:2aa9f933c8d2 117 if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ALL) {
TMBOY 45:2aa9f933c8d2 118 clearAll();
TMBOY 45:2aa9f933c8d2 119 } else if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ENQUEUED) {
TMBOY 45:2aa9f933c8d2 120 clearEnqueued();
TMBOY 45:2aa9f933c8d2 121 }
TMBOY 45:2aa9f933c8d2 122 final PlayPayload.Stream stream = item.stream;
TMBOY 45:2aa9f933c8d2 123 String streamUrl = stream.url;
TMBOY 45:2aa9f933c8d2 124 String streamId = stream.token;
TMBOY 45:2aa9f933c8d2 125 long offset = stream.offsetInMilliseconds;
TMBOY 45:2aa9f933c8d2 126 LogUtil.i(TAG, "URL:" + streamUrl);
TMBOY 45:2aa9f933c8d2 127 LogUtil.i(TAG, "StreamId:" + streamId);
TMBOY 45:2aa9f933c8d2 128 LogUtil.i(TAG, "Offset:" + offset);
TMBOY 45:2aa9f933c8d2 129 add(stream);
TMBOY 45:2aa9f933c8d2 130 }
TMBOY 45:2aa9f933c8d2 131
TMBOY 45:2aa9f933c8d2 132 /**
TMBOY 45:2aa9f933c8d2 133 * 处理停止指令(Stop)
TMBOY 45:2aa9f933c8d2 134 *
TMBOY 45:2aa9f933c8d2 135 * @param payload payload
TMBOY 45:2aa9f933c8d2 136 */
TMBOY 45:2aa9f933c8d2 137 private void handleStop(StopPayload payload) {
TMBOY 45:2aa9f933c8d2 138 stop();
TMBOY 45:2aa9f933c8d2 139 }
TMBOY 45:2aa9f933c8d2 140
TMBOY 45:2aa9f933c8d2 141 /**
TMBOY 45:2aa9f933c8d2 142 * 处理清空队列指令(Stop)
TMBOY 45:2aa9f933c8d2 143 *
TMBOY 45:2aa9f933c8d2 144 * @param clearQueuePayload clearQueuePayload
TMBOY 45:2aa9f933c8d2 145 */
TMBOY 45:2aa9f933c8d2 146 private void handleClearQueue(ClearQueuePayload clearQueuePayload) {
TMBOY 45:2aa9f933c8d2 147 // 清除播放列表,并停止当前播放的音频(如果有)
TMBOY 45:2aa9f933c8d2 148 if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ALL) {
TMBOY 45:2aa9f933c8d2 149 audioPlayStateReport.clearQueueAll();
TMBOY 45:2aa9f933c8d2 150 clearAll();
TMBOY 45:2aa9f933c8d2 151 } else if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ENQUEUED) {
TMBOY 45:2aa9f933c8d2 152 // 清除播放列表,但不影响当前播放
TMBOY 45:2aa9f933c8d2 153 audioPlayStateReport.clearQueueEnqueued();
TMBOY 45:2aa9f933c8d2 154 clearEnqueued();
TMBOY 45:2aa9f933c8d2 155 }
TMBOY 45:2aa9f933c8d2 156 }
TMBOY 45:2aa9f933c8d2 157
TMBOY 45:2aa9f933c8d2 158 private void add(PlayPayload.Stream stream) {
TMBOY 45:2aa9f933c8d2 159 String expectedPreviousToken = stream.expectedPreviousToken;
TMBOY 45:2aa9f933c8d2 160 boolean startPlaying = playQueue.isEmpty();
TMBOY 45:2aa9f933c8d2 161 if (expectedPreviousToken == null || latestStreamToken.isEmpty()
TMBOY 45:2aa9f933c8d2 162 || latestStreamToken.equals(expectedPreviousToken)) {
TMBOY 45:2aa9f933c8d2 163 playQueue.add(stream);
TMBOY 45:2aa9f933c8d2 164 }
TMBOY 45:2aa9f933c8d2 165 LogUtil.d(TAG, " coming playQueue size :" + playQueue.size());
TMBOY 45:2aa9f933c8d2 166 if (startPlaying) {
TMBOY 45:2aa9f933c8d2 167 startPlay();
TMBOY 45:2aa9f933c8d2 168 }
TMBOY 45:2aa9f933c8d2 169 }
TMBOY 45:2aa9f933c8d2 170
TMBOY 45:2aa9f933c8d2 171 /**
TMBOY 45:2aa9f933c8d2 172 * 开始播放音乐
TMBOY 45:2aa9f933c8d2 173 */
TMBOY 45:2aa9f933c8d2 174 private void startPlay() {
TMBOY 45:2aa9f933c8d2 175 if (playQueue.isEmpty()) {
TMBOY 45:2aa9f933c8d2 176 LogUtil.d(TAG, "startPlay-playQueue isEmpty !!");
TMBOY 45:2aa9f933c8d2 177 return;
TMBOY 45:2aa9f933c8d2 178 }
TMBOY 45:2aa9f933c8d2 179 PlayPayload.Stream currentStream = playQueue.peek();
TMBOY 45:2aa9f933c8d2 180 if (currentStream == null) {
TMBOY 45:2aa9f933c8d2 181 return;
TMBOY 45:2aa9f933c8d2 182 }
TMBOY 45:2aa9f933c8d2 183 latestStreamToken = currentStream.token;
TMBOY 45:2aa9f933c8d2 184 String url = currentStream.url;
TMBOY 45:2aa9f933c8d2 185 // 从哪个位置开始播放
TMBOY 45:2aa9f933c8d2 186 long offset = currentStream.offsetInMilliseconds;
TMBOY 45:2aa9f933c8d2 187 // 判断是否是流类型还是URL类型
TMBOY 45:2aa9f933c8d2 188 if (currentStream.hasAttachedContent()) {
TMBOY 45:2aa9f933c8d2 189 mediaPlayer.play(new IMediaPlayer.MediaResource(currentStream.getAttachedContent()));
TMBOY 45:2aa9f933c8d2 190 } else {
TMBOY 45:2aa9f933c8d2 191 mediaPlayer.play(new IMediaPlayer.MediaResource(url));
TMBOY 45:2aa9f933c8d2 192 }
TMBOY 45:2aa9f933c8d2 193 mediaPlayer.seekTo((int) offset);
TMBOY 45:2aa9f933c8d2 194 }
TMBOY 45:2aa9f933c8d2 195
TMBOY 45:2aa9f933c8d2 196 private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
TMBOY 45:2aa9f933c8d2 197 // 是否处于暂停
TMBOY 45:2aa9f933c8d2 198 private boolean isPause;
TMBOY 45:2aa9f933c8d2 199 // 是否第一次到达了100
TMBOY 45:2aa9f933c8d2 200 private boolean stutterFinished;
TMBOY 45:2aa9f933c8d2 201 // 是否处于上报ProgressReport事件中
TMBOY 45:2aa9f933c8d2 202 private boolean progressReporting;
TMBOY 45:2aa9f933c8d2 203 // 是否处于缓冲中
TMBOY 45:2aa9f933c8d2 204 private boolean bufferUnderRunInProgress;
TMBOY 45:2aa9f933c8d2 205
TMBOY 45:2aa9f933c8d2 206 @Override
TMBOY 45:2aa9f933c8d2 207 public void onInit() {
TMBOY 45:2aa9f933c8d2 208 super.onInit();
TMBOY 45:2aa9f933c8d2 209 LogUtil.d(TAG, "onInit");
TMBOY 45:2aa9f933c8d2 210 isPause = false;
TMBOY 45:2aa9f933c8d2 211 stutterFinished = false;
TMBOY 45:2aa9f933c8d2 212 progressReporting = false;
TMBOY 45:2aa9f933c8d2 213 bufferUnderRunInProgress = false;
TMBOY 45:2aa9f933c8d2 214 }
TMBOY 45:2aa9f933c8d2 215
TMBOY 45:2aa9f933c8d2 216 @Override
TMBOY 45:2aa9f933c8d2 217 public void onPrepared() {
TMBOY 45:2aa9f933c8d2 218 super.onPrepared();
TMBOY 45:2aa9f933c8d2 219 LogUtil.d(TAG, "onPrepared");
TMBOY 45:2aa9f933c8d2 220 fireOnPrepared();
TMBOY 45:2aa9f933c8d2 221 }
TMBOY 45:2aa9f933c8d2 222
TMBOY 45:2aa9f933c8d2 223 @Override
TMBOY 45:2aa9f933c8d2 224 public void onPlaying() {
TMBOY 45:2aa9f933c8d2 225 super.onPlaying();
TMBOY 45:2aa9f933c8d2 226 LogUtil.d(TAG, "onPlaying");
TMBOY 45:2aa9f933c8d2 227 // 暂停后继续播放
TMBOY 45:2aa9f933c8d2 228 if (isPause) {
TMBOY 45:2aa9f933c8d2 229 isPause = false;
TMBOY 45:2aa9f933c8d2 230 audioPlayStateReport.playbackResumed();
TMBOY 45:2aa9f933c8d2 231 } else {
TMBOY 45:2aa9f933c8d2 232 // 第一次播放
TMBOY 45:2aa9f933c8d2 233 PlayPayload.Stream stream = playQueue.peek();
TMBOY 45:2aa9f933c8d2 234 if (stream == null) {
TMBOY 45:2aa9f933c8d2 235 return;
TMBOY 45:2aa9f933c8d2 236 }
TMBOY 45:2aa9f933c8d2 237 long offset = stream.offsetInMilliseconds;
TMBOY 45:2aa9f933c8d2 238 LogUtil.d(TAG, "onPlaying---Duration----:" + mediaPlayer.getDuration());
TMBOY 45:2aa9f933c8d2 239 timer.reset(offset, mediaPlayer.getDuration());
TMBOY 45:2aa9f933c8d2 240
TMBOY 45:2aa9f933c8d2 241 // 上报PlaybackStarted事件
TMBOY 45:2aa9f933c8d2 242 audioPlayStateReport.playbackStarted();
TMBOY 45:2aa9f933c8d2 243 }
TMBOY 45:2aa9f933c8d2 244 startTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 245 fireOnPlaying();
TMBOY 45:2aa9f933c8d2 246 }
TMBOY 45:2aa9f933c8d2 247
TMBOY 45:2aa9f933c8d2 248 @Override
TMBOY 45:2aa9f933c8d2 249 public void onPaused() {
TMBOY 45:2aa9f933c8d2 250 LogUtil.d(TAG, "onPaused");
TMBOY 45:2aa9f933c8d2 251 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 252 isPause = true;
TMBOY 45:2aa9f933c8d2 253 audioPlayStateReport.playbackPaused();
TMBOY 45:2aa9f933c8d2 254 fireOnPaused();
TMBOY 45:2aa9f933c8d2 255 }
TMBOY 45:2aa9f933c8d2 256
TMBOY 45:2aa9f933c8d2 257 @Override
TMBOY 45:2aa9f933c8d2 258 public void onStopped() {
TMBOY 45:2aa9f933c8d2 259 super.onStopped();
TMBOY 45:2aa9f933c8d2 260 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 261 audioPlayStateReport.playbackStopped();
TMBOY 45:2aa9f933c8d2 262 fireOnStopped();
TMBOY 45:2aa9f933c8d2 263 }
TMBOY 45:2aa9f933c8d2 264
TMBOY 45:2aa9f933c8d2 265 @Override
TMBOY 45:2aa9f933c8d2 266 public void onCompletion() {
TMBOY 45:2aa9f933c8d2 267 LogUtil.d(TAG, "onCompletion");
TMBOY 45:2aa9f933c8d2 268 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 269 playQueue.poll();
TMBOY 45:2aa9f933c8d2 270 audioPlayStateReport.playbackFinished();
TMBOY 45:2aa9f933c8d2 271 audioPlayStateReport.playbackNearlyFinished();
TMBOY 45:2aa9f933c8d2 272 if (!playQueue.isEmpty()) {
TMBOY 45:2aa9f933c8d2 273 startPlay();
TMBOY 45:2aa9f933c8d2 274 }
TMBOY 45:2aa9f933c8d2 275 fireOnCompletion();
TMBOY 45:2aa9f933c8d2 276 }
TMBOY 45:2aa9f933c8d2 277
TMBOY 45:2aa9f933c8d2 278 @Override
TMBOY 45:2aa9f933c8d2 279 public void onRelease() {
TMBOY 45:2aa9f933c8d2 280 LogUtil.d(TAG, "onError");
TMBOY 45:2aa9f933c8d2 281 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 282 fireOnRelease();
TMBOY 45:2aa9f933c8d2 283 }
TMBOY 45:2aa9f933c8d2 284
TMBOY 45:2aa9f933c8d2 285 @Override
TMBOY 45:2aa9f933c8d2 286 public void onError(String error, IMediaPlayer.ErrorType errorType) {
TMBOY 45:2aa9f933c8d2 287 LogUtil.d(TAG, "onError");
TMBOY 45:2aa9f933c8d2 288 playQueue.clear();
TMBOY 45:2aa9f933c8d2 289 audioPlayStateReport.playbackFailed(errorType);
TMBOY 45:2aa9f933c8d2 290 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 291 fireOnError(error, errorType);
TMBOY 45:2aa9f933c8d2 292 }
TMBOY 45:2aa9f933c8d2 293
TMBOY 45:2aa9f933c8d2 294 @Override
TMBOY 45:2aa9f933c8d2 295 public void onBufferingUpdate(int percent) {
TMBOY 45:2aa9f933c8d2 296 LogUtil.d(TAG, "onBufferingUpdate:" + percent);
TMBOY 45:2aa9f933c8d2 297 fireOnBufferingUpdate(percent);
TMBOY 45:2aa9f933c8d2 298 PlayPayload.Stream stream = playQueue.peek();
TMBOY 45:2aa9f933c8d2 299 if (stream == null) {
TMBOY 45:2aa9f933c8d2 300 return;
TMBOY 45:2aa9f933c8d2 301 }
TMBOY 45:2aa9f933c8d2 302 // Play指令有progressReportDelayInMilliseconds
TMBOY 45:2aa9f933c8d2 303 if (!progressReporting && stream.getProgressReportRequired()) {
TMBOY 45:2aa9f933c8d2 304 LogUtil.d(TAG, "onBufferingUpdate:" + percent);
TMBOY 45:2aa9f933c8d2 305 progressReporting = true;
TMBOY 45:2aa9f933c8d2 306 progressReporter.disable();
TMBOY 45:2aa9f933c8d2 307 progressReporter.setup(stream.progressReport);
TMBOY 45:2aa9f933c8d2 308 long offset = stream.offsetInMilliseconds;
TMBOY 45:2aa9f933c8d2 309 timer.reset(offset, mediaPlayer.getDuration());
TMBOY 45:2aa9f933c8d2 310 startTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 311 }
TMBOY 45:2aa9f933c8d2 312
TMBOY 45:2aa9f933c8d2 313 // 已经缓冲完成了
TMBOY 45:2aa9f933c8d2 314 if (stutterFinished) {
TMBOY 45:2aa9f933c8d2 315 return;
TMBOY 45:2aa9f933c8d2 316 }
TMBOY 45:2aa9f933c8d2 317 // 开始缓冲
TMBOY 45:2aa9f933c8d2 318 if (!bufferUnderRunInProgress) {
TMBOY 45:2aa9f933c8d2 319 LogUtil.d(TAG, "==playbackStutterStarted");
TMBOY 45:2aa9f933c8d2 320 bufferUnderRunInProgress = true;
TMBOY 45:2aa9f933c8d2 321 bufferingStartMilliseconds = System.currentTimeMillis();
TMBOY 45:2aa9f933c8d2 322 audioPlayStateReport.playbackStutterStarted();
TMBOY 45:2aa9f933c8d2 323 }
TMBOY 45:2aa9f933c8d2 324 // 缓冲完毕后上报playbackStutterFinished
TMBOY 45:2aa9f933c8d2 325 if (percent >= 100) {
TMBOY 45:2aa9f933c8d2 326 stutterFinished = true;
TMBOY 45:2aa9f933c8d2 327 bufferingEndMilliseconds = System.currentTimeMillis();
TMBOY 45:2aa9f933c8d2 328 audioPlayStateReport.playbackStutterFinished();
TMBOY 45:2aa9f933c8d2 329 }
TMBOY 45:2aa9f933c8d2 330 }
TMBOY 45:2aa9f933c8d2 331 };
TMBOY 45:2aa9f933c8d2 332
TMBOY 45:2aa9f933c8d2 333 private void startTimerAndProgressReporter() {
TMBOY 45:2aa9f933c8d2 334 timer.start();
TMBOY 45:2aa9f933c8d2 335 if (progressReporter.isSetup()) {
TMBOY 45:2aa9f933c8d2 336 progressReporter.start();
TMBOY 45:2aa9f933c8d2 337 }
TMBOY 45:2aa9f933c8d2 338 }
TMBOY 45:2aa9f933c8d2 339
TMBOY 45:2aa9f933c8d2 340 private void stopTimerAndProgressReporter() {
TMBOY 45:2aa9f933c8d2 341 timer.stop();
TMBOY 45:2aa9f933c8d2 342 progressReporter.stop();
TMBOY 45:2aa9f933c8d2 343 }
TMBOY 45:2aa9f933c8d2 344
TMBOY 45:2aa9f933c8d2 345 private void clearAll() {
TMBOY 45:2aa9f933c8d2 346 stop();
TMBOY 45:2aa9f933c8d2 347 playQueue.clear();
TMBOY 45:2aa9f933c8d2 348 }
TMBOY 45:2aa9f933c8d2 349
TMBOY 45:2aa9f933c8d2 350 private void clearEnqueued() {
TMBOY 45:2aa9f933c8d2 351 PlayPayload.Stream top = playQueue.poll();
TMBOY 45:2aa9f933c8d2 352 playQueue.clear();
TMBOY 45:2aa9f933c8d2 353 if (top != null) {
TMBOY 45:2aa9f933c8d2 354 playQueue.add(top);
TMBOY 45:2aa9f933c8d2 355 }
TMBOY 45:2aa9f933c8d2 356 }
TMBOY 45:2aa9f933c8d2 357
TMBOY 45:2aa9f933c8d2 358 private void stop() {
TMBOY 45:2aa9f933c8d2 359 if (!playQueue.isEmpty() && isPlayingOrPaused()) {
TMBOY 45:2aa9f933c8d2 360 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 361 // 要把播放策略中的对应的那一条删除了
TMBOY 45:2aa9f933c8d2 362 mediaPlayer.stop();
TMBOY 45:2aa9f933c8d2 363 }
TMBOY 45:2aa9f933c8d2 364 }
TMBOY 45:2aa9f933c8d2 365
TMBOY 45:2aa9f933c8d2 366 private boolean isPlaying() {
TMBOY 45:2aa9f933c8d2 367 return (audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PLAYING
TMBOY 45:2aa9f933c8d2 368 || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED
TMBOY 45:2aa9f933c8d2 369 || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.BUFFER_UNDERRUN);
TMBOY 45:2aa9f933c8d2 370 }
TMBOY 45:2aa9f933c8d2 371
TMBOY 45:2aa9f933c8d2 372 private boolean isPlayingOrPaused() {
TMBOY 45:2aa9f933c8d2 373 return isPlaying() || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED;
TMBOY 45:2aa9f933c8d2 374 }
TMBOY 45:2aa9f933c8d2 375
TMBOY 45:2aa9f933c8d2 376 @Override
TMBOY 45:2aa9f933c8d2 377 public void release() {
TMBOY 45:2aa9f933c8d2 378 if (mediaPlayer != null) {
TMBOY 45:2aa9f933c8d2 379 mediaPlayer.release();
TMBOY 45:2aa9f933c8d2 380 mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
TMBOY 45:2aa9f933c8d2 381 }
TMBOY 45:2aa9f933c8d2 382 stopTimerAndProgressReporter();
TMBOY 45:2aa9f933c8d2 383 audioPlayerListeners.clear();
TMBOY 45:2aa9f933c8d2 384 }
TMBOY 45:2aa9f933c8d2 385
TMBOY 45:2aa9f933c8d2 386 /**
TMBOY 45:2aa9f933c8d2 387 * 播放上报时需要的信息
TMBOY 45:2aa9f933c8d2 388 */
TMBOY 45:2aa9f933c8d2 389 private AudioPlayStateReport.AudioPlayStateReportListener audioPlayStateReportListener =
TMBOY 45:2aa9f933c8d2 390 new AudioPlayStateReport.AudioPlayStateReportListener() {
TMBOY 45:2aa9f933c8d2 391 @Override
TMBOY 45:2aa9f933c8d2 392 public String getCurrentStreamToken() {
TMBOY 45:2aa9f933c8d2 393 return latestStreamToken;
TMBOY 45:2aa9f933c8d2 394 }
TMBOY 45:2aa9f933c8d2 395
TMBOY 45:2aa9f933c8d2 396 @Override
TMBOY 45:2aa9f933c8d2 397 public long getCurrentOffsetInMilliseconds() {
TMBOY 45:2aa9f933c8d2 398 return getCurrentOffsetInMillisecondsByTime();
TMBOY 45:2aa9f933c8d2 399 }
TMBOY 45:2aa9f933c8d2 400
TMBOY 45:2aa9f933c8d2 401 @Override
TMBOY 45:2aa9f933c8d2 402 public long getStutterDurationInMilliseconds() {
TMBOY 45:2aa9f933c8d2 403 // 缓冲时间ms
TMBOY 45:2aa9f933c8d2 404 return bufferingEndMilliseconds - bufferingStartMilliseconds;
TMBOY 45:2aa9f933c8d2 405 }
TMBOY 45:2aa9f933c8d2 406 };
TMBOY 45:2aa9f933c8d2 407
TMBOY 45:2aa9f933c8d2 408 private long getCurrentOffsetInMillisecondsByTime() {
TMBOY 45:2aa9f933c8d2 409 AudioPlayStateReport.AudioPlayerState playerActivity = audioPlayStateReport.getState();
TMBOY 45:2aa9f933c8d2 410 long offset;
TMBOY 45:2aa9f933c8d2 411 switch (playerActivity) {
TMBOY 45:2aa9f933c8d2 412 case PLAYING:
TMBOY 45:2aa9f933c8d2 413 case PAUSED:
TMBOY 45:2aa9f933c8d2 414 case BUFFER_UNDERRUN:
TMBOY 45:2aa9f933c8d2 415 case STOPPED:
TMBOY 45:2aa9f933c8d2 416 case FINISHED:
TMBOY 45:2aa9f933c8d2 417 offset = timer.getOffsetInMilliseconds();
TMBOY 45:2aa9f933c8d2 418 break;
TMBOY 45:2aa9f933c8d2 419 case IDLE:
TMBOY 45:2aa9f933c8d2 420 default:
TMBOY 45:2aa9f933c8d2 421 offset = 0;
TMBOY 45:2aa9f933c8d2 422 }
TMBOY 45:2aa9f933c8d2 423 LogUtil.d(TAG, "getCurrentOffsetInMilliseconds offset:" + offset);
TMBOY 45:2aa9f933c8d2 424 return offset;
TMBOY 45:2aa9f933c8d2 425 }
TMBOY 45:2aa9f933c8d2 426
TMBOY 45:2aa9f933c8d2 427 private static class ProgressReportDelayEventRunnable implements Runnable {
TMBOY 45:2aa9f933c8d2 428 private final AudioPlayStateReport audioPlayStateReport;
TMBOY 45:2aa9f933c8d2 429
TMBOY 45:2aa9f933c8d2 430 ProgressReportDelayEventRunnable(AudioPlayStateReport audioPlayStateReport) {
TMBOY 45:2aa9f933c8d2 431 this.audioPlayStateReport = audioPlayStateReport;
TMBOY 45:2aa9f933c8d2 432 }
TMBOY 45:2aa9f933c8d2 433
TMBOY 45:2aa9f933c8d2 434 @Override
TMBOY 45:2aa9f933c8d2 435 public void run() {
TMBOY 45:2aa9f933c8d2 436 audioPlayStateReport.reportProgressDelay();
TMBOY 45:2aa9f933c8d2 437 }
TMBOY 45:2aa9f933c8d2 438 }
TMBOY 45:2aa9f933c8d2 439
TMBOY 45:2aa9f933c8d2 440 private static class ProgressReportIntervalEventRunnable implements Runnable {
TMBOY 45:2aa9f933c8d2 441 private final AudioPlayStateReport audioPlayStateReport;
TMBOY 45:2aa9f933c8d2 442
TMBOY 45:2aa9f933c8d2 443 ProgressReportIntervalEventRunnable(AudioPlayStateReport audioPlayStateReport) {
TMBOY 45:2aa9f933c8d2 444 this.audioPlayStateReport = audioPlayStateReport;
TMBOY 45:2aa9f933c8d2 445 }
TMBOY 45:2aa9f933c8d2 446
TMBOY 45:2aa9f933c8d2 447 @Override
TMBOY 45:2aa9f933c8d2 448 public void run() {
TMBOY 45:2aa9f933c8d2 449 audioPlayStateReport.reportProgressInterval();
TMBOY 45:2aa9f933c8d2 450 }
TMBOY 45:2aa9f933c8d2 451 }
TMBOY 45:2aa9f933c8d2 452
TMBOY 45:2aa9f933c8d2 453 private void fireOnPrepared() {
TMBOY 45:2aa9f933c8d2 454 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 455 listener.onPrepared();
TMBOY 45:2aa9f933c8d2 456 }
TMBOY 45:2aa9f933c8d2 457 }
TMBOY 45:2aa9f933c8d2 458
TMBOY 45:2aa9f933c8d2 459 private void fireOnRelease() {
TMBOY 45:2aa9f933c8d2 460 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 461 listener.onRelease();
TMBOY 45:2aa9f933c8d2 462 }
TMBOY 45:2aa9f933c8d2 463 }
TMBOY 45:2aa9f933c8d2 464
TMBOY 45:2aa9f933c8d2 465 private void fireOnPlaying() {
TMBOY 45:2aa9f933c8d2 466 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 467 listener.onPlaying();
TMBOY 45:2aa9f933c8d2 468 }
TMBOY 45:2aa9f933c8d2 469 }
TMBOY 45:2aa9f933c8d2 470
TMBOY 45:2aa9f933c8d2 471 private void fireOnPaused() {
TMBOY 45:2aa9f933c8d2 472 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 473 listener.onPaused();
TMBOY 45:2aa9f933c8d2 474 }
TMBOY 45:2aa9f933c8d2 475 }
TMBOY 45:2aa9f933c8d2 476
TMBOY 45:2aa9f933c8d2 477 private void fireOnStopped() {
TMBOY 45:2aa9f933c8d2 478 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 479 listener.onStopped();
TMBOY 45:2aa9f933c8d2 480 }
TMBOY 45:2aa9f933c8d2 481 }
TMBOY 45:2aa9f933c8d2 482
TMBOY 45:2aa9f933c8d2 483 private void fireOnCompletion() {
TMBOY 45:2aa9f933c8d2 484 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 485 listener.onCompletion();
TMBOY 45:2aa9f933c8d2 486 }
TMBOY 45:2aa9f933c8d2 487 }
TMBOY 45:2aa9f933c8d2 488
TMBOY 45:2aa9f933c8d2 489 private void fireOnError(String error, IMediaPlayer.ErrorType errorType) {
TMBOY 45:2aa9f933c8d2 490 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 491 listener.onError(error, errorType);
TMBOY 45:2aa9f933c8d2 492 }
TMBOY 45:2aa9f933c8d2 493 }
TMBOY 45:2aa9f933c8d2 494
TMBOY 45:2aa9f933c8d2 495 private void fireOnBufferingUpdate(int percent) {
TMBOY 45:2aa9f933c8d2 496 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 497 listener.onBufferingUpdate(percent);
TMBOY 45:2aa9f933c8d2 498 }
TMBOY 45:2aa9f933c8d2 499 }
TMBOY 45:2aa9f933c8d2 500
TMBOY 45:2aa9f933c8d2 501 private void fireBufferingStart() {
TMBOY 45:2aa9f933c8d2 502 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 503 listener.onBufferingStart();
TMBOY 45:2aa9f933c8d2 504 }
TMBOY 45:2aa9f933c8d2 505 }
TMBOY 45:2aa9f933c8d2 506
TMBOY 45:2aa9f933c8d2 507 private void fireBufferingEnd() {
TMBOY 45:2aa9f933c8d2 508 for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
TMBOY 45:2aa9f933c8d2 509 listener.onBufferingEnd();
TMBOY 45:2aa9f933c8d2 510 }
TMBOY 45:2aa9f933c8d2 511 }
TMBOY 45:2aa9f933c8d2 512
TMBOY 45:2aa9f933c8d2 513 public void addAudioPlayListener(IMediaPlayer.IMediaPlayerListener listener) {
TMBOY 45:2aa9f933c8d2 514 audioPlayerListeners.add(listener);
TMBOY 45:2aa9f933c8d2 515 }
TMBOY 45:2aa9f933c8d2 516 }