kinda works

This commit is contained in:
Isaac Iwasaki 2024-09-26 01:43:56 +07:00
parent fdfb0aa679
commit b78a1cb407
8 changed files with 95 additions and 65 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="KotlinJpsPluginSettings"> <component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.0" /> <option name="version" value="2.0.20" />
</component> </component>
</project> </project>

View file

@ -1,6 +1,8 @@
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
alias(libs.plugins.compose.compiler)
id("org.jetbrains.kotlin.plugin.serialization") version "2.0.20"
} }
android { android {
@ -10,7 +12,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "usr.empty.player" applicationId = "usr.empty.player"
minSdk = 34 minSdk = 34
targetSdk = 34 targetSdk = 35
versionCode = 1 versionCode = 1
versionName = "0.0.1α" versionName = "0.0.1α"
@ -63,11 +65,6 @@ dependencies {
implementation(libs.androidx.media3.common) implementation(libs.androidx.media3.common)
implementation(libs.androidx.media3.session) 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.tooling)
debugImplementation(libs.androidx.ui.test.manifest) debugImplementation(libs.androidx.ui.test.manifest)
} }

View file

@ -6,15 +6,17 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.provider.Settings import android.provider.Settings
import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
@ -26,12 +28,14 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import usr.empty.player.ui.theme.PlayerTheme import usr.empty.player.ui.theme.PlayerTheme
@ -72,6 +76,7 @@ fun uriToPath(uri: Uri): String {
@Composable @Composable
fun MainLayout(modifier: Modifier = Modifier) { fun MainLayout(modifier: Modifier = Modifier) {
val context = LocalContext.current
val notas = remember { mutableStateListOf<NotaDescriptor>() } val notas = remember { mutableStateListOf<NotaDescriptor>() }
val pickAudioLauncher = rememberLauncherForActivityResult( val pickAudioLauncher = rememberLauncherForActivityResult(
@ -92,26 +97,59 @@ fun MainLayout(modifier: Modifier = Modifier) {
} }
Column(modifier.fillMaxSize()) { Column(modifier.fillMaxSize()) {
Row(
horizontalArrangement = Arrangement.Absolute.SpaceEvenly,
modifier = Modifier.fillMaxWidth(),
) {
Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary
), modifier = Modifier.align(Alignment.CenterHorizontally), onClick = { ), modifier = Modifier, onClick = {
pickAudioLauncher.launch("audio/*") pickAudioLauncher.launch("audio/*")
}) { }) {
Text("add track") 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) NotaList(notas)
} }
} }
@Composable @Composable
fun NotaList(notas: List<NotaDescriptor>, modifier: Modifier = Modifier) { fun NotaList(notas: List<NotaDescriptor>, modifier: Modifier = Modifier) {
val context = LocalContext.current
LazyColumn( LazyColumn(
modifier = modifier, modifier = modifier,
) { ) {
items(notas) { nota -> items(notas) { nota ->
Column(modifier = Modifier Column(modifier = Modifier
.fillParentMaxWidth() .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(4.dp)
.padding(start = 16.dp)) { .padding(start = 16.dp)) {
Text( Text(
@ -121,7 +159,6 @@ fun NotaList(notas: List<NotaDescriptor>, modifier: Modifier = Modifier) {
nota.artist, fontSize = 12.sp nota.artist, fontSize = 12.sp
) )
} }
Log.d("nya", nota.toString())
} }
} }
} }

View file

@ -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)
}
}

View file

@ -8,11 +8,14 @@ import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService import androidx.media3.session.MediaSessionService
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import kotlinx.serialization.json.Json
import java.util.concurrent.ConcurrentLinkedDeque
class PlayerService : MediaSessionService() { class PlayerService : MediaSessionService() {
private var mediaSession: MediaSession? = null private lateinit var mediaSession: MediaSession
var player: ExoPlayer? = null lateinit var player: ExoPlayer
private var virtualQueue = ConcurrentLinkedDeque<Nota>()
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -20,26 +23,35 @@ class PlayerService : MediaSessionService() {
player = this player = this
mediaSession = MediaSession.Builder(this@PlayerService, this).setCallback(MediaSessionCallback()).build() mediaSession = MediaSession.Builder(this@PlayerService, this).setCallback(MediaSessionCallback()).build()
} }
Log.d("meow", "memememe")
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("nya", "start!!!")
intent?.run { intent?.run {
if (getStringExtra("check") != "empty") return@run
handleCommand(getStringExtra("type")!!, this)
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
private fun start() { private fun handleCommand(type: String, intent: Intent) {
when (type) {
"nota" -> {
virtualQueue.add(Nota(Json.decodeFromString<NotaDescriptor>(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() { override fun onDestroy() {
player?.release() player.release()
mediaSession?.release() mediaSession.release()
player = null
mediaSession = null
Log.d("meow", "owowowow")
super.onDestroy() super.onDestroy()
} }

View file

@ -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)
}
}

View file

@ -21,3 +21,4 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
org.gradle.configuration-cache=true

View file

@ -1,28 +1,19 @@
[versions] [versions]
agp = "8.6.0" agp = "8.6.1"
core = "1.6.1" kotlin = "2.0.0"
kotlin = "1.9.0"
coreKtx = "1.13.1" coreKtx = "1.13.1"
junit = "4.13.2" kotlinxSerializationJson = "1.7.3"
junitVersion = "1.2.1" lifecycleRuntimeKtx = "2.8.6"
espressoCore = "3.6.1"
kotlinxSerializationJson = "1.7.1"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.9.2" activityCompose = "1.9.2"
composeBom = "2024.04.01" composeBom = "2024.09.02"
media3Exoplayer = "1.4.1" media3Exoplayer = "1.4.1"
junitJupiter = "5.8.1"
[libraries] [libraries]
androidx-core = { module = "androidx.test:core", version.ref = "core" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } 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-common = { module = "androidx.media3:media3-common", version.ref = "media3Exoplayer" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", 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-session = { module = "androidx.media3:media3-session", version.ref = "media3Exoplayer" }
androidx-media3-ui = { module = "androidx.media3:media3-ui", 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-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-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } 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 = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } 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-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" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } 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] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }