diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index fdf8d99..d4b7acc 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6695ae7..6dcbac4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,8 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) + id("org.jetbrains.kotlin.plugin.serialization") version "2.0.20" } android { @@ -10,7 +12,7 @@ android { defaultConfig { applicationId = "usr.empty.player" minSdk = 34 - targetSdk = 34 + targetSdk = 35 versionCode = 1 versionName = "0.0.1α" @@ -63,11 +65,6 @@ dependencies { implementation(libs.androidx.media3.common) implementation(libs.androidx.media3.session) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) - androidTestImplementation(platform(libs.androidx.compose.bom)) - androidTestImplementation(libs.androidx.ui.test.junit4) - debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) } \ No newline at end of file diff --git a/app/src/main/java/usr/empty/player/MainActivity.kt b/app/src/main/java/usr/empty/player/MainActivity.kt index 6a1d3d8..e884543 100644 --- a/app/src/main/java/usr/empty/player/MainActivity.kt +++ b/app/src/main/java/usr/empty/player/MainActivity.kt @@ -6,15 +6,17 @@ import android.net.Uri import android.os.Bundle import android.os.Environment import android.provider.Settings -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -26,12 +28,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import usr.empty.player.ui.theme.PlayerTheme @@ -72,6 +76,7 @@ fun uriToPath(uri: Uri): String { @Composable fun MainLayout(modifier: Modifier = Modifier) { + val context = LocalContext.current val notas = remember { mutableStateListOf() } val pickAudioLauncher = rememberLauncherForActivityResult( @@ -92,12 +97,38 @@ fun MainLayout(modifier: Modifier = Modifier) { } Column(modifier.fillMaxSize()) { - Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary - ), modifier = Modifier.align(Alignment.CenterHorizontally), onClick = { - pickAudioLauncher.launch("audio/*") - }) { - Text("add track") + Row( + horizontalArrangement = Arrangement.Absolute.SpaceEvenly, + modifier = Modifier.fillMaxWidth(), + ) { + Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary + ), modifier = Modifier, onClick = { + pickAudioLauncher.launch("audio/*") + }) { + Text("add track") + } +// VerticalDivider() + Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary + ), modifier = Modifier, onClick = { + context.startService(Intent(context, PlayerService::class.java).apply { + putExtra("check", "empty") + putExtra("type", "pause") + }) + }) { + Text("| pause |") + } + Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary + ), modifier = Modifier, onClick = { + context.startService(Intent(context, PlayerService::class.java).apply { + putExtra("check", "empty") + putExtra("type", "play") + }) + }) { + Text("| play >") + } } NotaList(notas) } @@ -105,13 +136,20 @@ fun MainLayout(modifier: Modifier = Modifier) { @Composable fun NotaList(notas: List, modifier: Modifier = Modifier) { + val context = LocalContext.current LazyColumn( modifier = modifier, ) { items(notas) { nota -> Column(modifier = Modifier .fillParentMaxWidth() - .clickable { } + .clickable { + context.startService(Intent(context, PlayerService::class.java).apply { + putExtra("check", "empty") + putExtra("type", "nota") + putExtra("nota", Json.encodeToString(nota)) + }) + } .padding(4.dp) .padding(start = 16.dp)) { Text( @@ -121,7 +159,6 @@ fun NotaList(notas: List, modifier: Modifier = Modifier) { nota.artist, fontSize = 12.sp ) } - Log.d("nya", nota.toString()) } } } diff --git a/app/src/main/java/usr/empty/player/Nota.kt b/app/src/main/java/usr/empty/player/Nota.kt new file mode 100644 index 0000000..bc6e84e --- /dev/null +++ b/app/src/main/java/usr/empty/player/Nota.kt @@ -0,0 +1,13 @@ +package usr.empty.player + +import androidx.media3.common.MediaItem +import androidx.media3.exoplayer.ExoPlayer + + +class Nota(val descriptor: NotaDescriptor) { + val mediaSource = MediaItem.fromUri(descriptor.source) + + fun prepare(player: ExoPlayer) { + player.setMediaItem(mediaSource) + } +} \ No newline at end of file diff --git a/app/src/main/java/usr/empty/player/PlayerService.kt b/app/src/main/java/usr/empty/player/PlayerService.kt index f48c1cd..a71b6fd 100644 --- a/app/src/main/java/usr/empty/player/PlayerService.kt +++ b/app/src/main/java/usr/empty/player/PlayerService.kt @@ -8,11 +8,14 @@ import androidx.media3.session.MediaSession import androidx.media3.session.MediaSessionService import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.ListenableFuture +import kotlinx.serialization.json.Json +import java.util.concurrent.ConcurrentLinkedDeque class PlayerService : MediaSessionService() { - private var mediaSession: MediaSession? = null - var player: ExoPlayer? = null + private lateinit var mediaSession: MediaSession + lateinit var player: ExoPlayer + private var virtualQueue = ConcurrentLinkedDeque() override fun onCreate() { super.onCreate() @@ -20,26 +23,35 @@ class PlayerService : MediaSessionService() { player = this mediaSession = MediaSession.Builder(this@PlayerService, this).setCallback(MediaSessionCallback()).build() } - Log.d("meow", "memememe") } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + Log.d("nya", "start!!!") intent?.run { - + if (getStringExtra("check") != "empty") return@run + handleCommand(getStringExtra("type")!!, this) } return super.onStartCommand(intent, flags, startId) } - private fun start() { - + private fun handleCommand(type: String, intent: Intent) { + when (type) { + "nota" -> { + virtualQueue.add(Nota(Json.decodeFromString(intent.getStringExtra("nota")!!))) +// virtualQueue.first.prepare(player) + virtualQueue.last.prepare(player) + player.prepare() + player.play() + Log.d("nya", virtualQueue.last.mediaSource.toString()) + } + "pause" -> player.pause() + "play" -> player.play() + } } override fun onDestroy() { - player?.release() - mediaSession?.release() - player = null - mediaSession = null - Log.d("meow", "owowowow") + player.release() + mediaSession.release() super.onDestroy() } diff --git a/app/src/test/java/usr/empty/player/ExampleUnitTest.kt b/app/src/test/java/usr/empty/player/ExampleUnitTest.kt deleted file mode 100644 index 1de8dd7..0000000 --- a/app/src/test/java/usr/empty/player/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package usr.empty.player - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 20e2a01..316a8ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,5 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +org.gradle.configuration-cache=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ee673b..031b62f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,28 +1,19 @@ [versions] -agp = "8.6.0" -core = "1.6.1" -kotlin = "1.9.0" +agp = "8.6.1" +kotlin = "2.0.0" coreKtx = "1.13.1" -junit = "4.13.2" -junitVersion = "1.2.1" -espressoCore = "3.6.1" -kotlinxSerializationJson = "1.7.1" -lifecycleRuntimeKtx = "2.6.1" +kotlinxSerializationJson = "1.7.3" +lifecycleRuntimeKtx = "2.8.6" activityCompose = "1.9.2" -composeBom = "2024.04.01" +composeBom = "2024.09.02" media3Exoplayer = "1.4.1" -junitJupiter = "5.8.1" [libraries] -androidx-core = { module = "androidx.test:core", version.ref = "core" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-media3-common = { module = "androidx.media3:media3-common", version.ref = "media3Exoplayer" } androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" } androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3Exoplayer" } androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3Exoplayer" } -junit = { group = "junit", name = "junit", version.ref = "junit" } -androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } -androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } @@ -31,15 +22,11 @@ androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } -androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } -junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junitJupiter" } -mockito-core = { module = "org.mockito:mockito-core", version = "5.10.0" } -mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "5.4.0" } -mockk = { module = "io.mockk:mockk", version = "1.13.10" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }