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 :
23 : #include "mixerpanelcontextmenumodel.h"
24 :
25 : #include "types/translatablestring.h"
26 :
27 : #include "playback/playbackcommands.h"
28 :
29 : using namespace mu;
30 : using namespace mu::playback;
31 : using namespace muse;
32 : using namespace muse::ui;
33 : using namespace muse::uicomponents;
34 : using namespace muse::audio;
35 :
36 : static const QString VIEW_MENU_ID("view-menu");
37 :
38 0 : static TranslatableString mixerSectionTitle(MixerSectionType type)
39 : {
40 0 : switch (type) {
41 0 : case MixerSectionType::Labels: return TranslatableString("playback", "Labels");
42 0 : case MixerSectionType::Sound: return TranslatableString("playback", "Sound");
43 0 : case MixerSectionType::AudioFX: return TranslatableString("playback", "Audio FX");
44 0 : case MixerSectionType::Balance: return TranslatableString("playback", "Pan");
45 0 : case MixerSectionType::Volume: return TranslatableString("playback", "Volume");
46 0 : case MixerSectionType::Fader: return TranslatableString("playback", "Fader");
47 0 : case MixerSectionType::MuteAndSolo: return TranslatableString("playback", "Mute and solo");
48 0 : case MixerSectionType::Title: return TranslatableString("playback", "Name");
49 0 : case MixerSectionType::Unknown: break;
50 : }
51 :
52 0 : return {};
53 : }
54 :
55 0 : MixerPanelContextMenuModel::MixerPanelContextMenuModel(QObject* parent)
56 0 : : AbstractMenuModel(parent)
57 : {
58 0 : }
59 :
60 0 : bool MixerPanelContextMenuModel::labelsSectionVisible() const
61 : {
62 0 : return isSectionVisible(MixerSectionType::Labels);
63 : }
64 :
65 0 : bool MixerPanelContextMenuModel::soundSectionVisible() const
66 : {
67 0 : return isSectionVisible(MixerSectionType::Sound);
68 : }
69 :
70 0 : bool MixerPanelContextMenuModel::audioFxSectionVisible() const
71 : {
72 0 : return isSectionVisible(MixerSectionType::AudioFX);
73 : }
74 :
75 0 : bool MixerPanelContextMenuModel::auxSendsSectionVisible() const
76 : {
77 0 : for (aux_channel_idx_t idx = 0; idx < AUX_CHANNEL_NUM; ++idx) {
78 0 : if (configuration()->isAuxSendVisible(idx)) {
79 0 : return true;
80 : }
81 : }
82 :
83 0 : return false;
84 : }
85 :
86 0 : bool MixerPanelContextMenuModel::balanceSectionVisible() const
87 : {
88 0 : return isSectionVisible(MixerSectionType::Balance);
89 : }
90 :
91 0 : bool MixerPanelContextMenuModel::volumeSectionVisible() const
92 : {
93 0 : return isSectionVisible(MixerSectionType::Volume);
94 : }
95 :
96 0 : bool MixerPanelContextMenuModel::faderSectionVisible() const
97 : {
98 0 : return isSectionVisible(MixerSectionType::Fader);
99 : }
100 :
101 0 : bool MixerPanelContextMenuModel::muteAndSoloSectionVisible() const
102 : {
103 0 : return isSectionVisible(MixerSectionType::MuteAndSolo);
104 : }
105 :
106 0 : bool MixerPanelContextMenuModel::titleSectionVisible() const
107 : {
108 0 : return isSectionVisible(MixerSectionType::Title);
109 : }
110 :
111 0 : void MixerPanelContextMenuModel::load()
112 : {
113 0 : AbstractMenuModel::load();
114 :
115 0 : configuration()->isAuxSendVisibleChanged().onReceive(this, [this](aux_channel_idx_t auxSendIndex, bool newVisibilityValue) {
116 0 : auto query = rcommand::make_query(TOGGLE_AUX_SEND_COMMAND, { { "auxsend-index", Val(auxSendIndex) } });
117 0 : setViewMenuItemChecked(query, newVisibilityValue);
118 :
119 0 : emit auxSendsSectionVisibleChanged();
120 0 : });
121 :
122 0 : configuration()->isAuxChannelVisibleChanged().onReceive(this, [this](aux_channel_idx_t auxChannelIndex, bool newVisibilityValue) {
123 0 : auto query = rcommand::make_query(TOGGLE_AUX_CHANNEL_COMMAND, { { "auxchannel-index", Val(auxChannelIndex) } });
124 0 : setViewMenuItemChecked(query, newVisibilityValue);
125 0 : });
126 :
127 0 : configuration()->isMixerSectionVisibleChanged().onReceive(this, [this](MixerSectionType sectionType, bool newVisibilityValue) {
128 0 : auto query = rcommand::make_query(TOGGLE_MIXER_SECTION_COMMAND, { { "section", Val(str_conv(sectionType)) } });
129 0 : setViewMenuItemChecked(query, newVisibilityValue);
130 :
131 0 : emitMixerSectionVisibilityChanged(sectionType);
132 0 : });
133 :
134 : MenuItemList viewMenuItems {
135 0 : buildSectionVisibleItem(MixerSectionType::Labels),
136 0 : buildSectionVisibleItem(MixerSectionType::Sound),
137 0 : buildSectionVisibleItem(MixerSectionType::AudioFX),
138 0 : };
139 :
140 0 : for (aux_channel_idx_t idx = 0; idx < AUX_CHANNEL_NUM; ++idx) {
141 0 : viewMenuItems.push_back(buildAuxSendVisibleItem(idx));
142 : }
143 :
144 0 : for (aux_channel_idx_t idx = 0; idx < AUX_CHANNEL_NUM; ++idx) {
145 0 : viewMenuItems.push_back(buildAuxChannelVisibleItem(idx));
146 : }
147 :
148 0 : viewMenuItems.push_back(buildSectionVisibleItem(MixerSectionType::Balance));
149 0 : viewMenuItems.push_back(buildSectionVisibleItem(MixerSectionType::Volume));
150 0 : viewMenuItems.push_back(buildSectionVisibleItem(MixerSectionType::Fader));
151 0 : viewMenuItems.push_back(buildSectionVisibleItem(MixerSectionType::MuteAndSolo));
152 0 : viewMenuItems.push_back(buildSectionVisibleItem(MixerSectionType::Title));
153 :
154 : MenuItemList items {
155 0 : makeMenuItem(OPEN_PLAYBACK_SETUP_COMMAND),
156 0 : makeMenu(TranslatableString("playback", "View"), viewMenuItems, VIEW_MENU_ID)
157 0 : };
158 :
159 0 : setItems(items);
160 0 : }
161 :
162 0 : bool MixerPanelContextMenuModel::isSectionVisible(MixerSectionType sectionType) const
163 : {
164 0 : return configuration()->isMixerSectionVisible(sectionType);
165 : }
166 :
167 0 : MenuItem* MixerPanelContextMenuModel::buildSectionVisibleItem(MixerSectionType sectionType)
168 : {
169 0 : MenuItem* item = new MenuItem(this);
170 0 : item->setTitle(mixerSectionTitle(sectionType));
171 0 : item->setCheckable(true);
172 0 : item->setChecked(isSectionVisible(sectionType));
173 0 : item->setCommandQuery(rcommand::make_query(TOGGLE_MIXER_SECTION_COMMAND, { { "section", Val(str_conv(sectionType)) } }));
174 0 : return item;
175 0 : }
176 :
177 0 : MenuItem* MixerPanelContextMenuModel::buildAuxSendVisibleItem(aux_channel_idx_t index)
178 : {
179 0 : MenuItem* item = new MenuItem(this);
180 0 : item->setTitle(TranslatableString("playback", String("Aux send %1").arg(index + 1)));
181 0 : item->setCheckable(true);
182 0 : item->setChecked(configuration()->isAuxSendVisible(index));
183 0 : item->setCommandQuery(rcommand::make_query(TOGGLE_AUX_SEND_COMMAND, { { "auxsend-index", Val(index) } }));
184 0 : return item;
185 0 : }
186 :
187 0 : MenuItem* MixerPanelContextMenuModel::buildAuxChannelVisibleItem(aux_channel_idx_t index)
188 : {
189 0 : MenuItem* item = new MenuItem(this);
190 0 : item->setTitle(TranslatableString("playback", String("Aux channel %1").arg(index + 1)));
191 0 : item->setCheckable(true);
192 0 : item->setChecked(configuration()->isAuxChannelVisible(index));
193 0 : item->setCommandQuery(rcommand::make_query(TOGGLE_AUX_CHANNEL_COMMAND, { { "auxchannel-index", Val(index) } }));
194 0 : return item;
195 0 : }
196 :
197 0 : void MixerPanelContextMenuModel::setViewMenuItemChecked(const muse::rcommand::CommandQuery& query, bool checked)
198 : {
199 0 : MenuItem& viewMenu = findMenu(VIEW_MENU_ID);
200 :
201 0 : for (MenuItem* item : viewMenu.subitems()) {
202 0 : if (item->commandQuery() == query) {
203 0 : item->setChecked(checked);
204 0 : return;
205 : }
206 0 : }
207 : }
208 :
209 0 : void MixerPanelContextMenuModel::emitMixerSectionVisibilityChanged(MixerSectionType sectionType)
210 : {
211 0 : switch (sectionType) {
212 0 : case MixerSectionType::Labels:
213 0 : emit labelsSectionVisibleChanged();
214 0 : break;
215 0 : case MixerSectionType::Sound:
216 0 : emit soundSectionVisibleChanged();
217 0 : break;
218 0 : case MixerSectionType::AudioFX:
219 0 : emit audioFxSectionVisibleChanged();
220 0 : break;
221 0 : case MixerSectionType::Balance:
222 0 : emit balanceSectionVisibleChanged();
223 0 : break;
224 0 : case MixerSectionType::Volume:
225 0 : emit volumeSectionVisibleChanged();
226 0 : break;
227 0 : case MixerSectionType::Fader:
228 0 : emit faderSectionVisibleChanged();
229 0 : break;
230 0 : case MixerSectionType::MuteAndSolo:
231 0 : emit muteAndSoloSectionVisibleChanged();
232 0 : break;
233 0 : case MixerSectionType::Title:
234 0 : emit titleSectionVisibleChanged();
235 0 : break;
236 0 : case MixerSectionType::Unknown:
237 0 : break;
238 : }
239 0 : }
|