diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt index ee87349..d40829a 100644 --- a/app/src/main/java/com/lukas/music/song/Song.kt +++ b/app/src/main/java/com/lukas/music/song/Song.kt @@ -2,8 +2,9 @@ import android.os.Handler import android.os.Looper -import android.widget.RadioButton +import android.view.View import android.widget.TextView +import androidx.core.view.doOnDetach import com.lukas.music.instruments.Instrument import com.lukas.music.song.chords.Chord import com.lukas.music.song.chords.ChordProgression @@ -16,21 +17,23 @@ ) { private var beat = beats - 1 private lateinit var chord: Chord - val stepButtons = mutableListOf() lateinit var chordDisplay: TextView + private val beatCallback = mutableListOf<(Int, Int) -> Unit>() fun step() { if (chordProgression.phrases.isEmpty()) { return } Handler(Looper.getMainLooper()).post { - stepButtons[beat].isChecked = false + val before = beat beat++ if (beat >= beats) { beat = 0 chord = chordProgression.step() } - stepButtons[beat].isChecked = true + for (callback in beatCallback) { + callback(before, beat) + } // this should not be executed here, but otherwise timing problems show up... val chordNotes = chord.getNotes(root) for (voice in Instrument.voice) { @@ -46,5 +49,12 @@ ChordProgression(), 4 ) + + fun View.setOnBeatCallback(callback: (Int, Int) -> Unit) { + currentSong.beatCallback += callback + doOnDetach { + currentSong.beatCallback.remove(callback) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt index ee87349..d40829a 100644 --- a/app/src/main/java/com/lukas/music/song/Song.kt +++ b/app/src/main/java/com/lukas/music/song/Song.kt @@ -2,8 +2,9 @@ import android.os.Handler import android.os.Looper -import android.widget.RadioButton +import android.view.View import android.widget.TextView +import androidx.core.view.doOnDetach import com.lukas.music.instruments.Instrument import com.lukas.music.song.chords.Chord import com.lukas.music.song.chords.ChordProgression @@ -16,21 +17,23 @@ ) { private var beat = beats - 1 private lateinit var chord: Chord - val stepButtons = mutableListOf() lateinit var chordDisplay: TextView + private val beatCallback = mutableListOf<(Int, Int) -> Unit>() fun step() { if (chordProgression.phrases.isEmpty()) { return } Handler(Looper.getMainLooper()).post { - stepButtons[beat].isChecked = false + val before = beat beat++ if (beat >= beats) { beat = 0 chord = chordProgression.step() } - stepButtons[beat].isChecked = true + for (callback in beatCallback) { + callback(before, beat) + } // this should not be executed here, but otherwise timing problems show up... val chordNotes = chord.getNotes(root) for (voice in Instrument.voice) { @@ -46,5 +49,12 @@ ChordProgression(), 4 ) + + fun View.setOnBeatCallback(callback: (Int, Int) -> Unit) { + currentSong.beatCallback += callback + doOnDetach { + currentSong.beatCallback.remove(callback) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt index e72a20d..48f9bcc 100644 --- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt +++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt @@ -12,9 +12,11 @@ import com.lukas.music.databinding.FragmentPlayBinding import com.lukas.music.instruments.Rhythm import com.lukas.music.song.Song +import com.lukas.music.song.Song.Companion.setOnBeatCallback class PlayFragment : Fragment() { lateinit var binding: FragmentPlayBinding + val beatIndicators = mutableListOf() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -61,10 +63,14 @@ if (i == 0) { child.isChecked = true } - Song.currentSong.stepButtons += child + beatIndicators += child binding.beatIndicator.addView(child) } Song.currentSong.chordDisplay = binding.currentChord + binding.root.setOnBeatCallback { before, now -> + beatIndicators[before].isChecked = false + beatIndicators[now].isChecked = true + } return binding.root }