Skip to content

Commit ee3a926

Browse files
authored
REfactored GOMidiPlayer for playing midi events though GOMidi instead of GOMOrganController (#2040)
1 parent 81446df commit ee3a926

File tree

8 files changed

+95
-45
lines changed

8 files changed

+95
-45
lines changed

src/core/midi/GOMidiEvent.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright 2006 Milan Digital Audio LLC
3-
* Copyright 2009-2023 GrandOrgue contributors (see AUTHORS)
3+
* Copyright 2009-2024 GrandOrgue contributors (see AUTHORS)
44
* License GPL-2.0 or later
55
* (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
66
*/
@@ -20,7 +20,8 @@ GOMidiEvent::GOMidiEvent()
2020
m_time(0),
2121
m_string(),
2222
m_data(),
23-
m_IsToUseNoteOff(true) {}
23+
m_IsToUseNoteOff(true),
24+
m_IsAllowedToReload(true) {}
2425

2526
GOMidiEvent::GOMidiEvent(const GOMidiEvent &e)
2627
: m_MidiType(e.m_MidiType),
@@ -31,7 +32,8 @@ GOMidiEvent::GOMidiEvent(const GOMidiEvent &e)
3132
m_time(e.m_time),
3233
m_string(e.m_string.Clone()),
3334
m_data(e.m_data),
34-
m_IsToUseNoteOff(e.m_IsToUseNoteOff) {}
35+
m_IsToUseNoteOff(e.m_IsToUseNoteOff),
36+
m_IsAllowedToReload(e.m_IsAllowedToReload) {}
3537

3638
void GOMidiEvent::SetString(const wxString &str, unsigned length) {
3739
unsigned len = str.length();

src/core/midi/GOMidiEvent.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright 2006 Milan Digital Audio LLC
3-
* Copyright 2009-2023 GrandOrgue contributors (see AUTHORS)
3+
* Copyright 2009-2024 GrandOrgue contributors (see AUTHORS)
44
* License GPL-2.0 or later
55
* (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
66
*/
@@ -56,6 +56,11 @@ class GOMidiEvent {
5656
wxString m_string;
5757
std::vector<uint8_t> m_data;
5858
bool m_IsToUseNoteOff;
59+
/**
60+
* Is allowing to close the organ and to load another organ when playing this
61+
* midi event
62+
*/
63+
bool m_IsAllowedToReload;
5964

6065
public:
6166
GOMidiEvent();
@@ -95,6 +100,9 @@ class GOMidiEvent {
95100

96101
void SetUseNoteOff(bool useNoteOff) { m_IsToUseNoteOff = useNoteOff; }
97102
bool IsUsingNoteOff() const { return m_IsToUseNoteOff; }
103+
104+
bool IsAllowedToReload() const { return m_IsAllowedToReload; }
105+
void SetAllowedToReload(bool value) { m_IsAllowedToReload = value; }
98106
};
99107

100108
#endif

src/grandorgue/GOOrganController.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ void GOOrganController::Abort() {
10271027

10281028
GOEventDistributor::AbortPlayback();
10291029

1030-
m_MidiPlayer->StopPlaying();
1030+
m_MidiPlayer->Cleanup();
10311031
m_MidiRecorder->StopRecording();
10321032
m_AudioRecorder->StopRecording();
10331033
m_AudioRecorder->SetAudioRecorder(NULL);
@@ -1064,6 +1064,7 @@ void GOOrganController::PreparePlayback(
10641064

10651065
GOEventDistributor::StartPlayback();
10661066
GOEventDistributor::PrepareRecording();
1067+
m_MidiPlayer->Setup(midi);
10671068

10681069
// Light the OnState button
10691070
if (p_OnStateButton) {

src/grandorgue/gui/frames/GOFrame.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -1345,12 +1345,14 @@ void GOFrame::OnMidiEvent(const GOMidiEvent &event) {
13451345
_("MIDI event: ") + event.ToString(m_Sound.GetMidi().GetMidiMap()));
13461346
}
13471347

1348-
ptr_vector<GOOrgan> &organs = m_config.GetOrganList();
1349-
for (unsigned i = 0; i < organs.size(); i++)
1350-
if (organs[i]->Match(event) && organs[i]->IsUsable(m_config)) {
1351-
SendLoadOrgan(*organs[i]);
1352-
return;
1353-
}
1348+
if (event.IsAllowedToReload()) {
1349+
ptr_vector<GOOrgan> &organs = m_config.GetOrganList();
1350+
for (auto pOrgan : organs)
1351+
if (pOrgan->Match(event) && pOrgan->IsUsable(m_config)) {
1352+
SendLoadOrgan(*pOrgan);
1353+
break;
1354+
}
1355+
}
13541356
}
13551357

13561358
void GOFrame::OnSetTitle(wxCommandEvent &event) {

src/grandorgue/midi/GOMidi.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,14 @@ void GOMidi::Recv(const GOMidiEvent &e) {
9595
AddPendingEvent(event);
9696
}
9797

98-
void GOMidi::OnMidiEvent(wxMidiEvent &event) {
99-
GOMidiEvent e = event.GetMidiEvent();
98+
void GOMidi::PlayEvent(const GOMidiEvent &e) {
10099
for (unsigned i = 0; i < m_Listeners.size(); i++)
101100
if (m_Listeners[i])
102101
m_Listeners[i]->Send(e);
103102
}
104103

104+
void GOMidi::OnMidiEvent(wxMidiEvent &e) { PlayEvent(e.GetMidiEvent()); }
105+
105106
void GOMidi::Send(const GOMidiEvent &e) {
106107
for (unsigned j = 0; j < m_midi_out_devices.size(); j++)
107108
((GOMidiOutPort *)m_midi_out_devices[j])->Send(e);

src/grandorgue/midi/GOMidi.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright 2006 Milan Digital Audio LLC
3-
* Copyright 2009-2023 GrandOrgue contributors (see AUTHORS)
3+
* Copyright 2009-2024 GrandOrgue contributors (see AUTHORS)
44
* License GPL-2.0 or later
55
* (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
66
*/
@@ -33,7 +33,6 @@ class GOMidi : public wxEvtHandler {
3333
int m_transpose;
3434
std::vector<GOMidiListener *> m_Listeners;
3535
GOMidiPortFactory m_MidiFactory;
36-
void OnMidiEvent(wxMidiEvent &event);
3736

3837
public:
3938
GOMidi(GOConfig &settings);
@@ -43,6 +42,8 @@ class GOMidi : public wxEvtHandler {
4342
void UpdateDevices(const GOPortsConfig &portsConfig);
4443

4544
void Recv(const GOMidiEvent &e);
45+
void PlayEvent(const GOMidiEvent &e);
46+
void OnMidiEvent(wxMidiEvent &e);
4647
void Send(const GOMidiEvent &e);
4748

4849
const ptr_vector<GOMidiPort> &GetInDevices() const {

src/grandorgue/midi/GOMidiPlayer.cpp

+38-28
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "midi/GOMidiMap.h"
1717

1818
#include "GOEvent.h"
19+
#include "GOMidi.h"
1920
#include "GOOrganController.h"
2021

2122
enum {
@@ -38,24 +39,29 @@ const struct GOElementCreator::ButtonDefinitionEntry *GOMidiPlayer::
3839
return m_element_types;
3940
}
4041

42+
void GOMidiPlayer::ResetUI() {
43+
m_buttons[ID_MIDI_PLAYER_PLAY]->Display(false);
44+
m_buttons[ID_MIDI_PLAYER_PAUSE]->Display(false);
45+
UpdateDisplay();
46+
}
47+
4148
GOMidiPlayer::GOMidiPlayer(GOOrganController *organController)
42-
: m_OrganController(organController),
49+
: r_MidiMap(organController->GetSettings().GetMidiMap()),
50+
r_timer(*organController->GetTimer()),
51+
p_midi(nullptr),
4352
m_content(),
4453
m_PlayingTime(organController),
4554
m_Start(0),
4655
m_PlayingSeconds(0),
4756
m_Speed(1),
4857
m_IsPlaying(false),
4958
m_Pause(false) {
50-
CreateButtons(*m_OrganController);
51-
Clear();
52-
m_DeviceID
53-
= m_OrganController->GetSettings().GetMidiMap().GetDeviceIdByLogicalName(
54-
_("GrandOrgue MIDI Player"));
55-
UpdateDisplay();
59+
CreateButtons(*organController);
60+
m_DeviceID = r_MidiMap.GetDeviceIdByLogicalName(_("GrandOrgue MIDI Player"));
61+
ResetUI();
5662
}
5763

58-
GOMidiPlayer::~GOMidiPlayer() { StopPlaying(); }
64+
GOMidiPlayer::~GOMidiPlayer() { Cleanup(); }
5965

6066
void GOMidiPlayer::Load(GOConfigReader &cfg) {
6167
m_buttons[ID_MIDI_PLAYER_PLAY]->Init(cfg, wxT("MidiPlayerPlay"), _("PLAY"));
@@ -81,15 +87,11 @@ void GOMidiPlayer::ButtonStateChanged(int id, bool newState) {
8187
}
8288
}
8389

84-
void GOMidiPlayer::Clear() {
85-
StopPlaying();
86-
m_content.Clear();
87-
}
88-
8990
void GOMidiPlayer::LoadFile(
9091
const wxString &filename, unsigned manuals, bool pedal) {
91-
Clear();
92-
GOMidiFileReader reader(m_OrganController->GetSettings().GetMidiMap());
92+
StopPlaying();
93+
m_content.Clear();
94+
GOMidiFileReader reader(r_MidiMap);
9395
if (!reader.Open(filename)) {
9496
GOMessageBox(
9597
wxString::Format(_("Failed to load %s"), filename.c_str()),
@@ -98,11 +100,7 @@ void GOMidiPlayer::LoadFile(
98100
NULL);
99101
return;
100102
}
101-
if (!m_content.Load(
102-
reader,
103-
m_OrganController->GetSettings().GetMidiMap(),
104-
manuals,
105-
pedal)) {
103+
if (!m_content.Load(reader, r_MidiMap, manuals, pedal)) {
106104
m_content.Clear();
107105
GOMessageBox(
108106
wxString::Format(_("Failed to load %s"), filename.c_str()),
@@ -150,10 +148,17 @@ void GOMidiPlayer::Pause() {
150148
m_Pause = true;
151149
m_buttons[ID_MIDI_PLAYER_PAUSE]->Display(m_Pause);
152150
m_Start = wxGetLocalTimeMillis() - m_Start;
153-
m_OrganController->GetTimer()->DeleteTimer(this);
151+
r_timer.DeleteTimer(this);
154152
}
155153
}
156154

155+
void GOMidiPlayer::PlayMidiEvent(const GOMidiEvent &e) {
156+
GOMidi *pMidi = p_midi;
157+
158+
if (pMidi)
159+
pMidi->PlayEvent(e);
160+
}
161+
157162
void GOMidiPlayer::StopPlaying() {
158163
if (m_IsPlaying) {
159164
for (unsigned i = 1; i < 16; i++) {
@@ -164,15 +169,14 @@ void GOMidiPlayer::StopPlaying() {
164169
e.SetValue(0);
165170
e.SetDevice(m_DeviceID);
166171
e.SetTime(wxGetLocalTimeMillis());
167-
m_OrganController->ProcessMidi(e);
172+
e.SetAllowedToReload(false);
173+
PlayMidiEvent(e);
168174
}
169175
}
170176

171177
m_IsPlaying = false;
172-
m_buttons[ID_MIDI_PLAYER_PLAY]->Display(false);
173-
m_buttons[ID_MIDI_PLAYER_PAUSE]->Display(false);
174-
UpdateDisplay();
175-
m_OrganController->GetTimer()->DeleteTimer(this);
178+
ResetUI();
179+
r_timer.DeleteTimer(this);
176180
}
177181

178182
bool GOMidiPlayer::IsPlaying() { return m_IsPlaying; }
@@ -207,12 +211,13 @@ void GOMidiPlayer::HandleTimer() {
207211
}
208212
e.SetDevice(m_DeviceID);
209213
e.SetTime(wxGetLocalTimeMillis());
210-
m_OrganController->ProcessMidi(e);
214+
e.SetAllowedToReload(false);
215+
PlayMidiEvent(e);
211216
} else {
212217
GOTime next = e.GetTime() * m_Speed + m_Start;
213218
if (next > m_Start + m_Speed * (m_PlayingSeconds + 1) * 1000)
214219
next = m_Start + m_Speed * (m_PlayingSeconds + 1) * 1000;
215-
m_OrganController->GetTimer()->SetTimer(next, this);
220+
r_timer.SetTimer(next, this);
216221
return;
217222
}
218223
} while (true);
@@ -231,3 +236,8 @@ GOLabelControl *GOMidiPlayer::GetLabelControl(
231236
return &m_PlayingTime;
232237
return NULL;
233238
}
239+
240+
void GOMidiPlayer::Cleanup() {
241+
StopPlaying();
242+
p_midi = nullptr;
243+
}

src/grandorgue/midi/GOMidiPlayer.h

+27-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
#include "GOTime.h"
2121
#include "GOTimerCallback.h"
2222

23+
class GOMidi;
24+
class GOMidiMap;
2325
class GOMidiEvent;
2426
class GOMidiFileReader;
2527
class GOOrganController;
28+
class GOTimer;
2629

2730
class GOMidiPlayer : public GOElementCreator, private GOTimerCallback {
2831
private:
29-
GOOrganController *m_OrganController;
32+
GOMidiMap &r_MidiMap;
33+
GOTimer &r_timer;
34+
GOMidi *p_midi;
3035
GOMidiPlayerContent m_content;
3136
GOLabelControl m_PlayingTime;
3237
GOTime m_Start;
@@ -43,13 +48,28 @@ class GOMidiPlayer : public GOElementCreator, private GOTimerCallback {
4348
void ButtonStateChanged(int id, bool newState) override;
4449

4550
void UpdateDisplay();
51+
52+
/**
53+
* Set the buttons and the display to the initial state
54+
*/
55+
void ResetUI();
56+
/**
57+
* Send midi event to the organ
58+
* @param event the event to process
59+
*/
60+
void PlayMidiEvent(const GOMidiEvent &e);
4661
void HandleTimer() override;
4762

4863
public:
4964
GOMidiPlayer(GOOrganController *organController);
5065
~GOMidiPlayer();
5166

52-
void Clear();
67+
/**
68+
* Set up for playing any midi
69+
* @param pMidi - a pointer to the midi engine
70+
*/
71+
void Setup(GOMidi *pMidi) { p_midi = pMidi; }
72+
5373
void LoadFile(const wxString &filename, unsigned manuals, bool pedal);
5474
bool IsLoaded();
5575

@@ -61,6 +81,11 @@ class GOMidiPlayer : public GOElementCreator, private GOTimerCallback {
6181
void Load(GOConfigReader &cfg) override;
6282
GOEnclosure *GetEnclosure(const wxString &name, bool is_panel) override;
6383
GOLabelControl *GetLabelControl(const wxString &name, bool is_panel) override;
84+
85+
/**
86+
* Clean up. Playing will be impossible until Setup is called
87+
*/
88+
void Cleanup();
6489
};
6590

6691
#endif

0 commit comments

Comments
 (0)