Loading android/pandora/server/src/com/android/pandora/A2dp.kt +37 −29 Original line number Diff line number Diff line Loading @@ -26,8 +26,6 @@ import android.content.Intent import android.content.IntentFilter import android.media.* import android.util.Log import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* import io.grpc.Status import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope Loading @@ -40,6 +38,8 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dp(val context: Context) : A2DPImplBase() { Loading @@ -56,7 +56,24 @@ class A2dp(val context: Context) : A2DPImplBase() { private val bluetoothAdapter = bluetoothManager.adapter private val bluetoothA2dp = getProfileProxy<BluetoothA2dp>(context, BluetoothProfile.A2DP) private val audioTrack: AudioTrack = private var audioTrack: AudioTrack? = null init { scope = CoroutineScope(Dispatchers.Default) val intentFilter = IntentFilter() intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED) intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() } fun buildAudioTrack(): AudioTrack? { audioTrack = AudioTrack.Builder() .setAudioAttributes( AudioAttributes.Builder() Loading @@ -74,19 +91,7 @@ class A2dp(val context: Context) : A2DPImplBase() { .setTransferMode(AudioTrack.MODE_STREAM) .setBufferSizeInBytes(44100 * 2 * 2) .build() init { scope = CoroutineScope(Dispatchers.Default) val intentFilter = IntentFilter() intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED) intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() return audioTrack } override fun openSource( Loading Loading @@ -168,6 +173,9 @@ class A2dp(val context: Context) : A2DPImplBase() { override fun start(request: StartRequest, responseObserver: StreamObserver<StartResponse>) { grpcUnary<StartResponse>(scope, responseObserver) { if (audioTrack == null) { audioTrack = buildAudioTrack() } val address = request.source.cookie.toByteArray().decodeToString() val device = bluetoothAdapter.getRemoteDevice(address) Log.i(TAG, "start: address=$address") Loading @@ -177,7 +185,7 @@ class A2dp(val context: Context) : A2DPImplBase() { throw Status.UNKNOWN.asException() } audioTrack.play() audioTrack!!.play() // If A2dp is not already playing, wait for it if (!bluetoothA2dp.isA2dpPlaying(device)) { Loading Loading @@ -218,7 +226,7 @@ class A2dp(val context: Context) : A2DPImplBase() { } .map { it.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothAdapter.ERROR) } audioTrack.pause() audioTrack!!.pause() a2dpPlayingStateFlow.filter { it == BluetoothA2dp.STATE_NOT_PLAYING }.first() SuspendResponse.getDefaultInstance() } Loading Loading @@ -274,8 +282,10 @@ class A2dp(val context: Context) : A2DPImplBase() { ): StreamObserver<PlaybackAudioRequest> { Log.i(TAG, "playbackAudio") if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { responseObserver.onError(Status.UNKNOWN.withDescription("AudioTrack is not started").asException()) if (audioTrack!!.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { responseObserver.onError( Status.UNKNOWN.withDescription("AudioTrack is not started").asException() ) } // Volume is maxed out to avoid any amplitude modification of the provided audio data, Loading @@ -297,9 +307,7 @@ class A2dp(val context: Context) : A2DPImplBase() { return object : StreamObserver<PlaybackAudioRequest> { override fun onNext(request: PlaybackAudioRequest) { val data = request.data.toByteArray() val written = synchronized(audioTrack) { audioTrack.write(data, 0, data.size) } val written = synchronized(audioTrack!!) { audioTrack!!.write(data, 0, data.size) } if (written != data.size) { responseObserver.onError( Status.UNKNOWN.withDescription("AudioTrack write failed").asException() Loading android/pandora/server/src/com/android/pandora/Host.kt +3 −3 Original line number Diff line number Diff line Loading @@ -24,8 +24,6 @@ import android.content.Intent import android.content.IntentFilter import android.net.MacAddress import android.util.Log import pandora.HostGrpc.HostImplBase import pandora.HostProto.* import com.google.protobuf.ByteString import com.google.protobuf.Empty import io.grpc.Status Loading @@ -41,6 +39,8 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch import pandora.HostGrpc.HostImplBase import pandora.HostProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Host(private val context: Context, private val server: Server) : HostImplBase() { Loading android/pandora/server/src/com/android/pandora/Utils.kt +13 −13 File changed.Contains only whitespace changes. Show changes Loading
android/pandora/server/src/com/android/pandora/A2dp.kt +37 −29 Original line number Diff line number Diff line Loading @@ -26,8 +26,6 @@ import android.content.Intent import android.content.IntentFilter import android.media.* import android.util.Log import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* import io.grpc.Status import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope Loading @@ -40,6 +38,8 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dp(val context: Context) : A2DPImplBase() { Loading @@ -56,7 +56,24 @@ class A2dp(val context: Context) : A2DPImplBase() { private val bluetoothAdapter = bluetoothManager.adapter private val bluetoothA2dp = getProfileProxy<BluetoothA2dp>(context, BluetoothProfile.A2DP) private val audioTrack: AudioTrack = private var audioTrack: AudioTrack? = null init { scope = CoroutineScope(Dispatchers.Default) val intentFilter = IntentFilter() intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED) intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() } fun buildAudioTrack(): AudioTrack? { audioTrack = AudioTrack.Builder() .setAudioAttributes( AudioAttributes.Builder() Loading @@ -74,19 +91,7 @@ class A2dp(val context: Context) : A2DPImplBase() { .setTransferMode(AudioTrack.MODE_STREAM) .setBufferSizeInBytes(44100 * 2 * 2) .build() init { scope = CoroutineScope(Dispatchers.Default) val intentFilter = IntentFilter() intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED) intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED) flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() return audioTrack } override fun openSource( Loading Loading @@ -168,6 +173,9 @@ class A2dp(val context: Context) : A2DPImplBase() { override fun start(request: StartRequest, responseObserver: StreamObserver<StartResponse>) { grpcUnary<StartResponse>(scope, responseObserver) { if (audioTrack == null) { audioTrack = buildAudioTrack() } val address = request.source.cookie.toByteArray().decodeToString() val device = bluetoothAdapter.getRemoteDevice(address) Log.i(TAG, "start: address=$address") Loading @@ -177,7 +185,7 @@ class A2dp(val context: Context) : A2DPImplBase() { throw Status.UNKNOWN.asException() } audioTrack.play() audioTrack!!.play() // If A2dp is not already playing, wait for it if (!bluetoothA2dp.isA2dpPlaying(device)) { Loading Loading @@ -218,7 +226,7 @@ class A2dp(val context: Context) : A2DPImplBase() { } .map { it.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothAdapter.ERROR) } audioTrack.pause() audioTrack!!.pause() a2dpPlayingStateFlow.filter { it == BluetoothA2dp.STATE_NOT_PLAYING }.first() SuspendResponse.getDefaultInstance() } Loading Loading @@ -274,8 +282,10 @@ class A2dp(val context: Context) : A2DPImplBase() { ): StreamObserver<PlaybackAudioRequest> { Log.i(TAG, "playbackAudio") if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { responseObserver.onError(Status.UNKNOWN.withDescription("AudioTrack is not started").asException()) if (audioTrack!!.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { responseObserver.onError( Status.UNKNOWN.withDescription("AudioTrack is not started").asException() ) } // Volume is maxed out to avoid any amplitude modification of the provided audio data, Loading @@ -297,9 +307,7 @@ class A2dp(val context: Context) : A2DPImplBase() { return object : StreamObserver<PlaybackAudioRequest> { override fun onNext(request: PlaybackAudioRequest) { val data = request.data.toByteArray() val written = synchronized(audioTrack) { audioTrack.write(data, 0, data.size) } val written = synchronized(audioTrack!!) { audioTrack!!.write(data, 0, data.size) } if (written != data.size) { responseObserver.onError( Status.UNKNOWN.withDescription("AudioTrack write failed").asException() Loading
android/pandora/server/src/com/android/pandora/Host.kt +3 −3 Original line number Diff line number Diff line Loading @@ -24,8 +24,6 @@ import android.content.Intent import android.content.IntentFilter import android.net.MacAddress import android.util.Log import pandora.HostGrpc.HostImplBase import pandora.HostProto.* import com.google.protobuf.ByteString import com.google.protobuf.Empty import io.grpc.Status Loading @@ -41,6 +39,8 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch import pandora.HostGrpc.HostImplBase import pandora.HostProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Host(private val context: Context, private val server: Server) : HostImplBase() { Loading
android/pandora/server/src/com/android/pandora/Utils.kt +13 −13 File changed.Contains only whitespace changes. Show changes