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 
stopnull58     override fun stop(request: Empty, responseObserver: StreamObserver<Empty>) {
59         grpcUnary<Empty>(scope, responseObserver) {
60             MediaPlayerBrowserService.instance.stop()
61             Empty.getDefaultInstance()
62         }
63     }
64 
pausenull65     override fun pause(request: Empty, responseObserver: StreamObserver<Empty>) {
66         grpcUnary<Empty>(scope, responseObserver) {
67             MediaPlayerBrowserService.instance.pause()
68             Empty.getDefaultInstance()
69         }
70     }
71 
rewindnull72     override fun rewind(request: Empty, responseObserver: StreamObserver<Empty>) {
73         grpcUnary<Empty>(scope, responseObserver) {
74             MediaPlayerBrowserService.instance.rewind()
75             Empty.getDefaultInstance()
76         }
77     }
78 
fastForwardnull79     override fun fastForward(request: Empty, responseObserver: StreamObserver<Empty>) {
80         grpcUnary<Empty>(scope, responseObserver) {
81             MediaPlayerBrowserService.instance.fastForward()
82             Empty.getDefaultInstance()
83         }
84     }
85 
forwardnull86     override fun forward(request: Empty, responseObserver: StreamObserver<Empty>) {
87         grpcUnary<Empty>(scope, responseObserver) {
88             MediaPlayerBrowserService.instance.forward()
89             Empty.getDefaultInstance()
90         }
91     }
92 
backwardnull93     override fun backward(request: Empty, responseObserver: StreamObserver<Empty>) {
94         grpcUnary<Empty>(scope, responseObserver) {
95             MediaPlayerBrowserService.instance.backward()
96             Empty.getDefaultInstance()
97         }
98     }
99 
setLargeMetadatanull100     override fun setLargeMetadata(request: Empty, responseObserver: StreamObserver<Empty>) {
101         grpcUnary<Empty>(scope, responseObserver) {
102             MediaPlayerBrowserService.instance.setLargeMetadata()
103             Empty.getDefaultInstance()
104         }
105     }
106 
updateQueuenull107     override fun updateQueue(request: Empty, responseObserver: StreamObserver<Empty>) {
108         grpcUnary<Empty>(scope, responseObserver) {
109             MediaPlayerBrowserService.instance.updateQueue()
110             Empty.getDefaultInstance()
111         }
112     }
113 
getShuffleModenull114     override fun getShuffleMode(
115         request: Empty,
116         responseObserver: StreamObserver<GetShuffleModeResponse>
117     ) {
118         grpcUnary(scope, responseObserver) {
119             val mode: Int = MediaPlayerBrowserService.instance.getShuffleMode()
120             val shuffleMode =
121                 when (mode) {
122                     SHUFFLE_MODE_NONE -> ShuffleMode.NONE
123                     SHUFFLE_MODE_ALL -> ShuffleMode.ALL
124                     SHUFFLE_MODE_GROUP -> ShuffleMode.GROUP
125                     else -> ShuffleMode.NONE
126                 }
127             GetShuffleModeResponse.newBuilder().setMode(shuffleMode).build()
128         }
129     }
130 
setShuffleModenull131     override fun setShuffleMode(
132         request: SetShuffleModeRequest,
133         responseObserver: StreamObserver<Empty>
134     ) {
135         grpcUnary(scope, responseObserver) {
136             when (request.mode!!) {
137                 ShuffleMode.NONE ->
138                     MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_NONE)
139                 ShuffleMode.ALL ->
140                     MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_ALL)
141                 ShuffleMode.GROUP ->
142                     MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_GROUP)
143                 else -> MediaPlayerBrowserService.instance.setShuffleMode(SHUFFLE_MODE_NONE)
144             }
145             Empty.getDefaultInstance()
146         }
147     }
148 
startTestPlaybacknull149     override fun startTestPlayback(request: Empty, responseObserver: StreamObserver<Empty>) {
150         grpcUnary<Empty>(scope, responseObserver) {
151             MediaPlayerBrowserService.instance.startTestPlayback()
152             Empty.getDefaultInstance()
153         }
154     }
155 
stopTestPlaybacknull156     override fun stopTestPlayback(request: Empty, responseObserver: StreamObserver<Empty>) {
157         grpcUnary<Empty>(scope, responseObserver) {
158             MediaPlayerBrowserService.instance.stopTestPlayback()
159             Empty.getDefaultInstance()
160         }
161     }
162 
closenull163     override fun close() {
164         // Deinit the CoroutineScope
165         scope.cancel()
166     }
167 }
168