Rename application identifier to space.rcmd.android.sizzle

Global rename of the app/package identifier from
com.reactorcoremeltdown.sizzletracker to space.rcmd.android.sizzle:

- build.gradle.kts: applicationId + namespace.
- Move the Kotlin source tree (main + test) and rewrite every package/import.
- native_audio.cpp: JNI symbol names (Java_space_rcmd_android_sizzle_...) so the
  Oboe callback still links against the relocated NativeAudioBridge.
- docs: package/file-map header.

The desktop-project GitHub URLs (github.com/reactorcoremeltdown/sizzletracker)
and the Reactorcoremeltdown copyright/SPDX author identity are intentionally left
unchanged. Note: the new applicationId installs as a separate package (existing
installs won't upgrade in place).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Reactorcoremeltdown
2026-07-17 18:59:51 +02:00
co-authored by Claude Opus 4.8
parent a5fdc7b6c4
commit 4bd8aac4d5
61 changed files with 289 additions and 289 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ plugins {
}
android {
namespace = "com.reactorcoremeltdown.sizzletracker"
namespace = "space.rcmd.android.sizzle"
compileSdk = 34
// Native (Oboe) low-latency output backend; see src/main/cpp.
@@ -17,7 +17,7 @@ android {
ndkVersion = "27.2.12479018"
defaultConfig {
applicationId = "com.reactorcoremeltdown.sizzletracker"
applicationId = "space.rcmd.android.sizzle"
// minSdk 26 (Android 8.0) is the floor for the native MIDI API
// (android.media.midi) and AAudio low-latency audio we rely on.
minSdk = 26
+2 -2
View File
@@ -214,7 +214,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_reactorcoremeltdown_sizzletracker_audio_NativeAudioBridge_nativeStart(
Java_space_rcmd_android_sizzle_audio_NativeAudioBridge_nativeStart(
JNIEnv *env, jobject /*thiz*/, jobject callback, jint sampleRate, jint framesPerCallback) {
g_callback = env->NewGlobalRef(callback);
jclass cls = env->GetObjectClass(callback);
@@ -241,7 +241,7 @@ Java_com_reactorcoremeltdown_sizzletracker_audio_NativeAudioBridge_nativeStart(
}
extern "C" JNIEXPORT void JNICALL
Java_com_reactorcoremeltdown_sizzletracker_audio_NativeAudioBridge_nativeStop(
Java_space_rcmd_android_sizzle_audio_NativeAudioBridge_nativeStop(
JNIEnv *env, jobject /*thiz*/) {
g_wantRunning = false; // stop the disconnect-recovery from reopening
if (g_stream) {
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker
package space.rcmd.android.sizzle
import android.Manifest
import android.content.pm.PackageManager
@@ -16,13 +16,13 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.reactorcoremeltdown.sizzletracker.input.GamepadInput
import com.reactorcoremeltdown.sizzletracker.input.KeyboardInput
import com.reactorcoremeltdown.sizzletracker.input.MidiInput
import com.reactorcoremeltdown.sizzletracker.playback.PlaybackService
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.SizzleApp as SizzleAppUi
import com.reactorcoremeltdown.sizzletracker.ui.theme.SizzleTheme
import space.rcmd.android.sizzle.input.GamepadInput
import space.rcmd.android.sizzle.input.KeyboardInput
import space.rcmd.android.sizzle.input.MidiInput
import space.rcmd.android.sizzle.playback.PlaybackService
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.SizzleApp as SizzleAppUi
import space.rcmd.android.sizzle.ui.theme.SizzleTheme
/**
* The single Activity. Its jobs are narrow and clear:
@@ -1,21 +1,21 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker
package space.rcmd.android.sizzle
import android.app.Application
import com.reactorcoremeltdown.sizzletracker.audio.AudioEngine
import com.reactorcoremeltdown.sizzletracker.input.BindingStore
import com.reactorcoremeltdown.sizzletracker.input.GamepadInput
import com.reactorcoremeltdown.sizzletracker.input.InputRouter
import com.reactorcoremeltdown.sizzletracker.input.KeyboardInput
import com.reactorcoremeltdown.sizzletracker.input.MidiInput
import com.reactorcoremeltdown.sizzletracker.io.PresetLibrary
import com.reactorcoremeltdown.sizzletracker.io.ProjectStore
import com.reactorcoremeltdown.sizzletracker.io.SettingsStore
import com.reactorcoremeltdown.sizzletracker.io.SongLibrary
import com.reactorcoremeltdown.sizzletracker.io.ThemeLibrary
import com.reactorcoremeltdown.sizzletracker.model.Project
import space.rcmd.android.sizzle.audio.AudioEngine
import space.rcmd.android.sizzle.input.BindingStore
import space.rcmd.android.sizzle.input.GamepadInput
import space.rcmd.android.sizzle.input.InputRouter
import space.rcmd.android.sizzle.input.KeyboardInput
import space.rcmd.android.sizzle.input.MidiInput
import space.rcmd.android.sizzle.io.PresetLibrary
import space.rcmd.android.sizzle.io.ProjectStore
import space.rcmd.android.sizzle.io.SettingsStore
import space.rcmd.android.sizzle.io.SongLibrary
import space.rcmd.android.sizzle.io.ThemeLibrary
import space.rcmd.android.sizzle.model.Project
import java.io.File
import kotlinx.coroutines.runBlocking
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import com.reactorcoremeltdown.sizzletracker.model.AmbiencePresets
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import space.rcmd.android.sizzle.model.AmbiencePresets
import space.rcmd.android.sizzle.model.ToolboxSlot
import kotlin.math.abs
import kotlin.math.exp
import kotlin.math.floor
@@ -1,18 +1,18 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import android.media.AudioAttributes
import android.media.AudioFormat
import android.media.AudioTrack
import com.reactorcoremeltdown.sizzletracker.model.Arrangement
import com.reactorcoremeltdown.sizzletracker.model.Pattern
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.SamplerPads
import com.reactorcoremeltdown.sizzletracker.model.TimeDivision
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import space.rcmd.android.sizzle.model.Arrangement
import space.rcmd.android.sizzle.model.Pattern
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.SamplerPads
import space.rcmd.android.sizzle.model.TimeDivision
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.model.ToolboxType
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlin.concurrent.thread
@@ -682,7 +682,7 @@ class AudioEngine(
* its own MIDI effects (Transposer shifts pitch; an Arpeggiator captures the
* note and hands retriggering to [advanceArps]).
*/
private fun triggerCell(proj: Project, lane: Int, cell: com.reactorcoremeltdown.sizzletracker.model.Cell) {
private fun triggerCell(proj: Project, lane: Int, cell: space.rcmd.android.sizzle.model.Cell) {
for (bus in 0 until Pattern.TRACK_COUNT) {
if (proj.mixer.channels[bus].midiChannel != cell.channel) continue
val arp = arps[lane * Pattern.TRACK_COUNT + bus]
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import com.reactorcoremeltdown.sizzletracker.model.DelayDivisions
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import space.rcmd.android.sizzle.model.DelayDivisions
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.model.ToolboxType
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.cos
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import java.io.File
import java.io.RandomAccessFile
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
/**
* Bridges the native Oboe (AAudio) output backend to the Kotlin [AudioEngine].
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import android.annotation.SuppressLint
import android.media.AudioFormat
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import java.nio.ByteBuffer
import java.nio.ByteOrder
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import kotlin.math.exp
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
import java.nio.ByteBuffer
import java.nio.ByteOrder
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
/**
* One playing note (a "voice"). This is a deliberately simple NES/Famicom-style
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.audio
package space.rcmd.android.sizzle.audio
/**
* A small, immutable snapshot of "where playback is" that the audio thread
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
import android.content.Context
import androidx.datastore.core.DataStore
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
import android.view.InputDevice
import android.view.KeyEvent
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
/**
* The heart of the "four equal input methods" requirement. Touch, physical
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
/**
* The single source of truth mapping a stable action-id string to the neutral
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
import android.view.KeyEvent
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import space.rcmd.android.sizzle.model.Pitch
/**
* Translates physical (USB / Bluetooth) keyboard events into [InputAction]s.
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.input
package space.rcmd.android.sizzle.input
import android.content.Context
import android.media.midi.MidiDeviceInfo
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.model.ToolboxType
/**
* Reads and writes a single instrument/effect preset as plain, human-readable
@@ -1,14 +1,14 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.audio.SampleStore
import com.reactorcoremeltdown.sizzletracker.model.AmbiencePresets
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.SamplerPads
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import space.rcmd.android.sizzle.audio.SampleStore
import space.rcmd.android.sizzle.model.AmbiencePresets
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.SamplerPads
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.model.ToolboxType
import java.io.File
import java.io.InputStream
import java.util.zip.ZipEntry
@@ -1,15 +1,15 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.model.Cell
import com.reactorcoremeltdown.sizzletracker.model.Mixer
import com.reactorcoremeltdown.sizzletracker.model.Pattern
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.Scale
import com.reactorcoremeltdown.sizzletracker.model.TimeSignature
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import space.rcmd.android.sizzle.model.Cell
import space.rcmd.android.sizzle.model.Mixer
import space.rcmd.android.sizzle.model.Pattern
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.Scale
import space.rcmd.android.sizzle.model.TimeSignature
import space.rcmd.android.sizzle.model.ToolboxType
/**
* Saves and loads a whole [Project] to/from the `.sng` text format.
@@ -87,7 +87,7 @@ object ProjectIo {
// Reset everything to a clean slate first.
project.patterns.clear()
for (lane in project.arrangement.slots.indices)
project.arrangement.slots[lane].fill(com.reactorcoremeltdown.sizzletracker.model.Arrangement.EMPTY)
project.arrangement.slots[lane].fill(space.rcmd.android.sizzle.model.Arrangement.EMPTY)
project.arrangement.laneMuted.fill(false)
project.toolbox.forEach { it.clearSlot() }
project.mixer.channels.forEach { ch ->
@@ -119,7 +119,7 @@ object ProjectIo {
// are restored from the explicit lane,beat,pid lines regardless).
project.arrangement.lengthBars =
attrs["bars"]?.toIntOrNull()
?: com.reactorcoremeltdown.sizzletracker.model.Arrangement.MAX_BARS
?: space.rcmd.android.sizzle.model.Arrangement.MAX_BARS
project.arrangement.loopEnabled = attrs["loop"] == "1"
attrs["mutes"]?.let { m ->
val lanes = project.arrangement.laneMuted
@@ -142,7 +142,7 @@ object ProjectIo {
}
// Guarantee one block per lane (lane i is tied to block i), padding any
// that the file did not define so the arrangement/editor always resolve.
for (id in 0 until com.reactorcoremeltdown.sizzletracker.model.Arrangement.LANE_COUNT) {
for (id in 0 until space.rcmd.android.sizzle.model.Arrangement.LANE_COUNT) {
if (project.patterns.none { it.id == id }) project.patterns.add(Pattern(id, name = "BLK${id + 1}"))
}
project.patterns.sortBy { it.id }
@@ -193,7 +193,7 @@ object ProjectIo {
p.arrangement.set(lane, beat, pid)
}
private fun applyRegion(region: com.reactorcoremeltdown.sizzletracker.model.LoopRegion, a: Map<String, String>) {
private fun applyRegion(region: space.rcmd.android.sizzle.model.LoopRegion, a: Map<String, String>) {
region.enabled = a["en"] == "1"
region.start = a["s"]?.toIntOrNull() ?: 0
region.end = a["e"]?.toIntOrNull() ?: 0
@@ -1,9 +1,9 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.model.Project
import space.rcmd.android.sizzle.model.Project
import java.io.File
/**
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import android.content.Context
import androidx.datastore.core.DataStore
@@ -32,7 +32,7 @@ data class AppSettings(
* Persists app-level UI/audio settings (the colour theme and the low-latency
* engine toggle). Song/mixer/toolbox parameters live in the project and are
* handled by [ProjectStore]; input bindings by
* [com.reactorcoremeltdown.sizzletracker.input.BindingStore].
* [space.rcmd.android.sizzle.input.BindingStore].
*
* Audio output/input *device* selection is intentionally not persisted: Android
* device ids are session-scoped and don't identify the same hardware next launch.
@@ -1,14 +1,14 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.model.Arrangement
import com.reactorcoremeltdown.sizzletracker.model.Cell
import com.reactorcoremeltdown.sizzletracker.model.Pattern
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.TimeSignature
import space.rcmd.android.sizzle.model.Arrangement
import space.rcmd.android.sizzle.model.Cell
import space.rcmd.android.sizzle.model.Pattern
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.TimeSignature
/**
* Reads and writes the reference desktop **sizzletracker `.sng`** format
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import java.io.File
@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import androidx.compose.ui.graphics.Color
import com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette
import space.rcmd.android.sizzle.ui.theme.RetroPalette
/**
* Reads and writes a colour [RetroPalette] as plain, human-editable text — the same
@@ -1,9 +1,9 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette
import space.rcmd.android.sizzle.ui.theme.RetroPalette
import java.io.File
/**
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* Factory data for the [ToolboxType.AMBIENCE] reverb, ported from OTODESK's
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* The lower-half piano-roll arrangement. It has [LANE_COUNT] lanes stacked
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* The mixer has exactly [CHANNEL_COUNT] channels, one per tracker track. Each
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* Musical primitives shared across the whole app: pitches, scales and time
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* One cell in the tracker grid: a single note event on a single line of a single
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* The whole song in memory. This single object is what gets saved to / loaded
@@ -9,7 +9,7 @@ package com.reactorcoremeltdown.sizzletracker.model
* Keeping one root object makes serialization and undo/redo straightforward.
*
* Persistence is done by our own text serializer (see
* [com.reactorcoremeltdown.sizzletracker.io.ProjectIo]), not kotlinx, so the
* [space.rcmd.android.sizzle.io.ProjectIo]), not kotlinx, so the
* model classes carry no serialization annotations.
*/
class Project {
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.model
package space.rcmd.android.sizzle.model
/**
* The third tab is a toolbox of 16 slots. Every slot can hold one instrument OR
@@ -273,7 +273,7 @@ enum class TimeDivision(val label: String, val beatFraction: Double) {
* sample file path live in the same map under keys the engine knows about
* (e.g. "samplePath", "target").
*
* (Serialized via [com.reactorcoremeltdown.sizzletracker.io.PresetIo], not
* (Serialized via [space.rcmd.android.sizzle.io.PresetIo], not
* kotlinx, so no @Serializable annotation is needed here.)
*/
class ToolboxSlot(
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.playback
package space.rcmd.android.sizzle.playback
import android.os.Looper
import androidx.media3.common.MediaItem
@@ -11,7 +11,7 @@ import androidx.media3.common.SimpleBasePlayer
import androidx.media3.common.util.UnstableApi
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import com.reactorcoremeltdown.sizzletracker.audio.AudioEngine
import space.rcmd.android.sizzle.audio.AudioEngine
/**
* Adapts our custom [AudioEngine] to the media3 [Player] interface via
@@ -1,14 +1,14 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.playback
package space.rcmd.android.sizzle.playback
import android.content.Context
import android.content.Intent
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
import com.reactorcoremeltdown.sizzletracker.SizzleApp
import space.rcmd.android.sizzle.SizzleApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui
package space.rcmd.android.sizzle.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
@@ -29,11 +29,11 @@ import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import com.reactorcoremeltdown.sizzletracker.ui.mixer.MixerScreen
import com.reactorcoremeltdown.sizzletracker.ui.settings.SettingsScreen
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import com.reactorcoremeltdown.sizzletracker.ui.toolbox.ToolboxScreen
import com.reactorcoremeltdown.sizzletracker.ui.tracker.TrackerScreen
import space.rcmd.android.sizzle.ui.mixer.MixerScreen
import space.rcmd.android.sizzle.ui.settings.SettingsScreen
import space.rcmd.android.sizzle.ui.theme.LocalRetro
import space.rcmd.android.sizzle.ui.toolbox.ToolboxScreen
import space.rcmd.android.sizzle.ui.tracker.TrackerScreen
/**
* The top-level layout: the active tab's screen fills the space above a standard
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui
package space.rcmd.android.sizzle.ui
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@@ -10,15 +10,15 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.reactorcoremeltdown.sizzletracker.audio.AudioEngine
import com.reactorcoremeltdown.sizzletracker.input.InputAction
import com.reactorcoremeltdown.sizzletracker.input.InputRouter
import com.reactorcoremeltdown.sizzletracker.model.Cell
import com.reactorcoremeltdown.sizzletracker.model.CellColumn
import com.reactorcoremeltdown.sizzletracker.model.Pattern
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.TimeSignature
import space.rcmd.android.sizzle.audio.AudioEngine
import space.rcmd.android.sizzle.input.InputAction
import space.rcmd.android.sizzle.input.InputRouter
import space.rcmd.android.sizzle.model.Cell
import space.rcmd.android.sizzle.model.CellColumn
import space.rcmd.android.sizzle.model.Pattern
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.TimeSignature
import kotlinx.coroutines.launch
/**
@@ -36,14 +36,14 @@ class AppViewModel(
val project: Project,
private val engine: AudioEngine,
private val router: InputRouter,
private val gamepadInput: com.reactorcoremeltdown.sizzletracker.input.GamepadInput,
private val midiInput: com.reactorcoremeltdown.sizzletracker.input.MidiInput,
private val keyboardInput: com.reactorcoremeltdown.sizzletracker.input.KeyboardInput,
private val bindingStore: com.reactorcoremeltdown.sizzletracker.input.BindingStore,
private val presetLibrary: com.reactorcoremeltdown.sizzletracker.io.PresetLibrary,
private val songLibrary: com.reactorcoremeltdown.sizzletracker.io.SongLibrary,
private val settingsStore: com.reactorcoremeltdown.sizzletracker.io.SettingsStore,
private val themeLibrary: com.reactorcoremeltdown.sizzletracker.io.ThemeLibrary,
private val gamepadInput: space.rcmd.android.sizzle.input.GamepadInput,
private val midiInput: space.rcmd.android.sizzle.input.MidiInput,
private val keyboardInput: space.rcmd.android.sizzle.input.KeyboardInput,
private val bindingStore: space.rcmd.android.sizzle.input.BindingStore,
private val presetLibrary: space.rcmd.android.sizzle.io.PresetLibrary,
private val songLibrary: space.rcmd.android.sizzle.io.SongLibrary,
private val settingsStore: space.rcmd.android.sizzle.io.SettingsStore,
private val themeLibrary: space.rcmd.android.sizzle.io.ThemeLibrary,
private val appContext: android.content.Context,
) : ViewModel() {
@@ -52,7 +52,7 @@ class AppViewModel(
var revision by mutableIntStateOf(0); private set // bump to force grid redraw
/** Active colour theme; read by [MainActivity] to drive SizzleTheme. Set via
* [selectPalette] so the choice is persisted. */
var palette by mutableStateOf(com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette.AMBER)
var palette by mutableStateOf(space.rcmd.android.sizzle.ui.theme.RetroPalette.AMBER)
private set
// Tracker cursor position.
@@ -110,7 +110,7 @@ class AppViewModel(
// ----- Binding-learn state (Settings tab) -----
/** The action id currently waiting to be bound, or null. */
var learnTarget by mutableStateOf<String?>(null); private set
private var learnSource: com.reactorcoremeltdown.sizzletracker.input.InputSource? = null
private var learnSource: space.rcmd.android.sizzle.input.InputSource? = null
init {
// Collect neutral input actions from every non-touch device.
@@ -444,7 +444,7 @@ class AppViewModel(
// ------------------------------------------------------- binding learn
/** Arm MIDI-learn / gamepad-rebind: the next matching control is bound to
* [actionId]. [source] restricts which device kind will be captured. */
fun beginLearn(actionId: String, source: com.reactorcoremeltdown.sizzletracker.input.InputSource) {
fun beginLearn(actionId: String, source: space.rcmd.android.sizzle.input.InputSource) {
learnTarget = actionId
learnSource = source
router.learnSource = source
@@ -465,15 +465,15 @@ class AppViewModel(
val target = learnTarget ?: return
if (action.source != learnSource) return
when (action.source) {
com.reactorcoremeltdown.sizzletracker.input.InputSource.MIDI ->
space.rcmd.android.sizzle.input.InputSource.MIDI ->
midiInput.ccBindings[action.code] = target
com.reactorcoremeltdown.sizzletracker.input.InputSource.GAMEPAD -> {
space.rcmd.android.sizzle.input.InputSource.GAMEPAD -> {
gamepadInput.bindings.entries.removeAll { it.value == target }
gamepadInput.bindings[
com.reactorcoremeltdown.sizzletracker.input.GamepadChord(action.modifier, action.code),
space.rcmd.android.sizzle.input.GamepadChord(action.modifier, action.code),
] = target
}
com.reactorcoremeltdown.sizzletracker.input.InputSource.KEYBOARD -> {
space.rcmd.android.sizzle.input.InputSource.KEYBOARD -> {
keyboardInput.bindings.entries.removeAll { it.value == target }
keyboardInput.bindings[action.code] = target
}
@@ -490,20 +490,20 @@ class AppViewModel(
/** Current gamepad chord (modifier + button, or plain button) bound to
* [actionId], or null. */
fun gamepadBindingFor(actionId: String): com.reactorcoremeltdown.sizzletracker.input.GamepadChord? =
fun gamepadBindingFor(actionId: String): space.rcmd.android.sizzle.input.GamepadChord? =
gamepadInput.bindings.entries.firstOrNull { it.value == actionId }?.key
/** Current keyboard key code bound to [actionId], or null. */
fun keyboardBindingFor(actionId: String): Int? =
keyboardInput.bindings.entries.firstOrNull { it.value == actionId }?.key
fun clearBinding(actionId: String, source: com.reactorcoremeltdown.sizzletracker.input.InputSource) {
fun clearBinding(actionId: String, source: space.rcmd.android.sizzle.input.InputSource) {
when (source) {
com.reactorcoremeltdown.sizzletracker.input.InputSource.MIDI ->
space.rcmd.android.sizzle.input.InputSource.MIDI ->
midiInput.ccBindings.entries.removeAll { it.value == actionId }
com.reactorcoremeltdown.sizzletracker.input.InputSource.GAMEPAD ->
space.rcmd.android.sizzle.input.InputSource.GAMEPAD ->
gamepadInput.bindings.entries.removeAll { it.value == actionId }
com.reactorcoremeltdown.sizzletracker.input.InputSource.KEYBOARD ->
space.rcmd.android.sizzle.input.InputSource.KEYBOARD ->
keyboardInput.bindings.entries.removeAll { it.value == actionId }
else -> {}
}
@@ -538,26 +538,26 @@ class AppViewModel(
/** Nudge an A/B loop region's repeat count and apply it to live playback
* immediately (without restarting the transport). */
fun changeRegionRepeats(region: com.reactorcoremeltdown.sizzletracker.model.LoopRegion, delta: Int) {
fun changeRegionRepeats(region: space.rcmd.android.sizzle.model.LoopRegion, delta: Int) {
region.repeats = (region.repeats + delta).coerceAtLeast(1)
engine.refreshLoopPlaylist()
touched()
}
// -------------------------------------------------------------- sampler
private val recorder = com.reactorcoremeltdown.sizzletracker.audio.SampleRecorder()
private val recorder = space.rcmd.android.sizzle.audio.SampleRecorder()
var isRecording by mutableStateOf(false); private set
/** Decode a WAV and assign it to Sampler [slot]'s [pad] (from a file import). */
fun loadSampleInto(
slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot,
slot: space.rcmd.android.sizzle.model.ToolboxSlot,
pad: Int,
id: String,
bytes: ByteArray,
): Boolean {
val sample = com.reactorcoremeltdown.sizzletracker.audio.SampleStore.decodeWav(bytes) ?: return false
com.reactorcoremeltdown.sizzletracker.audio.SampleStore.put(id, sample)
val pads = com.reactorcoremeltdown.sizzletracker.model.SamplerPads
val sample = space.rcmd.android.sizzle.audio.SampleStore.decodeWav(bytes) ?: return false
space.rcmd.android.sizzle.audio.SampleStore.put(id, sample)
val pads = space.rcmd.android.sizzle.model.SamplerPads
slot.set(pads.key(pad), id)
slot.set(pads.sliceStartKey(pad), 0f); slot.set(pads.sliceEndKey(pad), 1f)
touched()
@@ -567,12 +567,12 @@ class AppViewModel(
/** Load an SF2 / XI (or WAV) file into a SoundFont [slot]: parse it, cache the
* extracted sample, and store its id + root note on the slot. */
fun loadSoundFont(
slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot,
slot: space.rcmd.android.sizzle.model.ToolboxSlot,
id: String,
bytes: ByteArray,
): Boolean {
val loaded = com.reactorcoremeltdown.sizzletracker.audio.SoundFontLoader.load(bytes) ?: return false
com.reactorcoremeltdown.sizzletracker.audio.SampleStore.put(id, loaded.sample)
val loaded = space.rcmd.android.sizzle.audio.SoundFontLoader.load(bytes) ?: return false
space.rcmd.android.sizzle.audio.SampleStore.put(id, loaded.sample)
slot.set("sfSample", id)
slot.set("sfRoot", loaded.rootNote.toFloat())
touched()
@@ -585,9 +585,9 @@ class AppViewModel(
* and the markers reset to the full (new) sample. There is no undo — re-import
* or re-record to start over. Returns false if there's nothing to trim.
*/
fun trimSamplerPad(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, pad: Int): Boolean {
val pads = com.reactorcoremeltdown.sizzletracker.model.SamplerPads
val store = com.reactorcoremeltdown.sizzletracker.audio.SampleStore
fun trimSamplerPad(slot: space.rcmd.android.sizzle.model.ToolboxSlot, pad: Int): Boolean {
val pads = space.rcmd.android.sizzle.model.SamplerPads
val store = space.rcmd.android.sizzle.audio.SampleStore
val sample = store.get(slot.string(pads.key(pad))) ?: return false
val len = sample.data.size
if (len <= 1) return false
@@ -598,7 +598,7 @@ class AppViewModel(
if (start == 0 && end == len) return false // slice already spans the whole sample
// A fresh id so other pads sharing the original sample are left untouched.
val id = "trim:" + System.nanoTime()
store.put(id, com.reactorcoremeltdown.sizzletracker.audio.SampleStore.Sample(
store.put(id, space.rcmd.android.sizzle.audio.SampleStore.Sample(
sample.data.copyOfRange(start, end), sample.sampleRate))
slot.set(pads.key(pad), id)
slot.set(pads.sliceStartKey(pad), 0f)
@@ -613,9 +613,9 @@ class AppViewModel(
* the same). No undo. Returns false if the pad is empty, silent, or already
* normalized.
*/
fun normalizeSamplerPad(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, pad: Int): Boolean {
val pads = com.reactorcoremeltdown.sizzletracker.model.SamplerPads
val store = com.reactorcoremeltdown.sizzletracker.audio.SampleStore
fun normalizeSamplerPad(slot: space.rcmd.android.sizzle.model.ToolboxSlot, pad: Int): Boolean {
val pads = space.rcmd.android.sizzle.model.SamplerPads
val store = space.rcmd.android.sizzle.audio.SampleStore
val sample = store.get(slot.string(pads.key(pad))) ?: return false
val data = sample.data
if (data.isEmpty()) return false
@@ -626,15 +626,15 @@ class AppViewModel(
if (gain in 0.999f..1.001f) return false // already at full scale
val out = FloatArray(data.size) { (data[it] * gain).coerceIn(-1f, 1f) }
val id = "norm:" + System.nanoTime() // fresh id so shared samples are untouched
store.put(id, com.reactorcoremeltdown.sizzletracker.audio.SampleStore.Sample(out, sample.sampleRate))
store.put(id, space.rcmd.android.sizzle.audio.SampleStore.Sample(out, sample.sampleRate))
slot.set(pads.key(pad), id)
touched()
return true
}
/** Clear the sample assigned to a Sampler [slot]'s [pad]. */
fun clearSamplerPad(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, pad: Int) {
val pads = com.reactorcoremeltdown.sizzletracker.model.SamplerPads
fun clearSamplerPad(slot: space.rcmd.android.sizzle.model.ToolboxSlot, pad: Int) {
val pads = space.rcmd.android.sizzle.model.SamplerPads
slot.values.remove(pads.key(pad))
slot.values.remove(pads.sliceStartKey(pad))
slot.values.remove(pads.sliceEndKey(pad))
@@ -664,19 +664,19 @@ class AppViewModel(
fun dismissNativeAudioError() { nativeAudioError = null }
/** Choose the colour theme and persist the choice. */
fun selectPalette(p: com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette) {
fun selectPalette(p: space.rcmd.android.sizzle.ui.theme.RetroPalette) {
palette = p
persistSettings()
}
// ------------------------------------------------------------ colour themes
private val stockThemes get() = com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette.ALL
private val stockThemes get() = space.rcmd.android.sizzle.ui.theme.RetroPalette.ALL
/** The two built-in themes are read-only and can never be deleted. */
fun isStockTheme(name: String): Boolean = stockThemes.any { it.name == name }
/** Every selectable theme: the two stock themes followed by user themes. */
fun allThemes(): List<com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette> =
fun allThemes(): List<space.rcmd.android.sizzle.ui.theme.RetroPalette> =
stockThemes + themeLibrary.loadAll()
/** All theme names for the selector dropdown (stock first, then user). */
@@ -705,7 +705,7 @@ class AppViewModel(
if (isStockTheme(name)) return false
val ok = themeLibrary.delete(name)
if (ok) {
if (palette.name == name) selectPalette(com.reactorcoremeltdown.sizzletracker.ui.theme.RetroPalette.AMBER)
if (palette.name == name) selectPalette(space.rcmd.android.sizzle.ui.theme.RetroPalette.AMBER)
touched()
}
return ok
@@ -759,13 +759,13 @@ class AppViewModel(
}
/** Stop recording and assign the captured audio to Sampler [slot]'s [pad]. */
fun stopRecordingInto(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, pad: Int) {
fun stopRecordingInto(slot: space.rcmd.android.sizzle.model.ToolboxSlot, pad: Int) {
val sample = recorder.stop()
isRecording = false
if (sample != null) {
val id = "rec-" + System.currentTimeMillis()
com.reactorcoremeltdown.sizzletracker.audio.SampleStore.put(id, sample)
val pads = com.reactorcoremeltdown.sizzletracker.model.SamplerPads
space.rcmd.android.sizzle.audio.SampleStore.put(id, sample)
val pads = space.rcmd.android.sizzle.model.SamplerPads
slot.set(pads.key(pad), id)
slot.set(pads.sliceStartKey(pad), 0f); slot.set(pads.sliceEndKey(pad), 1f)
touched()
@@ -775,7 +775,7 @@ class AppViewModel(
/** Point an LFO slot at another device's parameter, capturing that param's
* current value as the modulation centre. Pass targetSlotIndex < 0 to clear. */
fun setLfoTarget(
lfoSlot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot,
lfoSlot: space.rcmd.android.sizzle.model.ToolboxSlot,
targetSlotIndex: Int,
key: String,
) {
@@ -791,7 +791,7 @@ class AppViewModel(
}
/** Preview a note of the Sampler slot's loaded sample (one-shot, editor use). */
fun auditionSample(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, midi: Int) {
fun auditionSample(slot: space.rcmd.android.sizzle.model.ToolboxSlot, midi: Int) {
engine.auditionSlotOn(slot.index, midi)
}
@@ -803,18 +803,18 @@ class AppViewModel(
// ------------------------------------------------------------ project I/O
/** Serialize the current song to `.sng` text. */
fun saveProjectText(): String =
com.reactorcoremeltdown.sizzletracker.io.ProjectIo.save(project)
space.rcmd.android.sizzle.io.ProjectIo.save(project)
/** Replace the current song's contents from our full internal text (in place). */
fun loadProjectText(text: String) {
com.reactorcoremeltdown.sizzletracker.io.ProjectIo.loadInto(project, text)
space.rcmd.android.sizzle.io.ProjectIo.loadInto(project, text)
cursorLine = 0; cursorTrack = 0
touched()
}
/** Export to the reference desktop sizzletracker `.sng` format (musical data). */
fun exportSng(): String =
com.reactorcoremeltdown.sizzletracker.io.SngFormat.export(project)
space.rcmd.android.sizzle.io.SngFormat.export(project)
/** Import a reference `.sng` file (in place). Returns false if the text doesn't
* look like a `.sng` (so the caller can surface a popup) rather than silently
@@ -823,7 +823,7 @@ class AppViewModel(
val looksLikeSng = Regex("(?m)^\\s*(version|bpm|sig|block)\\b").containsMatchIn(text)
if (!looksLikeSng) return false
runCatching {
com.reactorcoremeltdown.sizzletracker.io.SngFormat.importInto(project, text)
space.rcmd.android.sizzle.io.SngFormat.importInto(project, text)
}.getOrElse { return false }
cursorLine = 0; cursorTrack = 0
touched()
@@ -854,7 +854,7 @@ class AppViewModel(
*/
fun newProject() {
engine.stop()
loadProjectText(com.reactorcoremeltdown.sizzletracker.io.ProjectIo.save(Project()))
loadProjectText(space.rcmd.android.sizzle.io.ProjectIo.save(Project()))
project.name = "untitled"
engine.rebuildFxChains() // all FX routing was cleared
}
@@ -882,11 +882,11 @@ class AppViewModel(
// ------------------------------------------------------ instrument/effect presets
/** Preset names available for a device type (for the editor's browser dropdown). */
fun presetNames(type: com.reactorcoremeltdown.sizzletracker.model.ToolboxType): List<String> =
fun presetNames(type: space.rcmd.android.sizzle.model.ToolboxType): List<String> =
presetLibrary.list(type)
/** Save [slot] as a named preset in the library. Returns the preset file. */
fun savePreset(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, name: String): java.io.File {
fun savePreset(slot: space.rcmd.android.sizzle.model.ToolboxSlot, name: String): java.io.File {
val file = presetLibrary.save(slot, name)
touched()
return file
@@ -894,7 +894,7 @@ class AppViewModel(
/** Load a named preset for [slot]'s current type into it. The slot is renamed to
* the preset so the toolbox tile and mixer inserts read as the loaded sound. */
fun loadPreset(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, name: String): Boolean {
fun loadPreset(slot: space.rcmd.android.sizzle.model.ToolboxSlot, name: String): Boolean {
val type = slot.type ?: return false
val ok = presetLibrary.load(slot, type, name)
if (ok) { slot.name = name; engine.rebuildFxChains(); touched() }
@@ -902,7 +902,7 @@ class AppViewModel(
}
/** Import a preset from picked bytes: a `.zip` bundle (Sampler) or plain text. */
fun importPreset(slot: com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot, bytes: ByteArray): Boolean {
fun importPreset(slot: space.rcmd.android.sizzle.model.ToolboxSlot, bytes: ByteArray): Boolean {
val isZip = bytes.size >= 2 && bytes[0] == 'P'.code.toByte() && bytes[1] == 'K'.code.toByte()
val ok = if (isZip) presetLibrary.importZip(slot, java.io.ByteArrayInputStream(bytes))
else presetLibrary.importText(slot, String(bytes, Charsets.UTF_8))
@@ -911,11 +911,11 @@ class AppViewModel(
}
/** A shareable file for a stored preset (a zip bundle for the Sampler). */
fun presetShareFile(type: com.reactorcoremeltdown.sizzletracker.model.ToolboxType, name: String): java.io.File? =
fun presetShareFile(type: space.rcmd.android.sizzle.model.ToolboxType, name: String): java.io.File? =
presetLibrary.bundleForShare(type, name)
/** Delete a stored preset (and, for the Sampler, its bundled sample). */
fun deletePreset(type: com.reactorcoremeltdown.sizzletracker.model.ToolboxType, name: String): Boolean {
fun deletePreset(type: space.rcmd.android.sizzle.model.ToolboxType, name: String): Boolean {
val ok = presetLibrary.delete(type, name)
if (ok) touched()
return ok
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui
package space.rcmd.android.sizzle.ui
import android.content.res.Configuration
import androidx.compose.runtime.Composable
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui
package space.rcmd.android.sizzle.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
@@ -26,11 +26,11 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.ui.components.PianoKey
import com.reactorcoremeltdown.sizzletracker.ui.components.PianoOctave
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.ui.components.PianoKey
import space.rcmd.android.sizzle.ui.components.PianoOctave
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.theme.LocalRetro
private const val VEL_STEP = 8
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.components
package space.rcmd.android.sizzle.ui.components
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextMeasurer
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.components
package space.rcmd.android.sizzle.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -23,7 +23,7 @@ import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* Lays out one octave as a real piano keyboard: seven white keys across the bottom
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.components
package space.rcmd.android.sizzle.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -26,7 +26,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* A tiny library of "pixel" UI building blocks. They are intentionally plain —
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.mixer
package space.rcmd.android.sizzle.ui.mixer
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -34,15 +34,15 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.Mixer
import com.reactorcoremeltdown.sizzletracker.model.MixerChannel
import com.reactorcoremeltdown.sizzletracker.model.ToolboxKind
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.isLandscape
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroDropdown
import com.reactorcoremeltdown.sizzletracker.ui.components.SectionLabel
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.Mixer
import space.rcmd.android.sizzle.model.MixerChannel
import space.rcmd.android.sizzle.model.ToolboxKind
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.isLandscape
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.components.SectionLabel
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The second tab: a four-channel mixer, one strip per tracker track. Each strip
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.settings
package space.rcmd.android.sizzle.ui.settings
import android.content.Context
import android.content.Intent
@@ -60,10 +60,10 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import com.reactorcoremeltdown.sizzletracker.input.GamepadChord
import com.reactorcoremeltdown.sizzletracker.input.GamepadInput
import com.reactorcoremeltdown.sizzletracker.input.InputSource
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import space.rcmd.android.sizzle.input.GamepadChord
import space.rcmd.android.sizzle.input.GamepadInput
import space.rcmd.android.sizzle.input.InputSource
import space.rcmd.android.sizzle.ui.AppViewModel
/**
* The fourth tab, built from STANDARD Material 3 components (Cards, Buttons,
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.theme
package space.rcmd.android.sizzle.ui.theme
import android.app.Activity
import androidx.compose.foundation.isSystemInDarkTheme
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
@@ -25,11 +25,11 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.DelayDivisions
import com.reactorcoremeltdown.sizzletracker.model.ParamSpec
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.DelayDivisions
import space.rcmd.android.sizzle.model.ParamSpec
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The Tape Delay's custom editor: four tape heads side by side, each a vertical
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -13,10 +13,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroDropdown
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* A modulation target: a numeric parameter on another device the LFO can drive.
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -13,11 +13,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.ParamSpec
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroDropdown
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.ParamSpec
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.theme.LocalRetro
import kotlin.math.roundToInt
/**
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -37,13 +37,13 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.audio.SampleStore
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.model.SamplerPads
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.audio.SampleStore
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.model.SamplerPads
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.theme.LocalRetro
import kotlin.math.abs
/**
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -38,20 +38,20 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.audio.SampleStore
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.PianoKey
import com.reactorcoremeltdown.sizzletracker.ui.components.PianoOctave
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.audio.SampleStore
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.PianoKey
import space.rcmd.android.sizzle.ui.components.PianoOctave
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The SoundFont device editor: load an `.sf2` / `.xi` (or `.wav`) file from local
* storage, preview its waveform, set output volume, and audition it pitched across
* a two-octave keyboard. The extracted sample plays across the whole keyboard from
* the file's root note (see [com.reactorcoremeltdown.sizzletracker.audio.SoundFontLoader]).
* the file's root note (see [space.rcmd.android.sizzle.audio.SoundFontLoader]).
*/
@Composable
fun SoundFontEditor(vm: AppViewModel, slot: ToolboxSlot) {
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.toolbox
package space.rcmd.android.sizzle.ui.toolbox
import android.content.Intent
import androidx.activity.compose.BackHandler
@@ -54,14 +54,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.FileProvider
import com.reactorcoremeltdown.sizzletracker.model.ParamSpec
import com.reactorcoremeltdown.sizzletracker.model.ToolboxSlot
import com.reactorcoremeltdown.sizzletracker.model.ToolboxType
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.isLandscape
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroDropdown
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.ParamSpec
import space.rcmd.android.sizzle.model.ToolboxSlot
import space.rcmd.android.sizzle.model.ToolboxType
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.isLandscape
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.theme.LocalRetro
import kotlinx.coroutines.launch
/**
@@ -104,7 +104,7 @@ fun ToolboxScreen(vm: AppViewModel) {
ToolboxTileGrid(vm, selected, onTapTile, onDoubleTapTile, onLongPressTile,
Modifier.weight(1f).fillMaxHeight())
Box(Modifier.width(2.dp).fillMaxHeight().background(c.accent))
com.reactorcoremeltdown.sizzletracker.ui.StackedKeyboard(vm, punchIn = false, Modifier.weight(1.3f))
space.rcmd.android.sizzle.ui.StackedKeyboard(vm, punchIn = false, Modifier.weight(1.3f))
}
} else {
// Portrait: a scrolling grid of square tiles above the keyboard (1.7 : 1).
@@ -126,7 +126,7 @@ fun ToolboxScreen(vm: AppViewModel) {
}
}
Box(Modifier.fillMaxWidth().height(2.dp).background(c.accent)) // fixed divider
com.reactorcoremeltdown.sizzletracker.ui.StackedKeyboard(vm, punchIn = false, Modifier.weight(1f))
space.rcmd.android.sizzle.ui.StackedKeyboard(vm, punchIn = false, Modifier.weight(1f))
}
}
@@ -373,7 +373,7 @@ private val AMBIENCE_SECTIONS = listOf(
* the presets saved for this device type, plus Save (to the app's on-disk preset
* library), Import (from a picked text preset or — for the Sampler — a `.zip`
* bundle), and Share (via the system share sheet). Presets are the plain-text
* [com.reactorcoremeltdown.sizzletracker.io.PresetIo] format, stored one folder
* [space.rcmd.android.sizzle.io.PresetIo] format, stored one folder
* per instrument/effect.
*/
@Composable
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.tracker
package space.rcmd.android.sizzle.ui.tracker
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
@@ -42,12 +42,12 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.Arrangement as ArrModel
import com.reactorcoremeltdown.sizzletracker.model.LoopRegion
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.GlyphCache
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.Arrangement as ArrModel
import space.rcmd.android.sizzle.model.LoopRegion
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.GlyphCache
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The lower-half arrangement. Layout (spreadsheet-style, like the sizzletracker
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.tracker
package space.rcmd.android.sizzle.ui.tracker
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
@@ -23,13 +23,13 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.Cell
import com.reactorcoremeltdown.sizzletracker.model.CellColumn
import com.reactorcoremeltdown.sizzletracker.model.Pattern
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.components.GlyphCache
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.Cell
import space.rcmd.android.sizzle.model.CellColumn
import space.rcmd.android.sizzle.model.Pattern
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.components.GlyphCache
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The demoscene pattern grid, drawn as ONE [Canvas] instead of a tree of ~180
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.ui.tracker
package space.rcmd.android.sizzle.ui.tracker
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
@@ -28,12 +28,12 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.reactorcoremeltdown.sizzletracker.model.TimeSignature
import com.reactorcoremeltdown.sizzletracker.ui.AppViewModel
import com.reactorcoremeltdown.sizzletracker.ui.isLandscape
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroButton
import com.reactorcoremeltdown.sizzletracker.ui.components.RetroDropdown
import com.reactorcoremeltdown.sizzletracker.ui.theme.LocalRetro
import space.rcmd.android.sizzle.model.TimeSignature
import space.rcmd.android.sizzle.ui.AppViewModel
import space.rcmd.android.sizzle.ui.isLandscape
import space.rcmd.android.sizzle.ui.components.RetroButton
import space.rcmd.android.sizzle.ui.components.RetroDropdown
import space.rcmd.android.sizzle.ui.theme.LocalRetro
/**
* The first tab. Two stacked halves:
@@ -54,7 +54,7 @@ fun TrackerScreen(vm: AppViewModel) {
private fun TrackerLower(vm: AppViewModel, modifier: Modifier) {
Box(modifier) {
if (vm.punchInMode) {
com.reactorcoremeltdown.sizzletracker.ui.StackedKeyboard(vm, punchIn = true, Modifier.fillMaxSize())
space.rcmd.android.sizzle.ui.StackedKeyboard(vm, punchIn = true, Modifier.fillMaxSize())
} else {
ArrangementRoll(vm)
}
@@ -188,7 +188,7 @@ private fun PatternButtons(vm: AppViewModel) {
)
RetroDropdown(
label = "SCALE",
options = com.reactorcoremeltdown.sizzletracker.model.Scale.entries,
options = space.rcmd.android.sizzle.model.Scale.entries,
selected = project.scale,
optionLabel = { it.label },
onSelect = { project.scale = it; vm.bumpForToolbar() },
@@ -197,7 +197,7 @@ private fun PatternButtons(vm: AppViewModel) {
label = "ROOT",
options = (0..11).toList(),
selected = project.rootNote,
optionLabel = { com.reactorcoremeltdown.sizzletracker.model.Pitch.name(60 + it).dropLast(1) },
optionLabel = { space.rcmd.android.sizzle.model.Pitch.name(60 + it).dropLast(1) },
onSelect = { project.rootNote = it; vm.bumpForToolbar() },
)
}
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later
package com.reactorcoremeltdown.sizzletracker.io
package space.rcmd.android.sizzle.io
import com.reactorcoremeltdown.sizzletracker.model.Arrangement
import com.reactorcoremeltdown.sizzletracker.model.Pitch
import com.reactorcoremeltdown.sizzletracker.model.Project
import com.reactorcoremeltdown.sizzletracker.model.TimeSignature
import space.rcmd.android.sizzle.model.Arrangement
import space.rcmd.android.sizzle.model.Pitch
import space.rcmd.android.sizzle.model.Project
import space.rcmd.android.sizzle.model.TimeSignature
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
+1 -1
View File
@@ -84,7 +84,7 @@ Three ideas hold it together:
## 4. Package/file map
```
com.reactorcoremeltdown.sizzletracker
space.rcmd.android.sizzle
├── SizzleApp.kt Application = tiny DI container (Project, InputRouter, AudioEngine)
├── MainActivity.kt Hosts Compose UI; forwards HW key/motion events; starts MIDI + service
│