Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2024 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 :
23 : #ifndef MUSE_MPE_PLAYBACKSETUPDATA_H
24 : #define MUSE_MPE_PLAYBACKSETUPDATA_H
25 :
26 : #include <optional>
27 :
28 : #include "soundid.h"
29 :
30 : namespace muse::mpe {
31 : struct PlaybackSetupData
32 : {
33 : String id;
34 : StringList subCategories;
35 :
36 : std::optional<std::string> scoreId;
37 : std::optional<std::string> musicXmlSoundId;
38 :
39 : SoundCategory category = SoundCategory::Undefined;
40 :
41 : bool supportsSingleNoteDynamics = false;
42 :
43 77 : PlaybackSetupData() = default;
44 :
45 861 : PlaybackSetupData(SoundId id, SoundCategory category, SoundSubCategories&& soundSubCategories = {}, bool supportsSND = false)
46 861 : : id(soundIdToString(id)), category(category), supportsSingleNoteDynamics(supportsSND)
47 : {
48 1788 : for (SoundSubCategory subCategory : soundSubCategories) {
49 927 : subCategories.push_back(soundSubCategoryToString(subCategory));
50 : }
51 861 : }
52 :
53 0 : PlaybackSetupData(String id, SoundCategory category, StringList&& subCategories = {})
54 0 : : id(std::move(id)), subCategories(std::move(subCategories)), category(category)
55 0 : {}
56 :
57 30 : SoundId soundId() const
58 : {
59 30 : return soundIdFromString(id);
60 : }
61 :
62 0 : SoundSubCategories soundSubCategories() const
63 : {
64 0 : SoundSubCategories result;
65 0 : for (const String& subCategory : subCategories) {
66 0 : result.insert(soundSubCategoryFromString(subCategory));
67 : }
68 :
69 0 : return result;
70 0 : }
71 :
72 0 : bool isKnownSound() const
73 : {
74 0 : if (soundIdFromString(id) == SoundId::Unknown) {
75 0 : return false;
76 : }
77 :
78 0 : for (const String& subCategory : subCategories) {
79 0 : if (soundSubCategoryFromString(subCategory) == SoundSubCategory::Unknown) {
80 0 : return false;
81 : }
82 : }
83 :
84 0 : return true;
85 : }
86 :
87 0 : bool contains(const SoundSubCategory subcategory) const
88 : {
89 0 : return muse::contains(subCategories, soundSubCategoryToString(subcategory));
90 : }
91 :
92 19 : void add(const SoundSubCategory subcategory)
93 : {
94 19 : auto insertPos = std::find_if(subCategories.cbegin(), subCategories.cend(), [subcategory](const String& str) {
95 16 : SoundSubCategory existingSubCategory = soundSubCategoryFromString(str);
96 16 : return subcategory < existingSubCategory;
97 : });
98 :
99 19 : subCategories.insert(insertPos, soundSubCategoryToString(subcategory));
100 19 : }
101 :
102 14 : bool operator==(const PlaybackSetupData& other) const
103 : {
104 14 : return id == other.id
105 14 : && category == other.category
106 14 : && subCategories == other.subCategories
107 28 : && supportsSingleNoteDynamics == other.supportsSingleNoteDynamics;
108 : }
109 :
110 0 : bool operator<(const PlaybackSetupData& other) const
111 : {
112 0 : if (other.id > id) {
113 0 : return true;
114 0 : } else if (other.id == id) {
115 0 : if (other.category > category) {
116 0 : return true;
117 0 : } else if (other.category == category) {
118 0 : return other.subCategories > subCategories;
119 : }
120 : }
121 :
122 0 : return false;
123 : }
124 :
125 122 : bool isValid() const
126 : {
127 122 : if (category == SoundCategory::Undefined) {
128 76 : return false;
129 : }
130 :
131 46 : if (id.empty()) {
132 0 : return false;
133 : }
134 :
135 46 : if (id == ID_STRINGS.at(SoundId::Undefined)) {
136 0 : return false;
137 : }
138 :
139 46 : return true;
140 : }
141 :
142 184 : String toString() const
143 : {
144 184 : String result;
145 :
146 184 : if (!subCategories.empty()) {
147 368 : result = String(u"%1.%2.%3")
148 368 : .arg(soundCategoryToString(category))
149 184 : .arg(id)
150 368 : .arg(subCategories.join(u":"));
151 : } else {
152 0 : result = String(u"%1.%2")
153 0 : .arg(soundCategoryToString(category))
154 0 : .arg(id);
155 : }
156 :
157 184 : return result;
158 0 : }
159 :
160 0 : static PlaybackSetupData fromString(const String& str)
161 : {
162 0 : if (str.empty()) {
163 0 : return PlaybackSetupData();
164 : }
165 :
166 0 : StringList subStrList = str.split(u".");
167 :
168 0 : if (subStrList.size() < 2) {
169 0 : return PlaybackSetupData();
170 : }
171 :
172 0 : StringList subCategories;
173 0 : if (subStrList.size() == 3) {
174 0 : subCategories = subStrList.at(2).split(u":");
175 : }
176 :
177 : PlaybackSetupData result = {
178 0 : subStrList.at(1),
179 0 : soundCategoryFromString(subStrList.at(0)),
180 0 : std::move(subCategories)
181 0 : };
182 :
183 0 : return result;
184 0 : }
185 : };
186 :
187 : static const PlaybackSetupData GENERIC_SETUP_DATA = {
188 : SoundId::Last,
189 : SoundCategory::Last,
190 : { SoundSubCategory::Last }
191 : };
192 :
193 : static const String GENERIC_SETUP_DATA_STRING = GENERIC_SETUP_DATA.toString();
194 : }
195 :
196 : #endif // MUSE_MPE_PLAYBACKSETUPDATA_H
|