1212//
1313// You should have received a copy of the GNU General Public License
1414// along with Noteahead. If not, see <http://www.gnu.org/licenses/>.
15-
1615#include " device_service.hpp"
1716
1817#include " ../../common/constants.hpp"
18+ #include " ../../common/utils.hpp"
1919#include " ../../domain/devices/sampler_device.hpp"
2020#include " ../../domain/devices/synth_device.hpp"
2121#include " ../../infra/audio/audio_engine.hpp"
2222
23- #include < QStringList>
2423#include < QXmlStreamReader>
2524#include < QXmlStreamWriter>
25+ #include < set>
26+ #include < QXmlStreamWriter>
2627
2728#include < set>
2829
@@ -32,6 +33,9 @@ DeviceService::DeviceService(AudioEngineS audioEngine, QObject * parent)
3233 : QObject { parent }
3334 , m_audioEngine { std::move (audioEngine) }
3435{
36+ for (int i = 0 ; i < 128 ; ++i) {
37+ m_synthUserPresets[i] = SynthPresets::initPreset ();
38+ }
3539}
3640
3741DeviceService::~DeviceService () = default ;
@@ -78,6 +82,13 @@ void DeviceService::processMidiCc(const QString & portName, uint8_t controller,
7882 }
7983}
8084
85+ void DeviceService::processMidiProgramChange (const QString & portName, uint8_t program, uint8_t channel)
86+ {
87+ if (const auto dev = device (portName.toStdString ()); dev) {
88+ dev->processMidiProgramChange (program, channel);
89+ }
90+ }
91+
8192void DeviceService::processMidiAllNotesOff (const QString & portName)
8293{
8394 if (const auto dev = device (portName.toStdString ()); dev) {
@@ -139,6 +150,32 @@ QStringList DeviceService::devicesByCategory(const QString & category) const
139150 return devices;
140151}
141152
153+ void DeviceService::setSynthUserPresets (const UserPresets & presets)
154+ {
155+ m_synthUserPresets = presets;
156+ for (const auto & name : internalDeviceNames ()) {
157+ if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (name))) {
158+ synth->setUserPresets (m_synthUserPresets);
159+ }
160+ }
161+ if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (Constants::synthDeviceName ().toStdString ()))) {
162+ synth->setUserPresets (m_synthUserPresets);
163+ }
164+ emit synthUserPresetsChanged (m_synthUserPresets);
165+ }
166+
167+ UserPresets DeviceService::synthUserPresets () const
168+ {
169+ return m_synthUserPresets;
170+ }
171+
172+ void DeviceService::saveSynthUserPreset (int index, const SynthPreset & preset)
173+ {
174+ m_synthUserPresets[index] = preset;
175+ setSynthUserPresets (m_synthUserPresets);
176+ emit dataChanged ();
177+ }
178+
142179void DeviceService::setProjectPath (const std::string & projectPath)
143180{
144181 for (const auto & name : internalDeviceNames ()) {
@@ -156,30 +193,107 @@ void DeviceService::serializeToXml(QXmlStreamWriter & writer) const
156193 dev->serializeToXml (writer);
157194 }
158195 }
159- if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (Constants::synthDeviceName ().toStdString ())); synth ) {
196+ if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (Constants::synthDeviceName ().toStdString ()))) {
160197 synth->serializeToXml (writer);
161198 }
199+
200+ if (!m_synthUserPresets.empty ()) {
201+ std::shared_ptr<SynthDevice> synth;
202+ for (const auto & name : internalDeviceNames ()) {
203+ if (auto dev = std::dynamic_pointer_cast<SynthDevice>(device (name))) {
204+ synth = dev;
205+ break ;
206+ }
207+ }
208+ const auto typeId = synth ? QString::fromStdString (synth->typeId ()) : " " ;
209+
210+ writer.writeStartElement (Constants::NahdXml::xmlKeyUserPresets ());
211+ if (!typeId.isEmpty ()) {
212+ writer.writeAttribute (Constants::NahdXml::xmlKeyTypeId (), typeId);
213+ }
214+
215+ for (auto && [index, preset] : m_synthUserPresets) {
216+ if (!preset.parameters .empty ()) {
217+ writer.writeStartElement (Constants::NahdXml::xmlKeyPreset ());
218+ writer.writeAttribute (Constants::NahdXml::xmlKeyIndex (), QString::number (index));
219+ writer.writeAttribute (Constants::NahdXml::xmlKeyName (), QString::fromStdString (preset.name ));
220+ for (auto && [paramName, value] : preset.parameters ) {
221+ writer.writeStartElement (Constants::NahdXml::xmlKeyParameter ());
222+ writer.writeAttribute (Constants::NahdXml::xmlKeyName (), QString::fromStdString (paramName));
223+ if (synth) {
224+ if (auto p = synth->parameter (paramName); p) {
225+ writer.writeAttribute (Constants::NahdXml::xmlKeyValue (), QString::number (Parameter::internalToXmlValue (value, p->get ().xmlMin (), p->get ().xmlMax ())));
226+ writer.writeAttribute (Constants::NahdXml::xmlKeyMin (), QString::number (p->get ().xmlMin ()));
227+ writer.writeAttribute (Constants::NahdXml::xmlKeyMax (), QString::number (p->get ().xmlMax ()));
228+ writer.writeAttribute (Constants::NahdXml::xmlKeyDefault (), QString::number (p->get ().xmlDefault ()));
229+ writer.writeAttribute (Constants::NahdXml::xmlKeyScale (), QString::number (p->get ().xmlScale ()));
230+ } else {
231+ writer.writeAttribute (Constants::NahdXml::xmlKeyValue (), QString::number (static_cast <double >(value)));
232+ }
233+ } else {
234+ writer.writeAttribute (Constants::NahdXml::xmlKeyValue (), QString::number (static_cast <double >(value)));
235+ }
236+ writer.writeEndElement (); // Parameter
237+ }
238+ writer.writeEndElement (); // Preset
239+ }
240+ }
241+ writer.writeEndElement (); // SynthUserPresets
242+ }
243+
162244 writer.writeEndElement (); // Devices
163245}
164246
165247void DeviceService::deserializeFromXml (QXmlStreamReader & reader)
166248{
167- const auto samplersCategory = Constants::NahdXml::xmlValueSamplers ();
168-
169249 while (reader.readNextStartElement ()) {
170250 const auto name = reader.name ();
171251 if (name == Constants::NahdXml::xmlKeyDevice ()) {
172252 const auto category = reader.attributes ().value (Constants::NahdXml::xmlKeyCategory ()).toString ();
173253 const auto deviceName = reader.attributes ().value (Constants::NahdXml::xmlKeyName ()).toString ().toStdString ();
174- if (auto dev = device (deviceName)) {
254+ if (const auto dev = device (deviceName)) {
175255 dev->deserializeFromXml (reader);
176256 } else {
177257 reader.skipCurrentElement ();
178258 }
179- } else if (reader.isStartElement () && reader. name () == Constants::NahdXml::xmlKeySynth ()) {
180- if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (Constants::synthDeviceName ().toStdString ())); synth ) {
259+ } else if (reader.name () == Constants::NahdXml::xmlKeySynth ()) {
260+ if (const auto synth = std::dynamic_pointer_cast<SynthDevice>(device (Constants::synthDeviceName ().toStdString ()))) {
181261 synth->deserializeFromXml (reader);
182262 }
263+ } else if (reader.name () == Constants::NahdXml::xmlKeyUserPresets ()) {
264+ const auto typeId = Utils::Xml::readStringAttribute (reader, Constants::NahdXml::xmlKeyTypeId (), false );
265+
266+ while (reader.readNextStartElement ()) {
267+ if (reader.name () == Constants::NahdXml::xmlKeyPreset ()) {
268+ const auto index = Utils::Xml::readUIntAttribute (reader, Constants::NahdXml::xmlKeyIndex ()).value_or (0 );
269+ const auto presetName = Utils::Xml::readStringAttribute (reader, Constants::NahdXml::xmlKeyName ()).value_or (" Init" );
270+ SynthPreset preset { presetName.toStdString (), {} };
271+
272+ while (reader.readNextStartElement ()) {
273+ if (reader.name () == Constants::NahdXml::xmlKeyParameter ()) {
274+ const auto paramName = Utils::Xml::readStringAttribute (reader, Constants::NahdXml::xmlKeyName ()).value_or (" " ).toStdString ();
275+ if (!paramName.empty ()) {
276+ const auto xmlMin = reader.attributes ().value (Constants::NahdXml::xmlKeyMin ());
277+ const auto xmlMax = reader.attributes ().value (Constants::NahdXml::xmlKeyMax ());
278+ if (!xmlMin.isNull () && !xmlMax.isNull ()) {
279+ const auto xmlValue = reader.attributes ().value (Constants::NahdXml::xmlKeyValue ()).toInt ();
280+ preset.parameters [paramName] = Parameter::xmlValueToInternal (xmlValue, xmlMin.toInt (), xmlMax.toInt ());
281+ } else {
282+ const auto paramValue = Utils::Xml::readDoubleAttribute (reader, Constants::NahdXml::xmlKeyValue ()).value_or (0.0 );
283+ preset.parameters [paramName] = static_cast <float >(paramValue);
284+ }
285+ }
286+ reader.skipCurrentElement ();
287+ } else {
288+ reader.skipCurrentElement ();
289+ }
290+ }
291+ m_synthUserPresets[index] = std::move (preset);
292+ } else {
293+ reader.skipCurrentElement ();
294+ }
295+ }
296+ setSynthUserPresets (m_synthUserPresets);
183297 } else {
184298 reader.skipCurrentElement ();
185299 }
0 commit comments