fix(tracker): ID collisions in ClearUnit and Instruments.unmarshal

This commit is contained in:
5684185+vsariola@users.noreply.github.com 2024-09-07 15:20:12 +03:00
parent 9da6c2216c
commit 74972b5ff4
4 changed files with 20 additions and 4 deletions

View File

@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
resized ([#145][i145])
### Fixed
- Potential ID collisions when clearing unit or pasteing instruments
- Assign new IDs to loaded instruments, and fix ID collisions in case they
somehow still appear ([#146][i146])
- In x86 templates, do not optimize away phase modulations when unisons are used

View File

@ -154,6 +154,7 @@ func (m *Model) ClearUnit() Action {
defer (*Model)(m).change("DeleteUnitAction", PatchChange, MajorChange)()
m.d.UnitIndex = intMax(intMin(m.d.UnitIndex, len(m.d.Song.Patch[m.d.InstrIndex].Units)-1), 0)
m.d.Song.Patch[m.d.InstrIndex].Units[m.d.UnitIndex] = sointu.Unit{}
m.d.Song.Patch[m.d.InstrIndex].Units[m.d.UnitIndex].ID = m.maxID() + 1
},
allowed: func() bool {
return m.d.InstrIndex >= 0 &&

View File

@ -269,11 +269,13 @@ func (v *Instruments) unmarshal(data []byte) (from, to int, err error) {
if v.d.Song.Patch.NumVoices()+newInstr.Patch.NumVoices() > vm.MAX_VOICES {
return 0, 0, fmt.Errorf("InstrumentListView.unmarshal: too many voices: %d", v.d.Song.Patch.NumVoices()+newInstr.Patch.NumVoices())
}
patch := append(v.d.Song.Patch, make([]sointu.Instrument, len(newInstr.Patch))...)
v.d.Song.Patch = append(v.d.Song.Patch, make([]sointu.Instrument, len(newInstr.Patch))...)
sel := v.Selected()
copy(patch[sel+len(newInstr.Patch):], patch[sel:])
copy(patch[sel:sel+len(newInstr.Patch)], newInstr.Patch)
v.d.Song.Patch = patch
copy(v.d.Song.Patch[sel+len(newInstr.Patch):], v.d.Song.Patch[sel:])
for i := 0; i < len(newInstr.Patch); i++ {
(*Model)(v).assignUnitIDs(newInstr.Patch[i].Units)
v.d.Song.Patch[sel+i] = newInstr.Patch[i]
}
from = sel
to = sel + len(newInstr.Patch) - 1
return

View File

@ -408,6 +408,18 @@ func (m *Model) send(message interface{}) {
m.modelMessages <- message
}
func (m *Model) maxID() int {
maxID := 0
for _, instr := range m.d.Song.Patch {
for _, unit := range instr.Units {
if unit.ID > maxID {
maxID = unit.ID
}
}
}
return maxID
}
func (m *Model) assignUnitIDs(units []sointu.Unit) {
maxId := 0
usedIds := make(map[int]bool)