1 /* 2 * Copyright (C) 2022 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 17 package com.android.pandora 18 19 import android.content.Context 20 import android.content.Intent 21 import android.media.* 22 import android.support.v4.media.session.PlaybackStateCompat.SHUFFLE_MODE_ALL 23 import android.support.v4.media.session.PlaybackStateCompat.SHUFFLE_MODE_GROUP 24 import android.support.v4.media.session.PlaybackStateCompat.SHUFFLE_MODE_NONE 25 import com.google.protobuf.Empty 26 import io.grpc.stub.StreamObserver 27 import java.io.Closeable 28 import kotlinx.coroutines.CoroutineScope 29 import kotlinx.coroutines.Dispatchers 30 import kotlinx.coroutines.cancel 31 import pandora.MediaPlayerGrpc.MediaPlayerImplBase 32 import pandora.MediaPlayerProto.* 33 import pandora.MediaPlayerProto.GetShuffleModeResponse 34 import pandora.MediaPlayerProto.SetShuffleModeRequest 35 import pandora.MediaPlayerProto.ShuffleMode 36 37 @kotlinx.coroutines.ExperimentalCoroutinesApi 38 class MediaPlayer(val context: Context) : MediaPlayerImplBase(), Closeable { 39 private val TAG = "PandoraMediaPlayer" 40 41 private val scope: CoroutineScope 42 43 init { 44 // Init the CoroutineScope 45 scope = CoroutineScope(Dispatchers.Default.limitedParallelism(1)) 46 if (!MediaPlayerBrowserService.isInitialized()) { 47 context.startService(Intent(context, MediaPlayerBrowserService::class.java)) 48 } 49 } 50 playnull51 override fun play(request: Empty, responseObserver: StreamObserver<Empty>) { 52 grpcUnary<Empty>(scope, responseObserver) { 53 MediaPlayerBrowserService.instance.play() 54 Empty.getDefaultInstance() 55 } 56 } 57 playUpdatednull58 override fun playUpdated(request: Empty, responseObserver: StreamObserver<Empty>) { 59 grpcUnary<Empty>(scope, responseObserver) { 60 MediaPlayerBrowserService.instance.playUpdated() 61 Empty.getDefaultInstance() 62 } 63 } 64 stopnull65 override fun stop(request: Empty, responseObserver: StreamObserver<Empty>) { 66 grpcUnary<Empty>(scope, responseObserver) { 67 MediaPlayerBrowserService.instance.stop() 68 Empty.getDefaultInstance() 69 } 70 } 71 pausenull72 override fun pause(request: Empty, responseObserver: StreamObserver<Empty>) { 73 grpcUnary<Empty>(scope, responseObserver) { 74 MediaPlayerBrowserService.instance.pause() 75 Empty.getDefaultInstance() 76 } 77 } 78 rewindnull79 override fun rewind(request: Empty, responseObserver: StreamObserver<Empty>) { 80 grpcUnary<Empty>(scope, responseObserver) { 81 MediaPlayerBrowserService.instance.rewind() 82 Empty.getDefaultInstance() 83 } 84 } 85 fastForwardnull86 override fun fastForward(request: Empty, responseObserver: StreamObserver<Empty>) { 87 grpcUnary<Empty>(scope, responseObserver) { 88 MediaPlayerBrowserService.instance.fastForward() 89 Empty.getDefaultInstance() 90 } 91 } 92 forwardnull93 override fun forward(request: Empty, responseObserver: StreamObserver<Empty>) { 94 grpcUnary<Empty>(scope, responseObserver) { 95 MediaPlayerBrowserService.instance.forward() 96 Empty.getDefaultInstance() 97 } 98 } 99 backwardnull100 override fun backward(request: Empty, responseObserver: StreamObserver<Empty>) { 101 grpcUnary<Empty>(scope, responseObserver) { 102 MediaPlayerBrowserService.instance.backward() 103 Empty.getDefaultInstance() 104 } 105 } 106 setLargeMetadatanull107 override fun setLargeMetadata(request: Empty, responseObserver: StreamObserver<Empty>) { 108 grpcUnary<Empty>(scope, responseObserver) { 109 MediaPlayerBrowserService.instance.setLargeMetadata() 110 Empty.getDefaultInstance() 111 } 112 } 113 updateQueuenull114 override fun updateQueue(request: Empty, responseObserver: StreamObserver<Empty>) { 115 grpcUnary<Empty>(scope, responseObserver) { 116 MediaPlayerBrowserService.instance.updateQueue() 117 Empty.getDefaultInstance() 118 } 119 } 120 resetQueuenull121 override fun resetQueue(request: Empty, responseObserver: StreamObserver<Empty>) { 122 grpcUnary<Empty>(scope, responseObserver) { 123 MediaPlayerBrowserService.instance.resetQueue() 124 Empty.getDefaultInstance() 125 } 126 } 127 getShuffleModenull128 override fun getShuffleMode( 129 request: Empty, 130 responseObserver: StreamObserver<GetShuffleModeResponse> 131 ) { 132 grpcUnary(scope, responseObserver) { 133 val mode: Int = MediaPlayerBrowserService.instance.getShuffleMode() 134 val shuffleMode = 135 when (mode) { 136 SHUFFLE_MODE_NONE -> ShuffleMode.NONE 137 SHUFFLE_MODE_ALL -> ShuffleMode.ALL 138 SHUFFLE_MODE_GROUP -> ShuffleMode.GROUP 139 else -> ShuffleMode.NONE 140 } 141 GetShuffleModeResponse.newBuilder().setMode(shuffleMode).build() 142 } 143 } 144 setShuffleModenull145 override fun setShuffleMode( 146 request: SetShuffleModeRequest, 147 responseObserver: StreamObserver<Empty> 148 ) { 149 grpcUnary(scope, responseObserver) { 150 when (request.mode!!) { 151 ShuffleMode.NONE -> 152 MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_NONE) 153 ShuffleMode.ALL -> 154 MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_ALL) 155 ShuffleMode.GROUP -> 156 MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_GROUP) 157 else -> MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_NONE) 158 } 159 Empty.getDefaultInstance() 160 } 161 } 162 startTestPlaybacknull163 override fun startTestPlayback(request: Empty, responseObserver: StreamObserver<Empty>) { 164 grpcUnary<Empty>(scope, responseObserver) { 165 MediaPlayerBrowserService.instance.startTestPlayback() 166 Empty.getDefaultInstance() 167 } 168 } 169 stopTestPlaybacknull170 override fun stopTestPlayback(request: Empty, responseObserver: StreamObserver<Empty>) { 171 grpcUnary<Empty>(scope, responseObserver) { 172 MediaPlayerBrowserService.instance.stopTestPlayback() 173 Empty.getDefaultInstance() 174 } 175 } 176 closenull177 override fun close() { 178 // Deinit the CoroutineScope 179 scope.cancel() 180 } 181 } 182