openMSX
ImGuiSoundChip.cc
Go to the documentation of this file.
1#include "ImGuiSoundChip.hh"
2
3#include "ImGuiCpp.hh"
4#include "ImGuiManager.hh"
5#include "ImGuiUtils.hh"
6
7#include "MSXMixer.hh"
8#include "MSXMotherBoard.hh"
9#include "SoundDevice.hh"
10#include "StringSetting.hh"
11
12#include <imgui.h>
13
14using namespace std::literals;
15
16
17namespace openmsx {
18
19void ImGuiSoundChip::save(ImGuiTextBuffer& buf)
20{
22 for (const auto& [name, enabled] : channels) {
23 buf.appendf("showChannels.%s=%d\n", name.c_str(), enabled);
24 }
25}
26
27void ImGuiSoundChip::loadLine(std::string_view name, zstring_view value)
28{
29 if (loadOnePersistent(name, value, *this, persistentElements)) {
30 // already handled
31 } else if (name.starts_with("showChannels.")) {
32 channels[std::string(name.substr(13))] = StringOp::stringToBool(value);
33 }
34}
35
37{
38 if (!motherBoard) return;
40 showChipSettings(*motherBoard);
41 }
42
43 // Show sound chip channel settings
44 auto& msxMixer = motherBoard->getMSXMixer();
45 auto& infos = msxMixer.getDeviceInfos();
46 for (const auto& info : infos) {
47 const auto& name = info.device->getName();
48 auto [it, inserted] = channels.try_emplace(name, false);
49 auto& enabled = it->second;
50 if (enabled) {
51 showChannelSettings(*motherBoard, name, &enabled);
52 }
53 }
54}
55
56static bool anySpecialChannelSettings(const MSXMixer::SoundDeviceInfo& info)
57{
58 for (const auto& channel : info.channelSettings) {
59 if (channel.mute->getBoolean()) return true;
60 if (!channel.record->getString().empty()) return true;
61 }
62 return false;
63}
64
65void ImGuiSoundChip::showChipSettings(MSXMotherBoard& motherBoard)
66{
67 auto restoreDefaultPopup = [](const char* label, Setting& setting) {
69 if (ImGui::Button(label)) {
70 setting.setValue(setting.getDefaultValue());
71 ImGui::CloseCurrentPopup();
72 }
73 });
74 };
75
76 im::Window("Sound chip settings", &showSoundChipSettings, [&]{
77 auto& msxMixer = motherBoard.getMSXMixer();
78 auto& infos = msxMixer.getDeviceInfos(); // TODO sort on name
79 im::Table("table", narrow<int>(infos.size()), ImGuiTableFlags_ScrollX, [&]{
80 for (auto& info : infos) {
81 if (ImGui::TableNextColumn()) {
82 auto& device = *info.device;
83 ImGui::TextUnformatted(device.getName());
84 simpleToolTip(device.getDescription());
85 }
86 }
87 for (auto& info : infos) {
88 if (ImGui::TableNextColumn()) {
89 auto& volumeSetting = *info.volumeSetting;
90 int volume = volumeSetting.getInt();
91 int min = volumeSetting.getMinValue();
92 int max = volumeSetting.getMaxValue();
93 ImGui::TextUnformatted("volume"sv);
94 std::string id = "##volume-" + info.device->getName();
95 if (ImGui::VSliderInt(id.c_str(), ImVec2(18, 120), &volume, min, max)) {
96 volumeSetting.setInt(volume);
97 }
98 restoreDefaultPopup("Set default", volumeSetting);
99 }
100 }
101 for (auto& info : infos) {
102 if (ImGui::TableNextColumn()) {
103 auto& balanceSetting = *info.balanceSetting;
104 int balance = balanceSetting.getInt();
105 int min = balanceSetting.getMinValue();
106 int max = balanceSetting.getMaxValue();
107 ImGui::TextUnformatted("balance"sv);
108 std::string id = "##balance-" + info.device->getName();
109 if (ImGui::SliderInt(id.c_str(), &balance, min, max)) {
110 balanceSetting.setInt(balance);
111 }
112 restoreDefaultPopup("Set center", balanceSetting);
113 }
114 }
115 for (auto& info : infos) {
116 if (ImGui::TableNextColumn()) {
117 bool special = anySpecialChannelSettings(info);
118 if (special) {
119 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, getColor(imColor::YELLOW));
120 }
121 im::StyleColor(special, ImGuiCol_Text, getColor(imColor::BLACK), []{
122 ImGui::TextUnformatted("channels"sv);
123 });
124 const auto& name = info.device->getName();
125 std::string id = "##channels-" + name;
126 auto [it, inserted] = channels.try_emplace(name, false);
127 auto& enabled = it->second;
128 ImGui::Checkbox(id.c_str(), &enabled);
129 }
130 }
131 });
132 });
133}
134
135void ImGuiSoundChip::showChannelSettings(MSXMotherBoard& motherBoard, const std::string& name, bool* enabled)
136{
137 auto& msxMixer = motherBoard.getMSXMixer();
138 auto* info = msxMixer.findDeviceInfo(name);
139 if (!info) return;
140
141 std::string label = name + " channel setting";
142 im::Window(label.c_str(), enabled, [&]{
143 const auto& hotKey = manager.getReactor().getHotKey();
144 im::Table("table", 3, [&]{
145 im::ID_for_range(info->channelSettings.size(), [&](int i) {
146 auto& channel = info->channelSettings[i];
147 if (ImGui::TableNextColumn()) {
148 ImGui::StrCat("channel ", i);
149 }
150 if (ImGui::TableNextColumn()) {
151 Checkbox(hotKey, "mute", *channel.mute);
152 }
153 if (ImGui::TableNextColumn()) {
154 InputText("record", *channel.record);
155 }
156 });
157 });
158 });
159}
160
161} // namespace openmsx
BaseSetting * setting
void paint(MSXMotherBoard *motherBoard) override
static constexpr auto persistentElements
void save(ImGuiTextBuffer &buf) override
void loadLine(std::string_view name, zstring_view value) override
const auto & getDeviceInfos() const
Definition MSXMixer.hh:140
const std::string & getName() const
Get the unique name that identifies this sound device.
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
void TextUnformatted(const std::string &str)
Definition ImGuiUtils.hh:24
bool stringToBool(string_view str)
Definition StringOp.cc:16
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition gl_vec.hh:302
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition gl_vec.hh:320
void Table(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width, std::invocable<> auto next)
Definition ImGuiCpp.hh:479
void Window(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:63
void PopupContextItem(const char *str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:445
void StyleColor(ImGuiCol idx1, ImVec4 col1, ImGuiCol idx2, ImVec4 col2, std::invocable<> auto next)
Definition ImGuiCpp.hh:162
This file implemented 3 utility functions:
Definition Autofire.cc:11
bool loadOnePersistent(std::string_view name, zstring_view value, C &c, const std::tuple< Elements... > &tup)
void savePersistent(ImGuiTextBuffer &buf, C &c, const std::tuple< Elements... > &tup)
ImU32 getColor(imColor col)
std::unique_ptr< IntegerSetting > balanceSetting
Definition MSXMixer.hh:46
std::unique_ptr< IntegerSetting > volumeSetting
Definition MSXMixer.hh:45