Skip to content

Commit 9e5abae

Browse files
committed
Fix side services not correctly cleared on MIDI import
1 parent 87e2cad commit 9e5abae

10 files changed

Lines changed: 63 additions & 21 deletions

File tree

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ set(HEADER_FILES
7070
domain/midi_cc_automation.hpp
7171
domain/midi_cc_data.hpp
7272
domain/midi_cc_setting.hpp
73+
domain/midi_import_mode.hpp
7374
domain/midi_note_data.hpp
7475
domain/mixer_unit.hpp
7576
domain/note_data.hpp

src/application/application.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,14 @@ void Application::exportToMidi(QString fileName, quint64 startPosition, quint64
340340
m_applicationService->requestStatusText(message);
341341
}
342342
}
343-
void Application::importFromMidi(QString fileName, int importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts)
343+
void Application::importFromMidi(QString fileName, MidiImportMode importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts)
344344
{
345345
try {
346346
const auto midiData = m_midiImporter->parseMidiFile(fileName.toStdString());
347+
if (importMode == MidiImportMode::Overwrite) {
348+
m_mixerService->clear();
349+
m_automationService->clear();
350+
}
347351
m_midiImporter->importTo(midiData, m_editorService->song(), importMode, patternLength, quantizeNoteOn, quantizeNoteOff, connectMidiPorts ? m_midiService : nullptr);
348352
const auto message = QString { "Imported MIDI file '%1' " }.arg(fileName);
349353
m_applicationService->requestStatusText(message);

src/application/application.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class Application : public QObject
116116
void stopAllNotes() const;
117117

118118
void exportToMidi(QString fileName, quint64 startPosition, quint64 endPosition, MidiExportOptions options);
119-
void importFromMidi(QString fileName, int importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts);
119+
void importFromMidi(QString fileName, MidiImportMode importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts);
120120

121121
std::unique_ptr<UiLogger> m_uiLogger;
122122

src/application/service/application_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ void ApplicationService::importMidiFile(QUrl url, int importMode, int patternLen
181181
fileName = url.toString();
182182
}
183183
juzzlin::L(TAG).info() << "MIDI import requested for " << fileName.toStdString() << " mode: " << importMode << " length: " << patternLength << " quantizeNoteOn: " << quantizeNoteOn << " quantizeNoteOff: " << quantizeNoteOff << " connectMidiPorts: " << connectMidiPorts;
184-
emit midiImportRequested(fileName, importMode, patternLength, quantizeNoteOn, quantizeNoteOff, connectMidiPorts);
184+
emit midiImportRequested(fileName, static_cast<MidiImportMode>(importMode), patternLength, quantizeNoteOn, quantizeNoteOff, connectMidiPorts);
185185
}
186186

187187
void ApplicationService::requestLiveNoteOn(quint8 key, quint8 octave, quint8 velocity)

src/application/service/application_service.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <memory>
2525

26+
#include "../../domain/midi_import_mode.hpp"
2627
#include "../../infra/midi/export/midi_exporter.hpp"
2728

2829
namespace noteahead {
@@ -153,7 +154,7 @@ class ApplicationService : public QObject
153154
void midiExportRequested(QString fileName, quint64 startPosition, quint64 endPosition, MidiExportOptions options);
154155

155156
void midiImportDialogRequested();
156-
void midiImportRequested(QString fileName, int importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts);
157+
void midiImportRequested(QString fileName, MidiImportMode importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, bool connectMidiPorts);
157158

158159
void alertDialogRequested(QString message);
159160
void statusTextRequested(QString message);

src/domain/midi_import_mode.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This file is part of Noteahead.
2+
// Copyright (C) 2026 Jussi Lind <jussi.lind@iki.fi>
3+
//
4+
// Noteahead is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
// Noteahead is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with Noteahead. If not, see <http://www.gnu.org/licenses/>.
15+
16+
#ifndef MIDI_IMPORT_MODE_HPP
17+
#define MIDI_IMPORT_MODE_HPP
18+
19+
namespace noteahead {
20+
21+
enum class MidiImportMode {
22+
Overwrite,
23+
Merge
24+
};
25+
26+
} // namespace noteahead
27+
28+
#endif // MIDI_IMPORT_MODE_HPP

src/infra/midi/import/midi_importer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ MidiImporter::MidiTrack MidiImporter::parseTrack(std::istream & in, uint32_t tra
200200
return track;
201201
}
202202

203-
void MidiImporter::initializeSong(SongS song, const MidiFileData & data, int importMode, int patternLength) const
203+
void MidiImporter::initializeSong(SongS song, const MidiFileData & data, MidiImportMode importMode, int patternLength) const
204204
{
205-
if (!importMode) {
205+
if (importMode == MidiImportMode::Overwrite) {
206206
song->initialize();
207207
song->setBeatsPerMinute(data.initialTempoBpm);
208208
if (patternLength > 0) {
@@ -274,17 +274,17 @@ size_t MidiImporter::getFreeColumn(SongS song, size_t patternIndex, size_t track
274274
return col;
275275
}
276276

277-
void MidiImporter::finalizePlayOrder(SongS song, size_t maxPatternIndex, int importMode, [[maybe_unused]] int patternLength) const
277+
void MidiImporter::finalizePlayOrder(SongS song, size_t maxPatternIndex, MidiImportMode importMode, [[maybe_unused]] int patternLength) const
278278
{
279-
if (!importMode) {
279+
if (importMode == MidiImportMode::Overwrite) {
280280
song->setLength(maxPatternIndex + 1);
281281
for (size_t i = 0; i <= maxPatternIndex; ++i) {
282282
song->setPatternAtSongPosition(i, i);
283283
}
284284
}
285285
}
286286

287-
void MidiImporter::importTo(const MidiFileData & data, SongS song, int importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, MidiServiceS midiService) const
287+
void MidiImporter::importTo(const MidiFileData & data, SongS song, MidiImportMode importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, MidiServiceS midiService) const
288288
{
289289
initializeSong(song, data, importMode, patternLength);
290290

src/infra/midi/import/midi_importer.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#ifndef MIDI_IMPORTER_HPP
1717
#define MIDI_IMPORTER_HPP
1818

19+
#include "../../../domain/midi_import_mode.hpp"
20+
1921
#include <cstdint>
2022
#include <istream>
2123
#include <map>
@@ -69,7 +71,7 @@ class MidiImporter
6971

7072
MidiFileData parseMidiFile(const std::string & fileName) const;
7173

72-
void importTo(const MidiFileData & data, SongS song, int importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, MidiServiceS midiService) const;
74+
void importTo(const MidiFileData & data, SongS song, MidiImportMode importMode, int patternLength, bool quantizeNoteOn, bool quantizeNoteOff, MidiServiceS midiService) const;
7375

7476
private:
7577
struct PatternLine
@@ -78,10 +80,10 @@ class MidiImporter
7880
size_t lineIndex;
7981
};
8082

81-
void initializeSong(SongS song, const MidiFileData & data, int importMode, int patternLength) const;
83+
void initializeSong(SongS song, const MidiFileData & data, MidiImportMode importMode, int patternLength) const;
8284
PatternLine getPatternLine(SongS song, size_t scaledTick, int patternLength) const;
8385
size_t getFreeColumn(SongS song, size_t patternIndex, size_t trackIndex, size_t lineIndex, const std::map<uint8_t, size_t> & activeNotes) const;
84-
void finalizePlayOrder(SongS song, size_t maxPatternIndex, int importMode, int patternLength) const;
86+
void finalizePlayOrder(SongS song, size_t maxPatternIndex, MidiImportMode importMode, int patternLength) const;
8587

8688
uint32_t readBeU32(std::istream & in) const;
8789
uint16_t readBeU16(std::istream & in) const;

src/unit_tests/midi_importer_test/midi_importer_test.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void MidiImporterTest::test_import_exportedFile_shouldRestoreNotes()
8282
importedSong->setLinesPerBeat(4);
8383

8484
const auto midiData = importer.parseMidiFile(fileName.toStdString());
85-
importer.importTo(midiData, importedSong, 0, 64, false, false, nullptr);
85+
importer.importTo(midiData, importedSong, MidiImportMode::Overwrite, 64, false, false, nullptr);
8686

8787
QCOMPARE(importedSong->beatsPerMinute(), 140);
8888
// Noteahead initializes with 8 tracks by default
@@ -142,7 +142,7 @@ void MidiImporterTest::test_import_multipleTracksAndPatterns_shouldRestoreCorrec
142142

143143
const auto midiData = importer.parseMidiFile(fileName.toStdString());
144144
// Use pattern length 4 to match original structure
145-
importer.importTo(midiData, importedSong, 0, 4, false, false, nullptr);
145+
importer.importTo(midiData, importedSong, MidiImportMode::Overwrite, 4, false, false, nullptr);
146146

147147
QCOMPARE(importedSong->trackCount(), 8);
148148
QCOMPARE(QString::fromStdString(importedSong->trackName(0)), QString { "Melody" });
@@ -199,7 +199,7 @@ void MidiImporterTest::test_import_polyphony_shouldCreateNewColumns()
199199
importedSong->setLinesPerBeat(4);
200200

201201
const auto midiData = importer.parseMidiFile(fileName.toStdString());
202-
importer.importTo(midiData, importedSong, 0, 64, false, false, nullptr);
202+
importer.importTo(midiData, importedSong, MidiImportMode::Overwrite, 64, false, false, nullptr);
203203

204204
// Should have 3 columns on track 0
205205
QCOMPARE(importedSong->columnCount(0), 3);
@@ -254,7 +254,7 @@ void MidiImporterTest::test_import_quantization_shouldZeroDelays()
254254
const auto midiData = importer.parseMidiFile(fileName.toStdString());
255255

256256
// Import with quantization enabled
257-
importer.importTo(midiData, importedSong, 0, 64, true, true, nullptr);
257+
importer.importTo(midiData, importedSong, MidiImportMode::Overwrite, 64, true, true, nullptr);
258258

259259
const auto noteOnQuantized = importedSong->noteDataAtPosition({ 0, 0, 0, 0 });
260260
const auto noteOffQuantized = importedSong->noteDataAtPosition({ 0, 0, 0, 1 });
@@ -266,7 +266,7 @@ void MidiImporterTest::test_import_quantization_shouldZeroDelays()
266266
const auto importedSongNoQuantize = std::make_shared<Song>();
267267
importedSongNoQuantize->setBeatsPerMinute(120);
268268
importedSongNoQuantize->setLinesPerBeat(4);
269-
importer.importTo(midiData, importedSongNoQuantize, 0, 64, false, false, nullptr);
269+
importer.importTo(midiData, importedSongNoQuantize, MidiImportMode::Overwrite, 64, false, false, nullptr);
270270

271271
const auto noteOnNotQuantized = importedSongNoQuantize->noteDataAtPosition({ 0, 0, 0, 0 });
272272
const auto noteOffNotQuantized = importedSongNoQuantize->noteDataAtPosition({ 0, 0, 0, 1 });
@@ -313,7 +313,7 @@ void MidiImporterTest::test_import_bankAndProgramChange_shouldRestoreSettings()
313313

314314
const auto importedSong = std::make_shared<Song>();
315315
const auto midiData = importer.parseMidiFile(fileName.toStdString());
316-
importer.importTo(midiData, importedSong, 0, 64, false, false, midiService);
316+
importer.importTo(midiData, importedSong, MidiImportMode::Overwrite, 64, false, false, midiService);
317317

318318
const auto importedInstrument = importedSong->instrument(0);
319319
QVERIFY(importedInstrument != nullptr);

src/view/qml/Editor/Track.qml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,19 @@ Rectangle {
164164
resize(rootItem.width, rootItem.height);
165165
}
166166
function setColumnMuted(columnIndex: int, muted: bool): void {
167-
_noteColumns[columnIndex].setMuted(muted);
167+
if (_noteColumns[columnIndex]) {
168+
_noteColumns[columnIndex].setMuted(muted);
169+
}
168170
}
169171
function setColumnSoloed(columnIndex: int, soloed: bool): void {
170-
_noteColumns[columnIndex].setSoloed(soloed);
172+
if (_noteColumns[columnIndex]) {
173+
_noteColumns[columnIndex].setSoloed(soloed);
174+
}
171175
}
172176
function setColumnVelocityScale(columnIndex: int, value: int): void {
173-
_noteColumns[columnIndex].setVelocityScale(value);
177+
if (_noteColumns[columnIndex]) {
178+
_noteColumns[columnIndex].setVelocityScale(value);
179+
}
174180
}
175181
function clearMixerSettings(): void {
176182
_noteColumns.forEach(noteColumn => {

0 commit comments

Comments
 (0)