Skip to content

Commit

Permalink
Merge pull request #5 from pansong291/dev/fix_20241019
Browse files Browse the repository at this point in the history
增加倍速调整和点击模式功能
  • Loading branch information
pansong291 authored Oct 20, 2024
2 parents 49404df + ac79837 commit 26c173a
Show file tree
Hide file tree
Showing 21 changed files with 463 additions and 35 deletions.
6 changes: 4 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId = "pansong291.piano.wizard"
minSdk = 24
targetSdk = 34
versionCode = 20241018
versionName = "1.1.0-beta"
versionCode = 20241020
versionName = "1.2.0-beta"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -56,6 +56,8 @@ dependencies {
implementation(libs.google.gson)
implementation(libs.simplecityapps.recyclerview.fastscroll)
implementation(libs.googlecode.juniversalchardet)
implementation(libs.xw.repo.bubbleseekbar)
implementation(libs.androidx.gridlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
4 changes: 3 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@
-keep class com.hjq.window.** {*;}
# simplecityapps.recyclerview.fastscroll
-keep class com.simplecityapps.** {*;}
# 避免 Gson 反序列化失败
# 避免 Gson 反序列化失败
-keep class pansong291.piano.wizard.entity.** {*;}
# com.xw.repo.bubbleseekbar
-keep class com.xw.repo.** {*;}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ object StringConst {
*/
const val SP_DATA_KEY_SKY_STUDIO_SHEET_LAST_FOLDER = "sky_studio_sheet_last_folder"

/**
* 演奏设置
*/
const val SP_DATA_KEY_MUSIC_PLAYING_SETTINGS = "music_playing_settings"

/**
* SkyStudio 乐谱的文件后缀
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import kotlinx.coroutines.launch
import pansong291.piano.wizard.entity.ClickAction
import pansong291.piano.wizard.entity.KeyLayout
import pansong291.piano.wizard.entity.MusicNotation
import pansong291.piano.wizard.entity.MusicPlayingSettings
import pansong291.piano.wizard.entity.TapMode
import pansong291.piano.wizard.exceptions.MissingKeyException
import pansong291.piano.wizard.services.ClickAccessibilityService
import pansong291.piano.wizard.utils.MusicUtil
Expand All @@ -30,11 +32,17 @@ object MusicPlayer {
scope: CoroutineScope,
mn: MusicNotation,
kl: KeyLayout,
mps: MusicPlayingSettings,
offset: Int,
ignoreMissingKey: Boolean = false
) {
if (mps.tempoRate <= 0) throw IllegalArgumentException("tempoRate must be greater than 0")
if (mps.tapMode == TapMode.TapAndHold && mps.earlyRelease <= 0)
throw IllegalArgumentException("earlyRelease must be greater than 0")
if (mps.tapMode == TapMode.RepeatedlyTap && mps.tapInterval <= 0)
throw IllegalArgumentException("tapInterval must be greater than 0")
val keyMap = mutableMapOf<Int, Point>()
val baseTime = 60_000f / mn.bpm
val baseTime = 60_000f / mn.bpm / mps.tempoRate

// 构建十二平均律到按键点位的映射关系
kl.points.forEachIndexed { index, point ->
Expand Down Expand Up @@ -68,7 +76,22 @@ object MusicPlayer {
Thread.sleep(200)
}
val time = System.currentTimeMillis()
ClickAccessibilityService.click(it.points, maxOf(it.delay - 100L, 1L))
val holdTime = when (mps.tapMode) {
TapMode.TapAndHold -> maxOf(it.delay.toLong() - mps.earlyRelease, 1L)
TapMode.RepeatedlyTap -> maxOf(it.delay.toLong(), 1L)
else -> 1L
}
if (mps.tapMode == TapMode.RepeatedlyTap) {
val interval = mps.tapInterval.toLong()
var start = 0L
while (start < holdTime) {
if (start > 0) Thread.sleep(interval)
ClickAccessibilityService.click(it.points, 1L)
start += interval
}
} else {
ClickAccessibilityService.click(it.points, holdTime)
}
val rest = it.delay + time - System.currentTimeMillis()
if (rest > 0) Thread.sleep(rest)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MusicFileChooseDialog(context: Context) : BaseDialog(context) {
set(value) {
adapter.onFileChose = value
}
var scrollTo: ((DialogFileChooseContent.FileInfo) -> Boolean)? = null
var scrollTo: ((String, DialogFileChooseContent.FileInfo) -> Boolean)? = null

init {
setIcon(R.drawable.outline_music_file_32)
Expand All @@ -45,13 +45,18 @@ class MusicFileChooseDialog(context: Context) : BaseDialog(context) {
}
}

fun setHighlight(path: String) {
adapter.highlight = path
}

override fun show() {
adapter.reload()
scrollTo?.also {
val position = adapter.findItemPosition(it)
adapter.highlight = adapter.getItem(position)?.let { adapter.basePath to it.name }
val position = adapter.findItemPosition { info ->
it(adapter.basePath, info)
}
if (position >= 0) recyclerView.scrollToPosition(position)
} ?: run { adapter.highlight = null }
}
super.show()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package pansong291.piano.wizard.dialog

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RadioGroup
import android.widget.ScrollView
import com.xw.repo.BubbleSeekBar
import pansong291.piano.wizard.R
import pansong291.piano.wizard.dialog.actions.DialogConfirmActions
import pansong291.piano.wizard.dialog.base.BaseDialog
import pansong291.piano.wizard.entity.MusicPlayingSettings
import pansong291.piano.wizard.entity.TapMode
import pansong291.piano.wizard.utils.ViewUtil

class MusicPlayingSettingsDialog(context: Context) : BaseDialog(context) {
private val bsbTempoRate: BubbleSeekBar
private val rgTapMode: RadioGroup
private val bsbEarlyRelease: BubbleSeekBar
private val bsbTapInterval: BubbleSeekBar
var onOk: (() -> Unit)? = null

init {
setIcon(R.drawable.outline_settings_applications_32)
setTitle(R.string.playing_settings)
DialogConfirmActions.loadIn(this) { ok, cancel ->
ok.setOnClickListener { onOk?.invoke() }
}
val scrollView = ScrollView(context)
scrollView.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val horizontalPadding = ViewUtil.dpToPx(context, 16f).toInt()
scrollView.setPadding(horizontalPadding, horizontalPadding, horizontalPadding, 0)
findContentWrapper().addView(scrollView)
val root = LayoutInflater.from(context)
.inflate(R.layout.dialog_content_music_playing_settings, scrollView)
bsbTempoRate = root.findViewById(R.id.bsb_tempo_rate)
rgTapMode = root.findViewById(R.id.rg_tap_mode)
bsbEarlyRelease = root.findViewById(R.id.bsb_early_release)
bsbTapInterval = root.findViewById(R.id.bsb_tap_interval)

// FIXME 目前存在问题 https://github.com/woxingxiao/BubbleSeekBar/issues/214
// 故未启用进度气泡,待解决后再调整
/* scrollView.setOnScrollChangeListener { _, _, _, _, _ ->
bsbTempoRate.correctOffsetWhenContainerOnScrolling()
bsbEarlyRelease.correctOffsetWhenContainerOnScrolling()
bsbTapInterval.correctOffsetWhenContainerOnScrolling()
} */
rgTapMode.setOnCheckedChangeListener { _, id ->
setBubbleSeekBarEnabled(bsbEarlyRelease, id == android.R.id.button2)
setBubbleSeekBarEnabled(bsbTapInterval, id == android.R.id.button3)
}
}

fun setSettings(settings: MusicPlayingSettings) {
bsbTempoRate.setProgress(settings.tempoRate)
rgTapMode.check(
when (settings.tapMode) {
TapMode.Tap -> android.R.id.button1
TapMode.TapAndHold -> android.R.id.button2
TapMode.RepeatedlyTap -> android.R.id.button3
}
)
setBubbleSeekBarEnabled(bsbEarlyRelease, settings.tapMode == TapMode.TapAndHold)
setBubbleSeekBarEnabled(bsbTapInterval, settings.tapMode == TapMode.RepeatedlyTap)
bsbEarlyRelease.setProgress(settings.earlyRelease.toFloat())
bsbTapInterval.setProgress(settings.tapInterval.toFloat())
}

fun getSettings(): MusicPlayingSettings {
return MusicPlayingSettings().apply {
tempoRate = bsbTempoRate.progressFloat
tapMode = when (rgTapMode.checkedRadioButtonId) {
android.R.id.button2 -> TapMode.TapAndHold
android.R.id.button3 -> TapMode.RepeatedlyTap
else -> TapMode.Tap
}
earlyRelease = bsbEarlyRelease.progress
tapInterval = bsbTapInterval.progress
}
}

private fun setBubbleSeekBarEnabled(bsb: BubbleSeekBar, enabled: Boolean) {
bsb.isEnabled = enabled
bsb.alpha = if (enabled) 1f else .2f
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class SkyStudioSheetChooseDialog(context: Context) : BaseDialog(context) {
sharedPreferences.getString(StringConst.SP_DATA_KEY_SKY_STUDIO_SHEET_LAST_FOLDER, null)
?.let { adapter.basePath = it }
adapter.fileFilter = FileFilter {
it.isDirectory || it.name.endsWith(StringConst.SKY_STUDIO_SHEET_FILE_EXT)
it.isDirectory || (it.name.endsWith(StringConst.SKY_STUDIO_SHEET_FILE_EXT) &&
!it.name.endsWith(StringConst.MUSIC_NOTATION_FILE_EXT))
}
adapter.onPathChanged = { path ->
sharedPreferences.edit()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import pansong291.piano.wizard.R
import pansong291.piano.wizard.consts.ColorConst
import pansong291.piano.wizard.dialog.base.IDialog
import pansong291.piano.wizard.utils.FileUtil
import java.io.File
import java.io.FileFilter

Expand Down Expand Up @@ -54,7 +55,7 @@ object DialogFileChooseContent {
private val context: Context
) : RecyclerView.Adapter<FileViewHolder>() {
private lateinit var fileList: List<FileInfo>
var highlight: Pair<String, String>? = null
var highlight: String? = null
var basePath: String = Environment.getExternalStorageDirectory().path
var fileFilter: FileFilter = FileFilter { true }
var onFileChose: ((path: String, file: String) -> Unit)? = null
Expand Down Expand Up @@ -123,8 +124,7 @@ object DialogFileChooseContent {
override fun onBindViewHolder(holder: FileViewHolder, position: Int) {
val item = fileList[position]
holder.textView.setTextColor(
if (highlight?.let { it.first == basePath && it.second == item.name } == true)
ColorConst.GREEN_600
if (highlight == FileUtil.pathJoin(basePath, item.name)) ColorConst.GREEN_600
else Color.BLACK
)
holder.textView.text = item.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class MusicNotation {
*/
var name: String = ""

/**
* 乐谱文件路径
*/
var filepath: String = ""

/**
* 基准音调
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package pansong291.piano.wizard.entity

class MusicPlayingSettings {
/**
* 变速
*/
var tempoRate: Float = 1f

/**
* 点击模式
*/
var tapMode: TapMode = TapMode.Tap

/**
* 提前释放
* when: [TapMode.TapAndHold]
*/
var earlyRelease: Int = 100

/**
* 点击间隔
* when: [TapMode.RepeatedlyTap]
*/
var tapInterval: Int = 100
}

enum class TapMode {
/**
* 点触
*/
Tap,

/**
* 按住
*/
TapAndHold,

/**
* 连点
*/
RepeatedlyTap
}
Loading

0 comments on commit 26c173a

Please sign in to comment.