Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #include "projectaudiosettings.h"
23 :
24 : #include <map>
25 : #include <QJsonDocument>
26 : #include <QJsonArray>
27 : #include <QJsonObject>
28 :
29 : #include "types/bytearray.h"
30 :
31 : #include "audio/common/audioutils.h"
32 : #include "vst/vstpluginattrs.h"
33 :
34 : using namespace mu::project;
35 : using namespace muse;
36 : using namespace muse::audio;
37 : using namespace mu::engraving;
38 : using namespace mu::playback;
39 :
40 : static const std::map<AudioSourceType, QString> SOURCE_TYPE_MAP = {
41 : { AudioSourceType::Undefined, "undefined" },
42 : { AudioSourceType::MuseSampler, "musesampler" },
43 : { AudioSourceType::Fluid, "fluid" },
44 : { AudioSourceType::Vsti, "vsti" }
45 : };
46 :
47 0 : static void doCompatibilityConversions(AudioResourceMeta& meta)
48 : {
49 0 : if (isResourceType(meta, AudioResourceType::MuseSamplerSoundPack)) {
50 : // MS 4.5: resource name and category have been excluded from ID
51 : // Old format: category\\name\\uid
52 0 : if (meta.id.find("\\") == std::string::npos) {
53 0 : return;
54 : }
55 :
56 0 : const String& museUID = meta.attributeVal(u"museUID");
57 0 : if (!museUID.empty()) {
58 0 : meta.id = museUID.toStdString();
59 : }
60 : }
61 : }
62 :
63 0 : bool ProjectAudioSettings::hasAnyAudioSettings() const
64 : {
65 0 : return !m_trackInputParamsMap.empty() || !m_trackOutputParamsMap.empty() || !m_auxOutputParams.empty();
66 : }
67 :
68 0 : const AudioOutputParams& ProjectAudioSettings::masterAudioOutputParams() const
69 : {
70 0 : return m_masterOutputParams;
71 : }
72 :
73 0 : void ProjectAudioSettings::setMasterAudioOutputParams(const AudioOutputParams& params)
74 : {
75 0 : if (m_masterOutputParams == params) {
76 0 : return;
77 : }
78 :
79 0 : m_masterOutputParams = params;
80 0 : m_settingsChanged.notify();
81 : }
82 :
83 0 : bool ProjectAudioSettings::containsAuxOutputParams(aux_channel_idx_t index) const
84 : {
85 0 : return muse::contains(m_auxOutputParams, index);
86 : }
87 :
88 0 : const AudioOutputParams& ProjectAudioSettings::auxOutputParams(aux_channel_idx_t index) const
89 : {
90 0 : if (index < m_auxOutputParams.size()) {
91 0 : return m_auxOutputParams.at(index);
92 : }
93 :
94 0 : static const AudioOutputParams _dummy;
95 0 : return _dummy;
96 : }
97 :
98 0 : void ProjectAudioSettings::setAuxOutputParams(aux_channel_idx_t index, const AudioOutputParams& params, bool notifySettingsChanged)
99 : {
100 0 : auto it = m_auxOutputParams.find(index);
101 0 : if (it != m_auxOutputParams.end() && it->second == params) {
102 0 : return;
103 : }
104 :
105 0 : m_auxOutputParams.insert_or_assign(index, params);
106 :
107 0 : if (notifySettingsChanged) {
108 0 : m_settingsChanged.notify();
109 : }
110 : }
111 :
112 0 : const TrackInputParamsMap& ProjectAudioSettings::allTrackInputParams() const
113 : {
114 0 : return m_trackInputParamsMap;
115 : }
116 :
117 0 : const AudioInputParams& ProjectAudioSettings::trackInputParams(const InstrumentTrackId& partId) const
118 : {
119 0 : auto it = m_trackInputParamsMap.find(partId);
120 0 : if (it == m_trackInputParamsMap.end()) {
121 0 : static const AudioInputParams _dummy;
122 0 : return _dummy;
123 : }
124 :
125 0 : return it->second;
126 : }
127 :
128 0 : void ProjectAudioSettings::setTrackInputParams(const InstrumentTrackId& partId, const AudioInputParams& params,
129 : bool notifySettingsChanged)
130 : {
131 0 : auto it = m_trackInputParamsMap.find(partId);
132 0 : if (it != m_trackInputParamsMap.end() && it->second == params) {
133 0 : return;
134 : }
135 :
136 0 : m_trackInputParamsMap.insert_or_assign(partId, params);
137 0 : m_trackInputParamsChanged.send(partId);
138 :
139 0 : if (notifySettingsChanged) {
140 0 : m_settingsChanged.notify();
141 : }
142 : }
143 :
144 0 : void ProjectAudioSettings::clearTrackInputParams()
145 : {
146 0 : if (m_trackInputParamsMap.empty()) {
147 0 : return;
148 : }
149 :
150 0 : auto it = m_trackInputParamsMap.begin();
151 0 : while (it != m_trackInputParamsMap.end()) {
152 0 : InstrumentTrackId id = it->first;
153 0 : it = m_trackInputParamsMap.erase(it);
154 0 : m_trackInputParamsChanged.send(id);
155 0 : }
156 :
157 0 : m_settingsChanged.notify();
158 : }
159 :
160 0 : muse::async::Channel<mu::engraving::InstrumentTrackId> ProjectAudioSettings::trackInputParamsChanged() const
161 : {
162 0 : return m_trackInputParamsChanged;
163 : }
164 :
165 0 : bool ProjectAudioSettings::trackHasExistingOutputParams(const InstrumentTrackId& partId) const
166 : {
167 0 : return muse::contains(m_trackOutputParamsMap, partId);
168 : }
169 :
170 0 : const AudioOutputParams& ProjectAudioSettings::trackOutputParams(const InstrumentTrackId& partId) const
171 : {
172 0 : auto search = m_trackOutputParamsMap.find(partId);
173 :
174 0 : if (search == m_trackOutputParamsMap.end()) {
175 0 : static const AudioOutputParams _dummy;
176 0 : return _dummy;
177 : }
178 :
179 0 : return search->second;
180 : }
181 :
182 0 : void ProjectAudioSettings::setTrackOutputParams(const InstrumentTrackId& partId, const AudioOutputParams& params,
183 : bool notifySettingsChanged)
184 : {
185 0 : auto it = m_trackOutputParamsMap.find(partId);
186 0 : bool paramsChanged = it == m_trackOutputParamsMap.cend();
187 :
188 0 : if (!paramsChanged) {
189 0 : paramsChanged |= !muse::RealIsEqual(it->second.volume, params.volume);
190 0 : paramsChanged |= !muse::RealIsEqual(it->second.balance, params.balance);
191 0 : paramsChanged |= (it->second.fxChain != params.fxChain);
192 0 : paramsChanged |= (it->second.auxSends != params.auxSends);
193 : }
194 :
195 0 : m_trackOutputParamsMap.insert_or_assign(partId, params);
196 :
197 0 : if (paramsChanged && notifySettingsChanged) {
198 0 : m_settingsChanged.notify();
199 : }
200 0 : }
201 :
202 0 : const IProjectAudioSettings::SoloMuteState& ProjectAudioSettings::auxSoloMuteState(aux_channel_idx_t index) const
203 : {
204 0 : auto it = m_auxSoloMuteStatesMap.find(index);
205 0 : if (it == m_auxSoloMuteStatesMap.end()) {
206 : static const IProjectAudioSettings::SoloMuteState _dummy;
207 0 : return _dummy;
208 : }
209 :
210 0 : return it->second;
211 : }
212 :
213 0 : void ProjectAudioSettings::setAuxSoloMuteState(aux_channel_idx_t index, const SoloMuteState& state)
214 : {
215 0 : auto it = m_auxSoloMuteStatesMap.find(index);
216 0 : if (it != m_auxSoloMuteStatesMap.end() && it->second == state) {
217 0 : return;
218 : }
219 :
220 0 : m_auxSoloMuteStatesMap.insert_or_assign(index, state);
221 0 : m_auxSoloMuteStateChanged.send(index, state);
222 0 : m_settingsChanged.notify();
223 : }
224 :
225 0 : muse::async::Channel<aux_channel_idx_t, IProjectAudioSettings::SoloMuteState> ProjectAudioSettings::auxSoloMuteStateChanged() const
226 : {
227 0 : return m_auxSoloMuteStateChanged;
228 : }
229 :
230 0 : void ProjectAudioSettings::removeTrackParams(const InstrumentTrackId& partId)
231 : {
232 0 : auto inSearch = m_trackInputParamsMap.find(partId);
233 0 : if (inSearch != m_trackInputParamsMap.end()) {
234 0 : m_trackInputParamsMap.erase(inSearch);
235 0 : m_trackInputParamsChanged.send(partId);
236 0 : m_settingsChanged.notify();
237 : }
238 :
239 0 : auto outSearch = m_trackOutputParamsMap.find(partId);
240 0 : if (outSearch != m_trackOutputParamsMap.end()) {
241 0 : m_trackOutputParamsMap.erase(outSearch);
242 0 : m_settingsChanged.notify();
243 : }
244 0 : }
245 :
246 0 : const SoundProfileName& ProjectAudioSettings::activeSoundProfile() const
247 : {
248 0 : return m_activeSoundProfileName;
249 : }
250 :
251 0 : void ProjectAudioSettings::setActiveSoundProfile(const playback::SoundProfileName& profileName)
252 : {
253 0 : if (m_activeSoundProfileName == profileName) {
254 0 : return;
255 : }
256 :
257 0 : m_activeSoundProfileName = profileName;
258 0 : m_settingsChanged.notify();
259 : }
260 :
261 0 : muse::async::Notification ProjectAudioSettings::settingsChanged() const
262 : {
263 0 : return m_settingsChanged;
264 : }
265 :
266 0 : Ret ProjectAudioSettings::read(const engraving::MscReader& reader)
267 : {
268 0 : ByteArray json = reader.readAudioSettingsJsonFile();
269 0 : if (json.empty()) {
270 0 : return make_ret(Ret::Code::UnknownError);
271 : }
272 :
273 0 : QJsonObject rootObj = QJsonDocument::fromJson(json.toQByteArrayNoCopy()).object();
274 :
275 0 : QJsonObject masterObj = rootObj.value("master").toObject();
276 0 : m_masterOutputParams = outputParamsFromJson(masterObj);
277 :
278 0 : QJsonArray auxArray = rootObj.value("aux").toArray();
279 0 : for (aux_channel_idx_t i = 0; i < static_cast<aux_channel_idx_t>(auxArray.size()); ++i) {
280 0 : QJsonObject auxObject = auxArray[i].toObject();
281 :
282 0 : AudioOutputParams outParams = outputParamsFromJson(auxObject.value("out").toObject());
283 0 : SoloMuteState soloMuteState = soloMuteStateFromJson(auxObject.value("soloMuteState").toObject());
284 :
285 0 : m_auxOutputParams.emplace(i, std::move(outParams));
286 0 : m_auxSoloMuteStatesMap.emplace(i, std::move(soloMuteState));
287 0 : }
288 :
289 0 : QJsonArray tracksArray = rootObj.value("tracks").toArray();
290 :
291 0 : for (const QJsonValue value : tracksArray) {
292 0 : QJsonObject trackObject = value.toObject();
293 :
294 : InstrumentTrackId id = {
295 0 : trackObject.value("partId").toString(),
296 0 : trackObject.value("instrumentId").toString()
297 0 : };
298 :
299 0 : AudioInputParams inParams = inputParamsFromJson(trackObject.value("in").toObject());
300 0 : AudioOutputParams outParams = outputParamsFromJson(trackObject.value("out").toObject());
301 :
302 0 : doCompatibilityConversions(inParams.resourceMeta);
303 :
304 0 : m_trackInputParamsMap.emplace(id, std::move(inParams));
305 0 : m_trackOutputParamsMap.emplace(id, std::move(outParams));
306 0 : }
307 :
308 0 : m_activeSoundProfileName = rootObj.value("activeSoundProfile").toString();
309 0 : if (m_activeSoundProfileName.empty()) {
310 0 : m_activeSoundProfileName = playbackConfig()->defaultProfileForNewProjects();
311 0 : } else if (m_activeSoundProfileName == playbackConfig()->compatMuseSoundsProfileName()) {
312 0 : m_activeSoundProfileName = playbackConfig()->museSoundsProfileName();
313 : }
314 :
315 0 : return make_ret(Ret::Code::Ok);
316 0 : }
317 :
318 0 : Ret ProjectAudioSettings::write(engraving::MscWriter& writer, notation::INotationSoloMuteStatePtr masterSoloMuteStatePtr)
319 : {
320 0 : QJsonObject rootObj;
321 0 : rootObj["master"] = outputParamsToJson(m_masterOutputParams);
322 :
323 0 : QJsonArray auxArray;
324 0 : for (const auto& pair : m_auxOutputParams) {
325 0 : auxArray.append(buildAuxObject(pair.first, pair.second));
326 : }
327 :
328 0 : rootObj["aux"] = auxArray;
329 :
330 0 : QJsonArray tracksArray;
331 0 : for (const auto& pair : m_trackInputParamsMap) {
332 0 : tracksArray.append(buildTrackObject(masterSoloMuteStatePtr, pair.first));
333 : }
334 :
335 0 : rootObj["tracks"] = tracksArray;
336 0 : rootObj["activeSoundProfile"] = m_activeSoundProfileName.toQString();
337 :
338 0 : QByteArray json = QJsonDocument(rootObj).toJson();
339 0 : writer.writeAudioSettingsJsonFile(ByteArray::fromQByteArrayNoCopy(json));
340 :
341 0 : return make_ret(Ret::Code::Ok);
342 0 : }
343 :
344 0 : void ProjectAudioSettings::makeDefault()
345 : {
346 0 : m_activeSoundProfileName = playbackConfig()->defaultProfileForNewProjects();
347 0 : }
348 :
349 0 : AudioInputParams ProjectAudioSettings::inputParamsFromJson(const QJsonObject& object) const
350 : {
351 0 : AudioInputParams result;
352 0 : result.resourceMeta = resourceMetaFromJson(object.value("resourceMeta").toObject());
353 0 : result.configuration = unitConfigFromJson(object.value("unitConfiguration").toObject());
354 :
355 0 : return result;
356 0 : }
357 :
358 0 : AudioOutputParams ProjectAudioSettings::outputParamsFromJson(const QJsonObject& object) const
359 : {
360 0 : AudioOutputParams result;
361 0 : result.fxChain = fxChainFromJson(object.value("fxChain").toObject());
362 0 : result.balance = object.value("balance").toVariant().toFloat();
363 0 : result.volume = object.value("volumeDb").toVariant().toFloat();
364 0 : result.auxSends = auxSendsFromJson(object.value("auxSends").toArray());
365 :
366 0 : return result;
367 0 : }
368 :
369 0 : IProjectAudioSettings::SoloMuteState ProjectAudioSettings::soloMuteStateFromJson(const QJsonObject& object) const
370 : {
371 0 : SoloMuteState result;
372 0 : result.mute = object.value("mute").toBool();
373 0 : result.solo = object.value("solo").toBool();
374 :
375 0 : return result;
376 : }
377 :
378 0 : AudioFxChain ProjectAudioSettings::fxChainFromJson(const QJsonObject& fxChainObject) const
379 : {
380 0 : AudioFxChain result;
381 :
382 0 : for (const QString& key : fxChainObject.keys()) {
383 0 : AudioFxParams params = fxParamsFromJson(fxChainObject.value(key).toObject());
384 0 : result.emplace(static_cast<AudioFxChainOrder>(key.toInt()), std::move(params));
385 0 : }
386 :
387 0 : return result;
388 0 : }
389 :
390 0 : AudioFxParams ProjectAudioSettings::fxParamsFromJson(const QJsonObject& object) const
391 : {
392 0 : AudioFxParams result;
393 0 : result.active = object.value("active").toBool();
394 0 : result.chainOrder = static_cast<AudioFxChainOrder>(object.value("chainOrder").toInt());
395 0 : result.resourceMeta = resourceMetaFromJson(object.value("resourceMeta").toObject());
396 0 : result.configuration = unitConfigFromJson(object.value("unitConfiguration").toObject());
397 0 : result.categories = audioFxCategoriesFromString(result.resourceMeta.attributeVal(vst::CATEGORIES_ATTRIBUTE));
398 :
399 0 : return result;
400 0 : }
401 :
402 0 : AuxSendsParams ProjectAudioSettings::auxSendsFromJson(const QJsonArray& objectList) const
403 : {
404 0 : AuxSendsParams result;
405 :
406 0 : for (const QJsonValue value : objectList) {
407 0 : AuxSendParams params = auxSendParamsFromJson(value.toObject());
408 0 : result.emplace_back(std::move(params));
409 0 : }
410 :
411 0 : return result;
412 0 : }
413 :
414 0 : AuxSendParams ProjectAudioSettings::auxSendParamsFromJson(const QJsonObject& object) const
415 : {
416 0 : AuxSendParams result;
417 0 : result.signalAmount = object.value("signalAmount").toVariant().toFloat();
418 0 : result.active = object.value("active").toBool();
419 :
420 0 : return result;
421 : }
422 :
423 0 : AudioResourceMeta ProjectAudioSettings::resourceMetaFromJson(const QJsonObject& object) const
424 : {
425 0 : AudioResourceMeta result;
426 0 : result.id = object.value("id").toString().toStdString();
427 0 : result.vendor = object.value("vendor").toString().toStdString();
428 0 : result.type = resourceTypeFromString(object.value("type").toString());
429 0 : result.attributes = attributesFromJson(object.value("attributes").toObject());
430 :
431 : // migrate legacy top-level hasNativeEditorSupport into attributes
432 0 : const QString nativeEditorKey = audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE.toQString();
433 0 : if (object.contains(nativeEditorKey) && !result.attributes.count(audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE)) {
434 0 : const bool b = object.value(nativeEditorKey).toBool();
435 0 : result.attributes.emplace(audio::HAS_NATIVE_EDITOR_SUPPORT_ATTRIBUTE, b ? u"true" : u"false");
436 : }
437 :
438 0 : return result;
439 0 : }
440 :
441 0 : AudioUnitConfig ProjectAudioSettings::unitConfigFromJson(const QJsonObject& object) const
442 : {
443 0 : AudioUnitConfig result;
444 :
445 0 : for (const QString& key : object.keys()) {
446 0 : QByteArray base = QByteArray::fromBase64(object.value(key).toString().toUtf8());
447 0 : result.emplace(key.toStdString(), base.toStdString());
448 0 : }
449 :
450 0 : return result;
451 0 : }
452 :
453 0 : AudioResourceAttributes ProjectAudioSettings::attributesFromJson(const QJsonObject& object) const
454 : {
455 0 : AudioResourceAttributes result;
456 :
457 0 : for (const QString& key : object.keys()) {
458 0 : result.emplace(String::fromQString(key), String::fromQString(object.value(key).toString()));
459 0 : }
460 :
461 0 : return result;
462 0 : }
463 :
464 0 : QJsonObject ProjectAudioSettings::inputParamsToJson(const AudioInputParams& params) const
465 : {
466 0 : QJsonObject result;
467 0 : result.insert("resourceMeta", resourceMetaToJson(params.resourceMeta));
468 0 : result.insert("unitConfiguration", unitConfigToJson(params.configuration));
469 :
470 0 : return result;
471 0 : }
472 :
473 0 : QJsonObject ProjectAudioSettings::outputParamsToJson(const AudioOutputParams& params) const
474 : {
475 0 : QJsonObject result;
476 0 : result.insert("fxChain", fxChainToJson(params.fxChain));
477 0 : result.insert("balance", params.balance.raw());
478 0 : result.insert("volumeDb", params.volume.raw());
479 :
480 0 : if (!params.auxSends.empty()) {
481 0 : result.insert("auxSends", auxSendsToJson(params.auxSends));
482 : }
483 :
484 0 : return result;
485 0 : }
486 :
487 0 : QJsonObject ProjectAudioSettings::soloMuteStateToJson(const SoloMuteState& state) const
488 : {
489 0 : QJsonObject result;
490 0 : result.insert("mute", state.mute);
491 0 : result.insert("solo", state.solo);
492 :
493 0 : return result;
494 0 : }
495 :
496 0 : QJsonObject ProjectAudioSettings::fxChainToJson(const AudioFxChain& fxChain) const
497 : {
498 0 : QJsonObject result;
499 :
500 0 : for (const auto& pair : fxChain) {
501 0 : result.insert(QString::number(static_cast<int>(pair.first)), fxParamsToJson(pair.second));
502 : }
503 :
504 0 : return result;
505 0 : }
506 :
507 0 : QJsonArray ProjectAudioSettings::auxSendsToJson(const AuxSendsParams& auxSends) const
508 : {
509 0 : QJsonArray result;
510 :
511 0 : for (const AuxSendParams& auxSend : auxSends) {
512 0 : result.push_back(auxSendParamsToJson(auxSend));
513 : }
514 :
515 0 : return result;
516 0 : }
517 :
518 0 : QJsonObject ProjectAudioSettings::auxSendParamsToJson(const AuxSendParams& auxParams) const
519 : {
520 0 : QJsonObject result;
521 0 : result.insert("active", auxParams.active);
522 0 : result.insert("signalAmount", auxParams.signalAmount);
523 :
524 0 : return result;
525 0 : }
526 :
527 0 : QJsonObject ProjectAudioSettings::fxParamsToJson(const AudioFxParams& fxParams) const
528 : {
529 0 : QJsonObject result;
530 0 : result.insert("active", fxParams.active);
531 0 : result.insert("chainOrder", static_cast<int>(fxParams.chainOrder));
532 0 : result.insert("resourceMeta", resourceMetaToJson(fxParams.resourceMeta));
533 0 : result.insert("unitConfiguration", unitConfigToJson(fxParams.configuration));
534 :
535 0 : return result;
536 0 : }
537 :
538 0 : QJsonObject ProjectAudioSettings::resourceMetaToJson(const AudioResourceMeta& meta) const
539 : {
540 0 : QJsonObject result;
541 0 : result.insert("id", QString::fromStdString(meta.id));
542 0 : result.insert("vendor", QString::fromStdString(meta.vendor));
543 0 : result.insert("type", audioResourceTypeToString(meta.type).toQString());
544 0 : result.insert("attributes", attributesToJson(meta.attributes));
545 :
546 0 : return result;
547 0 : }
548 :
549 0 : QJsonObject ProjectAudioSettings::unitConfigToJson(const AudioUnitConfig& config) const
550 : {
551 0 : QJsonObject result;
552 :
553 0 : for (const auto& pair : config) {
554 0 : QByteArray byteArray = QByteArray::fromRawData(pair.second.c_str(), static_cast<int>(pair.second.size()));
555 0 : result.insert(QString::fromStdString(pair.first), QString(byteArray.toBase64()));
556 0 : }
557 :
558 0 : return result;
559 0 : }
560 :
561 0 : QJsonObject ProjectAudioSettings::attributesToJson(const AudioResourceAttributes& attributes) const
562 : {
563 0 : QJsonObject result;
564 :
565 0 : for (const auto& pair : attributes) {
566 0 : result.insert(pair.first.toQString(), pair.second.toQString());
567 : }
568 :
569 0 : return result;
570 0 : }
571 :
572 0 : AudioSourceType ProjectAudioSettings::sourceTypeFromString(const QString& string) const
573 : {
574 0 : for (const auto& pair : SOURCE_TYPE_MAP) {
575 0 : if (pair.second == string) {
576 0 : return pair.first;
577 : }
578 : }
579 :
580 0 : return AudioSourceType::Undefined;
581 : }
582 :
583 0 : audioplugins::PluginType ProjectAudioSettings::resourceTypeFromString(const QString& string) const
584 : {
585 0 : for (const auto& pair : RESOURCE_TYPE_MAP) {
586 0 : if (pair.second == string) {
587 0 : return audio::resourceTypeName(pair.first);
588 : }
589 : }
590 :
591 0 : return audioplugins::PluginType();
592 : }
593 :
594 0 : QString ProjectAudioSettings::sourceTypeToString(const AudioSourceType& type) const
595 : {
596 0 : auto search = SOURCE_TYPE_MAP.find(type);
597 :
598 0 : if (search != SOURCE_TYPE_MAP.end()) {
599 0 : return search->second;
600 : }
601 :
602 0 : return SOURCE_TYPE_MAP.at(AudioSourceType::Undefined);
603 : }
604 :
605 0 : QJsonObject ProjectAudioSettings::buildAuxObject(aux_channel_idx_t index, const AudioOutputParams& params) const
606 : {
607 0 : QJsonObject result;
608 :
609 0 : result.insert("out", outputParamsToJson(params));
610 :
611 0 : auto soloMuteSearch = m_auxSoloMuteStatesMap.find(index);
612 0 : if (soloMuteSearch != m_auxSoloMuteStatesMap.end()) {
613 0 : result.insert("soloMuteState", soloMuteStateToJson(soloMuteSearch->second));
614 : }
615 :
616 0 : return result;
617 0 : }
618 :
619 0 : QJsonObject ProjectAudioSettings::buildTrackObject(notation::INotationSoloMuteStatePtr masterSoloMuteStatePtr,
620 : const InstrumentTrackId& id) const
621 : {
622 0 : QJsonObject result;
623 :
624 0 : result.insert("partId", id.partId.toQString());
625 0 : result.insert("instrumentId", id.instrumentId.toQString());
626 :
627 0 : auto inputParamsSearch = m_trackInputParamsMap.find(id);
628 0 : if (inputParamsSearch != m_trackInputParamsMap.end()) {
629 0 : result.insert("in", inputParamsToJson(inputParamsSearch->second));
630 : }
631 :
632 0 : auto outputParamsSearch = m_trackOutputParamsMap.find(id);
633 0 : if (outputParamsSearch != m_trackOutputParamsMap.end()) {
634 0 : result.insert("out", outputParamsToJson(outputParamsSearch->second));
635 : }
636 :
637 0 : if (masterSoloMuteStatePtr && masterSoloMuteStatePtr->trackSoloMuteStateExists(id)) {
638 0 : const SoloMuteState& soloMuteState = masterSoloMuteStatePtr->trackSoloMuteState(id);
639 0 : result.insert("soloMuteState", soloMuteStateToJson(soloMuteState));
640 : }
641 :
642 0 : return result;
643 0 : }
|