diff --git a/Android/app/build.gradle.kts b/Android/app/build.gradle.kts index 743dc9c1..9d598d76 100644 --- a/Android/app/build.gradle.kts +++ b/Android/app/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } android { - namespace = "io.github.teamclouday.AndroidMic" + namespace = "io.github.teamclouday.androidMic" compileSdk = 36 defaultConfig { diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml index dec61b2f..ff0b702c 100644 --- a/Android/app/src/main/AndroidManifest.xml +++ b/Android/app/src/main/AndroidManifest.xml @@ -17,7 +17,7 @@ @@ -46,7 +46,7 @@ diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/AndroidMicApp.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/AndroidMicApp.kt similarity index 88% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/AndroidMicApp.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/AndroidMicApp.kt index 983cfb25..809665ee 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/AndroidMicApp.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/AndroidMicApp.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic +package io.github.teamclouday.androidMic import android.app.Application import android.content.ComponentName @@ -7,15 +7,15 @@ import android.content.ServiceConnection import android.os.IBinder import android.os.Messenger import android.util.Log -import io.github.teamclouday.AndroidMic.domain.service.BIND_SERVICE_ACTION -import io.github.teamclouday.AndroidMic.domain.service.ForegroundService -import io.github.teamclouday.AndroidMic.ui.MainActivity +import io.github.teamclouday.androidMic.domain.service.BIND_SERVICE_ACTION +import io.github.teamclouday.androidMic.domain.service.ForegroundService +import io.github.teamclouday.androidMic.ui.MainActivity import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch +private const val TAG = "AndroidMicApp" class AndroidMicApp : Application() { - private val TAG = "AndroidMicApp" companion object { diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/AppModule.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/AppModule.kt similarity index 80% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/AppModule.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/AppModule.kt index fb6477c1..1100c0af 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/AppModule.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/AppModule.kt @@ -1,7 +1,7 @@ -package io.github.teamclouday.AndroidMic +package io.github.teamclouday.androidMic import android.content.Context -import io.github.teamclouday.AndroidMic.ui.utils.UiHelper +import io.github.teamclouday.androidMic.ui.utils.UiHelper interface AppModule { diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/Preferences.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/Preferences.kt similarity index 85% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/Preferences.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/Preferences.kt index 9a32ddde..fc792899 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/Preferences.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/Preferences.kt @@ -1,11 +1,12 @@ -package io.github.teamclouday.AndroidMic +package io.github.teamclouday.androidMic import android.content.Context import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import io.github.teamclouday.AndroidMic.utils.PreferencesManager +import io.github.teamclouday.androidMic.ui.utils.UiHelper +import io.github.teamclouday.androidMic.utils.PreferencesManager object DefaultStates { const val IP = "192.168." @@ -92,4 +93,11 @@ enum class ChannelCount(val value: Int) { Stereo -> stringResource(R.string.stereo) } } + + fun getString(uiHelper: UiHelper): String { + return when (this) { + Mono -> uiHelper.getString(R.string.mono) + Stereo -> uiHelper.getString(R.string.stereo) + } + } } diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/audio/MicAudioManager.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/audio/MicAudioManager.kt similarity index 92% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/audio/MicAudioManager.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/audio/MicAudioManager.kt index 357257c6..77393574 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/audio/MicAudioManager.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/audio/MicAudioManager.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.domain.audio +package io.github.teamclouday.androidMic.domain.audio import android.Manifest import android.content.Context @@ -8,7 +8,7 @@ import android.media.AudioRecord import android.media.MediaRecorder import android.util.Log import androidx.core.content.ContextCompat -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.domain.service.AudioPacket import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.channels.awaitClose @@ -19,6 +19,9 @@ import kotlinx.coroutines.launch import java.nio.ByteBuffer import java.nio.ByteOrder + +private const val TAG: String = "MicAM" + // manage microphone recording class MicAudioManager( ctx: Context, @@ -28,7 +31,6 @@ class MicAudioManager( val channelCount: Int ) { - private val TAG: String = "MicAM" companion object { const val RECORD_DELAY_MS = 100L @@ -41,6 +43,8 @@ class MicAudioManager( private val bufferFloatConvert: ByteBuffer private var streamJob: Job? = null + private var isMuted = false + init { // check microphone require(ctx.packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) { @@ -92,6 +96,12 @@ class MicAudioManager( // launch in scope so infinite loop will be canceled when scope exits streamJob = scope.launch { while (true) { + + if (isMuted) { + delay(RECORD_DELAY_MS) + continue + } + if (recorder.state != AudioRecord.STATE_INITIALIZED || recorder.recordingState != AudioRecord.RECORDSTATE_RECORDING) { delay(RECORD_DELAY_MS) continue @@ -143,6 +153,14 @@ class MicAudioManager( } } + fun mute() { + isMuted = true + } + + fun unmute() { + isMuted = false + } + // start recording fun start() { recorder.startRecording() diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Command.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Command.kt similarity index 68% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Command.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Command.kt index d3481652..28bb6f55 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Command.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Command.kt @@ -1,21 +1,27 @@ -package io.github.teamclouday.AndroidMic.domain.service +package io.github.teamclouday.androidMic.domain.service import android.os.Bundle import android.os.Message -import io.github.teamclouday.AndroidMic.AppPreferences -import io.github.teamclouday.AndroidMic.AudioFormat -import io.github.teamclouday.AndroidMic.ChannelCount -import io.github.teamclouday.AndroidMic.Dialogs -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.SampleRates -import io.github.teamclouday.AndroidMic.utils.Either -import io.github.teamclouday.AndroidMic.utils.checkIp -import io.github.teamclouday.AndroidMic.utils.checkPort - +import io.github.teamclouday.androidMic.AppPreferences +import io.github.teamclouday.androidMic.AudioFormat +import io.github.teamclouday.androidMic.ChannelCount +import io.github.teamclouday.androidMic.Dialogs +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.SampleRates +import io.github.teamclouday.androidMic.utils.Either +import io.github.teamclouday.androidMic.utils.checkIp +import io.github.teamclouday.androidMic.utils.checkPort +/** + * Service -> UI + */ private const val ID_MSG: String = "ID_MSG" -private const val ID_STATE: String = "ID_STATE" +private const val ID_CONNECTION_STATE: String = "ID_CONNECTION_STATE" +private const val ID_MUTE_STATE: String = "ID_MUTE_STATE" +/** + * UI -> Service + */ private const val ID_MODE: String = "ID_MODE" private const val ID_IP: String = "ID_IP" @@ -27,7 +33,7 @@ private const val ID_AUDIO_FORMAT: String = "ID_AUDIO_FORMAT" /** - * Commands UI -> Service + * UI -> Service */ enum class Command { StartStream, @@ -36,18 +42,12 @@ enum class Command { // called when the ui is bind BindCheck, -} - -fun Bundle.getOrdinal(key: String): Int? { - val v = this.getInt(key, Int.MIN_VALUE); - return if (v == Int.MIN_VALUE) { - null - } else { - v - } + Mute, + Unmute, } + data class CommandData( val command: Command, val mode: Mode? = null, @@ -134,29 +134,38 @@ data class CommandData( /** - * Response Service -> UI + * Service -> UI */ -enum class Response { +enum class ResponseKind { Standard, } -enum class ServiceState { +private enum class ConnectionState { Connected, - Disconnected, + Disconnected; +} + +private enum class MuteState { + Muted, + Unmuted, } data class ResponseData( - val state: ServiceState? = null, val msg: String? = null, - val kind: Response = Response.Standard, + val isConnected: Boolean? = null, + val isMuted: Boolean? = null, + val kind: ResponseKind = ResponseKind.Standard, ) { companion object { fun fromMessage(msg: Message): ResponseData { return ResponseData( - kind = Response.entries[msg.what], - state = msg.data.getOrdinal(ID_STATE)?.let { ServiceState.entries[it] }, + kind = ResponseKind.entries[msg.what], + isConnected = msg.data.getOrdinal(ID_CONNECTION_STATE) + ?.let { ConnectionState.entries[it] == ConnectionState.Connected }, + isMuted = msg.data.getOrdinal(ID_MUTE_STATE) + ?.let { MuteState.entries[it] == MuteState.Muted }, msg = msg.data.getString(ID_MSG) ) } @@ -168,7 +177,18 @@ data class ResponseData( val r = Bundle() this.msg?.let { r.putString(ID_MSG, it) } - this.state?.let { r.putInt(ID_STATE, it.ordinal) } + this.isConnected?.let { + r.putInt( + ID_CONNECTION_STATE, + (if (it) ConnectionState.Connected else ConnectionState.Disconnected).ordinal + ) + } + this.isMuted?.let { + r.putInt( + ID_MUTE_STATE, + (if (it) MuteState.Muted else MuteState.Unmuted).ordinal + ) + } val reply = Message.obtain() reply.data = r @@ -180,4 +200,12 @@ data class ResponseData( } +fun Bundle.getOrdinal(key: String): Int? { + val v = this.getInt(key, Int.MIN_VALUE) + return if (v == Int.MIN_VALUE) { + null + } else { + v + } +} diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ForegroundService.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ForegroundService.kt similarity index 85% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ForegroundService.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ForegroundService.kt index f0a84080..f748e74a 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ForegroundService.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ForegroundService.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.domain.service +package io.github.teamclouday.androidMic.domain.service import android.app.NotificationChannel import android.app.NotificationManager @@ -13,11 +13,11 @@ import android.os.Message import android.os.Messenger import android.os.Process import android.util.Log -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.domain.audio.MicAudioManager -import io.github.teamclouday.AndroidMic.domain.streaming.MicStreamManager -import io.github.teamclouday.AndroidMic.utils.ignore +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.domain.audio.MicAudioManager +import io.github.teamclouday.androidMic.domain.streaming.MicStreamManager +import io.github.teamclouday.androidMic.utils.ignore import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -27,6 +27,7 @@ import kotlinx.coroutines.launch data class ServiceStates( var isStreamStarted: Boolean = false, var isAudioStarted: Boolean = false, + var isMuted: Boolean = false, var mode: Mode = Mode.WIFI ) @@ -52,6 +53,16 @@ class ForegroundService : Service() { Command.BindCheck -> { uiMessenger = msg.replyTo } + + Command.Mute -> { + states.isMuted = true + managerAudio?.mute() + } + + Command.Unmute -> { + states.isMuted = false + managerAudio?.unmute() + } } } @@ -181,13 +192,15 @@ class ForegroundService : Service() { // start streaming private fun startStream(msg: CommandData, replyTo: Messenger) { + states.isMuted = false // check connection state if (states.isStreamStarted) { reply( replyTo, ResponseData( - ServiceState.Connected, - this.getString(R.string.stream_already_started) + msg = this.getString(R.string.stream_already_started), + isConnected = true, + isMuted = states.isMuted, ) ) return @@ -206,8 +219,9 @@ class ForegroundService : Service() { reply( replyTo, ResponseData( - ServiceState.Disconnected, - applicationContext.getString(R.string.error) + e.message + msg = applicationContext.getString(R.string.error) + e.message, + isConnected = false, + isMuted = states.isMuted, ) ) return @@ -219,8 +233,9 @@ class ForegroundService : Service() { reply( replyTo, ResponseData( - ServiceState.Disconnected, - applicationContext.getString(R.string.failed_to_connect) + msg = applicationContext.getString(R.string.failed_to_connect), + isConnected = false, + isMuted = states.isMuted, ) ) shutdownStream() @@ -245,8 +260,9 @@ class ForegroundService : Service() { reply( replyTo, ResponseData( - ServiceState.Connected, - applicationContext.getString(R.string.connected_device) + managerStream?.getInfo() + msg = applicationContext.getString(R.string.connected_device) + managerStream?.getInfo(), + isConnected = true, + isMuted = states.isMuted, ) ) @@ -263,8 +279,9 @@ class ForegroundService : Service() { reply( uiMessenger, ResponseData( - ServiceState.Disconnected, - applicationContext.getString(R.string.device_disconnected) + msg = applicationContext.getString(R.string.device_disconnected), + isConnected = false, + isMuted = states.isMuted, ) ) @@ -279,13 +296,6 @@ class ForegroundService : Service() { states.isStreamStarted = false } - private fun isConnected(): ServiceState { - return if (states.isStreamStarted) { - ServiceState.Connected - } else { - ServiceState.Disconnected - } - } // start mic private fun startAudio(msg: CommandData, replyTo: Messenger): Boolean { @@ -349,6 +359,6 @@ class ForegroundService : Service() { private fun getStatus(replyTo: Messenger) { Log.d(TAG, "getStatus") - reply(replyTo, ResponseData(isConnected())) + reply(replyTo, ResponseData(isConnected = states.isStreamStarted, isMuted = states.isMuted)) } } \ No newline at end of file diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Packets.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Packets.kt similarity index 74% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Packets.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Packets.kt index ee5efd0e..52fc87be 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/Packets.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/Packets.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.domain.service +package io.github.teamclouday.androidMic.domain.service // definition of an audio packet data class AudioPacket( diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ServiceUtil.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ServiceUtil.kt similarity index 91% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ServiceUtil.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ServiceUtil.kt index 2b86308b..6f15bef5 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/service/ServiceUtil.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/service/ServiceUtil.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.domain.service +package io.github.teamclouday.androidMic.domain.service import android.app.Notification @@ -6,8 +6,8 @@ import android.app.PendingIntent import android.content.Intent import android.widget.Toast import androidx.core.app.NotificationCompat -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.ui.MainActivity +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.ui.MainActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,7 @@ class MessageUi(private val ctx: ForegroundService) { ctx.getString(R.string.stop_streaming), pStopStreamingIntent ) - ); + ) return builder.build() } diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/BluetoothStreamer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/BluetoothStreamer.kt similarity index 94% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/BluetoothStreamer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/BluetoothStreamer.kt index 02788b26..505d95f6 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/BluetoothStreamer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/BluetoothStreamer.kt @@ -1,6 +1,6 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming -import Message +import Message.Messages import android.Manifest import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothClass @@ -17,10 +17,10 @@ import android.os.Messenger import android.util.Log import androidx.core.content.ContextCompat import com.google.protobuf.ByteString -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket -import io.github.teamclouday.AndroidMic.utils.chunked -import io.github.teamclouday.AndroidMic.utils.ignore -import io.github.teamclouday.AndroidMic.utils.toBigEndianU32 +import io.github.teamclouday.androidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.utils.chunked +import io.github.teamclouday.androidMic.utils.ignore +import io.github.teamclouday.androidMic.utils.toBigEndianU32 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -29,8 +29,10 @@ import kotlinx.coroutines.launch import java.io.IOException import java.util.UUID + +private const val TAG: String = "BluetoothStreamer" + class BluetoothStreamer(private val ctx: Context, val scope: CoroutineScope) : Streamer { - private val TAG: String = "MicStreamBTH" private val myUUID: UUID = UUID.fromString("34335e34-bccf-11eb-8529-0242ac130003") @@ -124,7 +126,7 @@ class BluetoothStreamer(private val ctx: Context, val scope: CoroutineScope) : S if (socket == null || socket?.isConnected != true) return@collect try { - val message = Message.AudioPacketMessage.newBuilder() + val message = Messages.AudioPacketMessage.newBuilder() .setBuffer(ByteString.copyFrom(data.buffer)) .setSampleRate(data.sampleRate) .setAudioFormat(data.audioFormat) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/MicStreamManager.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/MicStreamManager.kt similarity index 85% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/MicStreamManager.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/MicStreamManager.kt index 42d7621f..0eb8809e 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/MicStreamManager.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/MicStreamManager.kt @@ -1,16 +1,16 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming import android.content.Context import android.os.Messenger -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.domain.service.AudioPacket import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow // manage streaming data class MicStreamManager( ctx: Context, - val scope: CoroutineScope, + scope: CoroutineScope, val mode: Mode, ip: String?, port: Int? diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/Streamer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/Streamer.kt similarity index 64% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/Streamer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/Streamer.kt index a725eb58..2bafd646 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/Streamer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/Streamer.kt @@ -1,14 +1,14 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming import android.os.Messenger -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.domain.service.AudioPacket import kotlinx.coroutines.flow.Flow const val CHECK_1 = "AndroidMic1" const val CHECK_2 = "AndroidMic2" -const val DEFAULT_PORT: Int = 55555; -const val MAX_PORT: Int = 55570; +const val DEFAULT_PORT: Int = 55555 +const val MAX_PORT: Int = 55570 interface Streamer { fun connect(): Boolean diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/TcpStreamer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/TcpStreamer.kt similarity index 93% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/TcpStreamer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/TcpStreamer.kt index 3b258594..40de1a07 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/TcpStreamer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/TcpStreamer.kt @@ -1,15 +1,15 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming -import Message +import Message.Messages import android.content.Context import android.net.ConnectivityManager import android.os.Messenger import android.util.Log import com.google.protobuf.ByteString -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket -import io.github.teamclouday.AndroidMic.domain.service.Command -import io.github.teamclouday.AndroidMic.domain.service.CommandData -import io.github.teamclouday.AndroidMic.utils.toBigEndianU32 +import io.github.teamclouday.androidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.domain.service.Command +import io.github.teamclouday.androidMic.domain.service.CommandData +import io.github.teamclouday.androidMic.utils.toBigEndianU32 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -109,7 +109,7 @@ class TcpStreamer( if (socket == null || socket?.isConnected != true) return@collect try { - val message = Message.AudioPacketMessage.newBuilder() + val message = Messages.AudioPacketMessage.newBuilder() .setBuffer(ByteString.copyFrom(data.buffer)) .setSampleRate(data.sampleRate) .setAudioFormat(data.audioFormat) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UdpStreamer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UdpStreamer.kt similarity index 51% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UdpStreamer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UdpStreamer.kt index 4c183f37..9c725a79 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UdpStreamer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UdpStreamer.kt @@ -1,11 +1,11 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming -import Message +import Message.Messages import android.os.Messenger import android.util.Log import com.google.protobuf.ByteString -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket -import io.github.teamclouday.AndroidMic.utils.toBigEndianU32 +import io.github.teamclouday.androidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.utils.toBigEndianU32 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow @@ -14,9 +14,11 @@ import java.net.DatagramPacket import java.net.DatagramSocket import java.net.InetAddress +private const val TAG: String = "UDP streamer" + class UdpStreamer(private val scope: CoroutineScope, val ip: String, var port: Int) : Streamer { - private val TAG: String = "UDP streamer" + private val socket: DatagramSocket = DatagramSocket() private val address = InetAddress.getByName(ip) @@ -25,7 +27,41 @@ class UdpStreamer(private val scope: CoroutineScope, val ip: String, var port: I override fun connect(): Boolean { socket.soTimeout = 1500 - return true + + val message = Messages.MessageWrapper.newBuilder() + .setConnect( + Messages.ConnectMessage.newBuilder() + .build() + ) + .build() + + val pack = message.toByteArray() + val combined = pack.size.toBigEndianU32() + pack + + val packet = DatagramPacket( + combined, + 0, + combined.size, + address, + port + ) + + try { + socket.send(packet) + } catch (_: Exception) { + return false + } + + val buff = ByteArray(CHECK_2.length) + val recvPacket = DatagramPacket(buff, buff.size) + + try { + socket.receive(recvPacket) + } catch (_: Exception) { + return false + } + + return recvPacket.data.contentEquals(CHECK_2.toByteArray()) } override fun disconnect(): Boolean { @@ -45,18 +81,23 @@ class UdpStreamer(private val scope: CoroutineScope, val ip: String, var port: I streamJob = scope.launch { audioStream.collect { data -> try { - val message = Message.AudioPacketMessageOrdered.newBuilder() - .setSequenceNumber(sequenceIdx++) + + val message = Messages.MessageWrapper.newBuilder() .setAudioPacket( - Message.AudioPacketMessage.newBuilder() - .setBuffer(ByteString.copyFrom(data.buffer)) - .setSampleRate(data.sampleRate) - .setAudioFormat(data.audioFormat) - .setChannelCount(data.channelCount) + Messages.AudioPacketMessageOrdered.newBuilder() + .setSequenceNumber(sequenceIdx++) + .setAudioPacket( + Messages.AudioPacketMessage.newBuilder() + .setBuffer(ByteString.copyFrom(data.buffer)) + .setSampleRate(data.sampleRate) + .setAudioFormat(data.audioFormat) + .setChannelCount(data.channelCount) + ) .build() ) .build() + val pack = message.toByteArray() val combined = pack.size.toBigEndianU32() + pack @@ -65,7 +106,7 @@ class UdpStreamer(private val scope: CoroutineScope, val ip: String, var port: I 0, combined.size, address, - port!! + port ) socket.send(packet) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UsbStreamer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UsbStreamer.kt similarity index 90% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UsbStreamer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UsbStreamer.kt index 9d177dc3..161f421f 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/domain/streaming/UsbStreamer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/domain/streaming/UsbStreamer.kt @@ -1,6 +1,6 @@ -package io.github.teamclouday.AndroidMic.domain.streaming +package io.github.teamclouday.androidMic.domain.streaming -import Message +import Message.Messages import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context @@ -14,8 +14,8 @@ import android.os.ParcelFileDescriptor import android.util.Log import androidx.core.os.BundleCompat import com.google.protobuf.ByteString -import io.github.teamclouday.AndroidMic.domain.service.AudioPacket -import io.github.teamclouday.AndroidMic.utils.toBigEndianU32 +import io.github.teamclouday.androidMic.domain.service.AudioPacket +import io.github.teamclouday.androidMic.utils.toBigEndianU32 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow @@ -24,10 +24,14 @@ import java.io.FileDescriptor import java.io.FileInputStream import java.io.FileOutputStream + +private const val TAG: String = "USB streamer" + class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { - private val TAG: String = "USB streamer" - private val USB_PERMISSION = "io.github.teamclouday.AndroidMic.USB_PERMISSION" + companion object { + private const val USB_PERMISSION = "io.github.teamclouday.AndroidMic.USB_PERMISSION" + } private var streamJob: Job? = null @@ -44,7 +48,7 @@ class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { if (action == UsbManager.ACTION_USB_ACCESSORY_DETACHED) { Log.d(TAG, "onReceive: USB accessory detached") - val acc = BundleCompat.getParcelable( + val acc = BundleCompat.getParcelable( intent.extras!!, UsbManager.EXTRA_ACCESSORY, UsbAccessory::class.java, @@ -102,7 +106,7 @@ class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { "No USB device detected" } - accessory = accessoryList[0]; + accessory = accessoryList[0] Log.d( TAG, @@ -114,7 +118,7 @@ class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { Log.d(TAG, "requesting permission") usbManager.requestPermission( accessory, PendingIntent.getBroadcast( - ctx, 0, Intent(USB_PERMISSION), 0 + ctx, 0, Intent(USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE ) ) } @@ -159,7 +163,7 @@ class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { if (accessory == null || outputStream == null) return@collect try { - val message = Message.AudioPacketMessage.newBuilder() + val message = Messages.AudioPacketMessage.newBuilder() .setBuffer(ByteString.copyFrom(data.buffer)) .setSampleRate(data.sampleRate) .setAudioFormat(data.audioFormat) @@ -188,4 +192,6 @@ class UsbStreamer(ctx: Context, private val scope: CoroutineScope) : Streamer { override fun isAlive(): Boolean { return true } + + } \ No newline at end of file diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainActivity.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainActivity.kt similarity index 77% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainActivity.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainActivity.kt index 18bee58e..dae3232f 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainActivity.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainActivity.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui +package io.github.teamclouday.androidMic.ui import android.content.Intent import android.os.Bundle @@ -6,17 +6,16 @@ import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels -import io.github.teamclouday.AndroidMic.AndroidMicApp -import io.github.teamclouday.AndroidMic.domain.service.WAIT_PERIOD -import io.github.teamclouday.AndroidMic.ui.home.HomeScreen -import io.github.teamclouday.AndroidMic.ui.home.openAppSettings -import io.github.teamclouday.AndroidMic.ui.theme.AndroidMicTheme -import io.github.teamclouday.AndroidMic.ui.utils.rememberWindowInfo -import io.github.teamclouday.AndroidMic.utils.ignore - - +import io.github.teamclouday.androidMic.AndroidMicApp +import io.github.teamclouday.androidMic.domain.service.WAIT_PERIOD +import io.github.teamclouday.androidMic.ui.home.HomeScreen +import io.github.teamclouday.androidMic.ui.home.openAppSettings +import io.github.teamclouday.androidMic.ui.theme.AndroidMicTheme +import io.github.teamclouday.androidMic.ui.utils.rememberWindowInfo +import io.github.teamclouday.androidMic.utils.ignore + +private const val TAG = "MainActivity" class MainActivity : ComponentActivity() { - private val TAG = "MainActivity" val vm: MainViewModel by viewModels() diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainViewModel.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainViewModel.kt similarity index 74% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainViewModel.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainViewModel.kt index 138e307e..43df32a1 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/MainViewModel.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/MainViewModel.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui +package io.github.teamclouday.androidMic.ui import android.os.Handler import android.os.HandlerThread @@ -10,31 +10,27 @@ import android.util.Log import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import io.github.teamclouday.AndroidMic.AndroidMicApp -import io.github.teamclouday.AndroidMic.AppPreferences -import io.github.teamclouday.AndroidMic.AudioFormat -import io.github.teamclouday.AndroidMic.ChannelCount -import io.github.teamclouday.AndroidMic.Dialogs -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.SampleRates -import io.github.teamclouday.AndroidMic.Themes -import io.github.teamclouday.AndroidMic.domain.service.Command -import io.github.teamclouday.AndroidMic.domain.service.CommandData -import io.github.teamclouday.AndroidMic.domain.service.Response -import io.github.teamclouday.AndroidMic.domain.service.ResponseData -import io.github.teamclouday.AndroidMic.domain.service.ServiceState -import io.github.teamclouday.AndroidMic.ui.utils.UiHelper -import io.github.teamclouday.AndroidMic.utils.Either +import io.github.teamclouday.androidMic.AndroidMicApp +import io.github.teamclouday.androidMic.AppPreferences +import io.github.teamclouday.androidMic.AudioFormat +import io.github.teamclouday.androidMic.ChannelCount +import io.github.teamclouday.androidMic.Dialogs +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.SampleRates +import io.github.teamclouday.androidMic.Themes +import io.github.teamclouday.androidMic.domain.service.Command +import io.github.teamclouday.androidMic.domain.service.CommandData +import io.github.teamclouday.androidMic.domain.service.ResponseData +import io.github.teamclouday.androidMic.domain.service.ResponseKind +import io.github.teamclouday.androidMic.ui.utils.UiHelper +import io.github.teamclouday.androidMic.utils.Either import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking - +private const val TAG = "MainViewModel" class MainViewModel : ViewModel() { - private val TAG = "MainViewModel" - - val prefs: AppPreferences = AndroidMicApp.appModule.appPreferences val uiHelper: UiHelper = AndroidMicApp.appModule.uiHelper @@ -51,6 +47,8 @@ class MainViewModel : ViewModel() { val isStreamStarted = mutableStateOf(false) val isButtonConnectClickable = mutableStateOf(false) + val isMuted = mutableStateOf(false) + init { Log.d(TAG, "init") } @@ -61,10 +59,14 @@ class MainViewModel : ViewModel() { val data = ResponseData.fromMessage(msg) when (data.kind) { - Response.Standard -> { - data.state?.let { + ResponseKind.Standard -> { + data.isConnected?.let { isButtonConnectClickable.value = true - isStreamStarted.value = it == ServiceState.Connected + isStreamStarted.value = it + } + + data.isMuted?.let { + isMuted.value = it } data.msg?.let { @@ -89,14 +91,31 @@ class MainViewModel : ViewModel() { isStreamStarted.value = false isButtonConnectClickable.value = false + isMuted.value = false val msg = CommandData(Command.BindCheck).toCommandMsg() msg.replyTo = messenger service?.send(msg) } + fun onMuteSwitch() { + if (!isBound) return + + val message = if (isMuted.value) { + isMuted.value = false + CommandData(Command.Unmute) + } else { + isMuted.value = true + CommandData(Command.Mute) + }.toCommandMsg() + + message.replyTo = messenger + service?.send(message) + } + fun onConnectButton(): Dialogs? { if (!isBound) return null + isMuted.value = false val message = if (isStreamStarted.value) { Log.d(TAG, "onConnectButton: stop stream") CommandData(Command.StopStream) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/components/Components.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/components/Components.kt similarity index 98% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/components/Components.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/components/Components.kt index 61d34065..7e56a208 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/components/Components.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/components/Components.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.components +package io.github.teamclouday.androidMic.ui.components import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/AppBar.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/AppBar.kt similarity index 94% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/AppBar.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/AppBar.kt index a428b25a..87d283a5 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/AppBar.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/AppBar.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home +package io.github.teamclouday.androidMic.ui.home import androidx.compose.foundation.layout.size @@ -15,7 +15,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import io.github.teamclouday.AndroidMic.R +import io.github.teamclouday.androidMic.R @OptIn(ExperimentalMaterial3Api::class) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/HomeScreen.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/HomeScreen.kt similarity index 77% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/HomeScreen.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/HomeScreen.kt index 82fa4058..5f939b0d 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/HomeScreen.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/HomeScreen.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home +package io.github.teamclouday.androidMic.ui.home import androidx.activity.compose.BackHandler import androidx.activity.compose.rememberLauncherForActivityResult @@ -12,12 +12,15 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.DrawerValue @@ -25,6 +28,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalDrawerSheet import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.Scaffold +import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable @@ -36,13 +40,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import io.github.teamclouday.AndroidMic.Dialogs -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.ui.MainViewModel -import io.github.teamclouday.AndroidMic.ui.components.ManagerButton -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogIpPort -import io.github.teamclouday.AndroidMic.ui.utils.WindowInfo +import io.github.teamclouday.androidMic.Dialogs +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.ui.components.ManagerButton +import io.github.teamclouday.androidMic.ui.home.dialog.DialogIpPort +import io.github.teamclouday.androidMic.ui.utils.WindowInfo import kotlinx.coroutines.launch @@ -103,12 +107,23 @@ fun HomeScreen( .fillMaxWidth() .padding(all = 15.dp) ) + + Spacer(modifier = Modifier.height(40.dp)) ConnectButton( vm = vm, - modifier = Modifier - .padding(vertical = 40.dp), + modifier = Modifier, openAppSettings = openAppSettings ) + + if (vm.isStreamStarted.value) { + Spacer(modifier = Modifier.height(15.dp)) + + AudioSwitch( + vm = vm, + ) + } + + Spacer(modifier = Modifier.height(40.dp)) } } else { @@ -128,12 +143,26 @@ fun HomeScreen( .padding(all = 15.dp) ) - ConnectButton( - vm = vm, + Column( modifier = Modifier .padding(all = 15.dp), - openAppSettings = openAppSettings - ) + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + ConnectButton( + vm = vm, + modifier = Modifier, + openAppSettings = openAppSettings + ) + + + if (vm.isStreamStarted.value) { + Spacer(modifier = Modifier.height(15.dp)) + AudioSwitch( + vm = vm, + ) + } + } } } @@ -170,6 +199,31 @@ private fun Log( } } +@Composable +private fun AudioSwitch( + vm: MainViewModel, +) { + + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + + Text( + text = stringResource(id = R.string.turn_audio), + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.labelLarge + ) + Spacer(Modifier.width(12.dp)) + Switch( + checked = vm.isMuted.value, + onCheckedChange = { + vm.onMuteSwitch() + } + ) + } +} + @Composable private fun ConnectButton( vm: MainViewModel, diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/NavigationDrawer.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/NavigationDrawer.kt similarity index 92% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/NavigationDrawer.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/NavigationDrawer.kt index 1040c3e6..7bcd2673 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/NavigationDrawer.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/NavigationDrawer.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home +package io.github.teamclouday.androidMic.ui.home import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -27,15 +27,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.ui.MainViewModel -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogAudioFormat -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogChannelCount -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogIpPort -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogMode -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogSampleRate -import io.github.teamclouday.AndroidMic.ui.home.dialog.DialogTheme +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.ui.home.dialog.DialogAudioFormat +import io.github.teamclouday.androidMic.ui.home.dialog.DialogChannelCount +import io.github.teamclouday.androidMic.ui.home.dialog.DialogIpPort +import io.github.teamclouday.androidMic.ui.home.dialog.DialogMode +import io.github.teamclouday.androidMic.ui.home.dialog.DialogSampleRate +import io.github.teamclouday.androidMic.ui.home.dialog.DialogTheme @Composable @@ -120,7 +120,7 @@ fun DrawerBody(vm: MainViewModel) { DialogChannelCount(vm = vm, expanded = dialogChannelCountExpanded) SettingsItem( title = stringResource(id = R.string.channel_count), - subTitle = vm.prefs.channelCount.getAsState().value.toString(), + subTitle = vm.prefs.channelCount.getAsState().value.getString(), contentDescription = "set channel count", expanded = dialogChannelCountExpanded ) diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/PermissionHelper.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/PermissionHelper.kt similarity index 90% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/PermissionHelper.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/PermissionHelper.kt index 79d653f0..47c7e9c0 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/PermissionHelper.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/PermissionHelper.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home +package io.github.teamclouday.androidMic.ui.home import android.Manifest import android.app.Activity @@ -9,9 +9,9 @@ import android.provider.Settings import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import io.github.teamclouday.AndroidMic.ui.MainViewModel -import io.github.teamclouday.AndroidMic.ui.components.ManagerButton -import io.github.teamclouday.AndroidMic.ui.home.dialog.BaseDialog +import io.github.teamclouday.androidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.ui.components.ManagerButton +import io.github.teamclouday.androidMic.ui.home.dialog.BaseDialog fun getWifiPermission(): MutableList { val list = mutableListOf() diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/BaseDialog.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/BaseDialog.kt similarity index 95% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/BaseDialog.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/BaseDialog.kt index ba7e0c91..ab3702d9 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/BaseDialog.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/BaseDialog.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home.dialog +package io.github.teamclouday.androidMic.ui.home.dialog import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -16,7 +16,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import io.github.teamclouday.AndroidMic.ui.components.ManagerButton +import io.github.teamclouday.androidMic.ui.components.ManagerButton @Composable fun BaseDialog( diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/audio.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/audio.kt similarity index 72% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/audio.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/audio.kt index 7848ff58..77499186 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/audio.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/audio.kt @@ -1,11 +1,11 @@ -package io.github.teamclouday.AndroidMic.ui.home.dialog +package io.github.teamclouday.androidMic.ui.home.dialog import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import io.github.teamclouday.AndroidMic.AudioFormat -import io.github.teamclouday.AndroidMic.ChannelCount -import io.github.teamclouday.AndroidMic.SampleRates -import io.github.teamclouday.AndroidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.AudioFormat +import io.github.teamclouday.androidMic.ChannelCount +import io.github.teamclouday.androidMic.SampleRates +import io.github.teamclouday.androidMic.ui.MainViewModel @Composable fun DialogSampleRate( @@ -29,7 +29,7 @@ fun DialogChannelCount( expanded, enum = ChannelCount.entries, onClick = { vm.setChannelCount(it) }, - text = { it.toString() } + text = { it.getString(vm.uiHelper) } ) } diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/ipPort.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/ipPort.kt similarity index 88% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/ipPort.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/ipPort.kt index d6091f82..f8d08529 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/ipPort.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/ipPort.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.home.dialog +package io.github.teamclouday.androidMic.ui.home.dialog import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -13,11 +13,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import io.github.teamclouday.AndroidMic.DefaultStates -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.ui.MainViewModel -import io.github.teamclouday.AndroidMic.ui.components.ManagerButton -import io.github.teamclouday.AndroidMic.ui.components.ManagerOutlinedTextField +import io.github.teamclouday.androidMic.DefaultStates +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.ui.components.ManagerButton +import io.github.teamclouday.androidMic.ui.components.ManagerOutlinedTextField @Composable fun DialogIpPort(vm: MainViewModel, expanded: MutableState) { diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/mode.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/mode.kt similarity index 67% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/mode.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/mode.kt index 1c165bd9..863a2a18 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/mode.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/mode.kt @@ -1,9 +1,9 @@ -package io.github.teamclouday.AndroidMic.ui.home.dialog +package io.github.teamclouday.androidMic.ui.home.dialog import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import io.github.teamclouday.AndroidMic.Mode -import io.github.teamclouday.AndroidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.Mode +import io.github.teamclouday.androidMic.ui.MainViewModel @Composable fun DialogMode( diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/theme.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/theme.kt similarity index 74% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/theme.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/theme.kt index ec02ee6a..1ac85841 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/home/dialog/theme.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/home/dialog/theme.kt @@ -1,13 +1,13 @@ -package io.github.teamclouday.AndroidMic.ui.home.dialog +package io.github.teamclouday.androidMic.ui.home.dialog import android.os.Build import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.ui.res.stringResource -import io.github.teamclouday.AndroidMic.R -import io.github.teamclouday.AndroidMic.Themes -import io.github.teamclouday.AndroidMic.ui.MainViewModel -import io.github.teamclouday.AndroidMic.ui.components.ManagerCheckBox +import io.github.teamclouday.androidMic.R +import io.github.teamclouday.androidMic.Themes +import io.github.teamclouday.androidMic.ui.MainViewModel +import io.github.teamclouday.androidMic.ui.components.ManagerCheckBox @Composable fun DialogTheme( diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Color.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Color.kt similarity index 74% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Color.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Color.kt index c9af129c..1c94568a 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Color.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.theme +package io.github.teamclouday.androidMic.ui.theme import androidx.compose.ui.graphics.Color diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Theme.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Theme.kt similarity index 95% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Theme.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Theme.kt index 45b02d6c..307b2f8e 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Theme.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Theme.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.theme +package io.github.teamclouday.androidMic.ui.theme import android.os.Build @@ -11,7 +11,7 @@ import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import io.github.teamclouday.AndroidMic.Themes +import io.github.teamclouday.androidMic.Themes private val DarkColorScheme = darkColorScheme( diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Type.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Type.kt similarity index 97% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Type.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Type.kt index 8dd7414c..0767ccd3 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/theme/Type.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.theme +package io.github.teamclouday.androidMic.ui.theme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/UiHelper.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/UiHelper.kt similarity index 94% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/UiHelper.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/UiHelper.kt index cda73ad2..9467840b 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/UiHelper.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/UiHelper.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.utils +package io.github.teamclouday.androidMic.ui.utils import android.content.Context import android.widget.Toast diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/ViewModelFactoryHelper.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/ViewModelFactoryHelper.kt similarity index 88% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/ViewModelFactoryHelper.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/ViewModelFactoryHelper.kt index 88d83e9b..aced344c 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/ViewModelFactoryHelper.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/ViewModelFactoryHelper.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.ui.utils +package io.github.teamclouday.androidMic.ui.utils import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/rememberWindowInfo.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/rememberWindowInfo.kt similarity index 50% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/rememberWindowInfo.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/rememberWindowInfo.kt index b177dd34..8a4e0b10 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/ui/utils/rememberWindowInfo.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/ui/utils/rememberWindowInfo.kt @@ -1,26 +1,32 @@ -package io.github.teamclouday.AndroidMic.ui.utils +package io.github.teamclouday.androidMic.ui.utils import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @Composable fun rememberWindowInfo(): WindowInfo { - val configuration = LocalConfiguration.current + val windowInfo = LocalWindowInfo.current + val size = windowInfo.containerSize + + val widthDp = with(LocalDensity.current) { size.width.toDp() } + val heightDp = with(LocalDensity.current) { size.height.toDp() } + return WindowInfo( screenWidthInfo = when { - configuration.screenWidthDp < 600 -> WindowInfo.WindowType.Compact - configuration.screenWidthDp < 840 -> WindowInfo.WindowType.Medium + widthDp < 600.dp -> WindowInfo.WindowType.Compact + widthDp < 840.dp -> WindowInfo.WindowType.Medium else -> WindowInfo.WindowType.Expanded }, screenHeightInfo = when { - configuration.screenHeightDp < 480 -> WindowInfo.WindowType.Compact - configuration.screenHeightDp < 900 -> WindowInfo.WindowType.Medium + heightDp < 480.dp -> WindowInfo.WindowType.Compact + heightDp < 900.dp -> WindowInfo.WindowType.Medium else -> WindowInfo.WindowType.Expanded }, - screenWidth = configuration.screenWidthDp.dp, - screenHeight = configuration.screenHeightDp.dp + screenWidth = widthDp, + screenHeight = heightDp ) } diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/PreferencesManager.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/utils/PreferencesManager.kt similarity index 97% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/PreferencesManager.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/utils/PreferencesManager.kt index 333fcbdc..a542e35d 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/PreferencesManager.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/utils/PreferencesManager.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.utils +package io.github.teamclouday.androidMic.utils import android.content.Context import androidx.compose.runtime.Composable @@ -14,7 +14,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringSetPreferencesKey import androidx.datastore.preferences.preferencesDataStore import androidx.lifecycle.compose.collectAsStateWithLifecycle -import io.github.teamclouday.AndroidMic.utils.PreferencesManager.Companion.editor +import io.github.teamclouday.androidMic.utils.PreferencesManager.Companion.editor import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map diff --git a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/Utils.kt b/Android/app/src/main/java/io/github/teamclouday/androidMic/utils/Utils.kt similarity index 90% rename from Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/Utils.kt rename to Android/app/src/main/java/io/github/teamclouday/androidMic/utils/Utils.kt index f2785a5d..ab70f8c1 100644 --- a/Android/app/src/main/java/io/github/teamclouday/AndroidMic/utils/Utils.kt +++ b/Android/app/src/main/java/io/github/teamclouday/androidMic/utils/Utils.kt @@ -1,4 +1,4 @@ -package io.github.teamclouday.AndroidMic.utils +package io.github.teamclouday.androidMic.utils import java.net.InetSocketAddress @@ -16,7 +16,7 @@ fun checkIp(ip: String): Boolean { return try { InetSocketAddress(ip, 6000) true - } catch (e: Exception) { + } catch (_: Exception) { false } } @@ -29,13 +29,13 @@ fun checkPort(portStr: String, emptyAllowed: Boolean): Boolean { val port = try { portStr.toInt() - } catch (e: NumberFormatException) { + } catch (_: NumberFormatException) { return false } return try { InetSocketAddress("127.0.0.1", port) true - } catch (e: Exception) { + } catch (_: Exception) { false } } diff --git a/Android/app/src/main/proto/message.proto b/Android/app/src/main/proto/message.proto deleted file mode 100644 index c6c14585..00000000 --- a/Android/app/src/main/proto/message.proto +++ /dev/null @@ -1,13 +0,0 @@ -syntax = "proto3"; - -message AudioPacketMessage { - bytes buffer = 1; - uint32 sample_rate = 2; - uint32 channel_count = 3; - uint32 audio_format = 4; -} - -message AudioPacketMessageOrdered { - uint32 sequence_number = 1; - AudioPacketMessage audio_packet = 2; -} \ No newline at end of file diff --git a/Android/app/src/main/proto/messages.proto b/Android/app/src/main/proto/messages.proto new file mode 100644 index 00000000..9985196f --- /dev/null +++ b/Android/app/src/main/proto/messages.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package Message; + +message AudioPacketMessage { + bytes buffer = 1; + uint32 sample_rate = 2; + uint32 channel_count = 3; + uint32 audio_format = 4; +} + +message AudioPacketMessageOrdered { + uint32 sequence_number = 1; + AudioPacketMessage audio_packet = 2; +} + +message ConnectMessage {} + +message MessageWrapper { + oneof payload { + AudioPacketMessageOrdered audio_packet = 1; + ConnectMessage connect = 2; + } +} \ No newline at end of file diff --git a/Android/app/src/main/res/values-fr/strings.xml b/Android/app/src/main/res/values-fr/strings.xml index abcfd19c..9617c432 100644 --- a/Android/app/src/main/res/values-fr/strings.xml +++ b/Android/app/src/main/res/values-fr/strings.xml @@ -4,7 +4,7 @@ --> Connecter Deconnecter - Enregister l\'audio + Muter l\'audio 连接 断开连接 - 录制音频 Connect Disconnect - Record Audio + Mute Audio