Skip to content

Commit 8b3f6de

Browse files
committed
Dynamic Range Control, Fix multi-message parsing
1 parent dc8c746 commit 8b3f6de

9 files changed

Lines changed: 247 additions & 140 deletions

File tree

lib/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ add_library(${PROJECT_NAME}
1111
${HDR}
1212
)
1313

14-
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
14+
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
1515

1616
target_include_directories(${PROJECT_NAME}
1717
PUBLIC

lib/include/Denon/denon.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ enum class Source
2424
enum class Surround
2525
{
2626
Direct, PureDirect, Stereo, Standard,
27-
DolbyDigital, DtsSurround,
27+
DolbyDigital, DolbyDigitalNeuralX, DtsSurround,
2828
Neural, WideScreen, _7ChStereo,
2929
SuperStadium, RockArena, JazzClub, Classic, MonoMovie, Matrix, VideoGame
3030
};
@@ -59,6 +59,11 @@ enum class SoundMode
5959
Pure, Music, Movie, Game
6060
};
6161

62+
enum class DrcMode
63+
{
64+
Auto, Low, Mid, Hi, Off
65+
};
66+
6267
/// Interface for responses
6368
class Response
6469
{
@@ -73,6 +78,7 @@ class Response
7378
virtual void OnBluetooth(bool on) = 0;
7479
virtual void OnDynamicEq(bool on) = 0;
7580
virtual void OnDynamicVolume(DynamicVolume v) = 0;
81+
virtual void OnDynamicRangeControl(DrcMode v) = 0;
7682
virtual void OnCinemaEq(bool on) = 0;
7783
virtual void OnMultiEq(Denon::RoomEqualizer e) = 0;
7884
virtual void OnSpeaker(Denon::Speaker speaker, Denon::SpeakerType type) = 0;

lib/include/Denon/serial.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Command
3939
void RoomEq(RoomEqualizer e); // Superseded by MultiEq() ?
4040
void DynamicEq(bool on);
4141
void DynamicVolume(DynamicVolume v);
42+
void DynamicRangeControl(DrcMode v);
4243
void CinemaEq(bool on);
4344
void MultiEq(RoomEqualizer e);
4445
void EcoMode(EcoMode e);

lib/serial.cc

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include <iostream>
55
#include <functional>
66
#include <map>
7+
#include <ranges>
78
#include <sstream>
9+
#include <string_view>
810

911

1012
namespace Denon {
@@ -27,6 +29,7 @@ const std::map<std::string, Surround> gSurround = {
2729
{"STEREO", Surround::Stereo},
2830
{"STANDARD", Surround::Standard},
2931
{"DOLBY AUDIO-DD+DSUR", Surround::DolbyDigital},
32+
{"DOLBY AUDIO-DD+ +NEURAL:X", Surround::DolbyDigitalNeuralX},
3033
{"M CH IN+DSUR", Surround::DtsSurround},
3134
};
3235

@@ -87,6 +90,16 @@ const std::map<std::string, SoundMode> gSoundMode = {
8790
};
8891

8992

93+
const std::map<std::string, DrcMode> gDynamicRangeControl = {
94+
{"AUTO", DrcMode::Auto},
95+
{"LOW", DrcMode::Low},
96+
{"MID", DrcMode::Mid},
97+
{"HI", DrcMode::Hi},
98+
{"OFF", DrcMode::Off},
99+
};
100+
101+
102+
90103
template<typename Enum>
91104
std::string lu(const std::map<std::string, Enum>& lut, Enum v)
92105
{
@@ -109,13 +122,12 @@ std::ostream& operator<<(std::ostream& os, Surround s)
109122
}
110123

111124

112-
void ParseResponse(std::string_view line, Response& response)
125+
void ParseResponse(std::string_view lines, Response& response)
113126
{
114-
if(line.size() < 3)
127+
if(lines.size() < 3)
115128
return;
116129

117-
//std::string cmd = str.substr(0,2);
118-
std::string param = std::string(line.substr(2, line.size()-3));
130+
std::string param;
119131

120132
const std::map<std::string, std::function<void(void)>> handlers = {
121133
{"BT" , [&]()
@@ -133,7 +145,7 @@ void ParseResponse(std::string_view line, Response& response)
133145
{"MU" , [&](){ response.OnMute(param == "ON"); }},
134146
{"MV", [&]()
135147
{
136-
if(!startswith(line, "MVMAX"))
148+
if(!startswith(param, "MAX"))
137149
{
138150
int vol = std::stoi(param);
139151
if(vol > 100)
@@ -153,7 +165,7 @@ void ParseResponse(std::string_view line, Response& response)
153165
}},
154166
{"SS", [&]()
155167
{
156-
if(line == "SSINFAISFSV")
168+
if(param == "INFAISFSV")
157169
{
158170
std::string sr = param.substr(10);
159171
if(sr == "441")
@@ -180,6 +192,12 @@ void ParseResponse(std::string_view line, Response& response)
180192
{
181193
response.OnCinemaEq(param == "CINEMA EQ.ON");
182194
}
195+
else if(startswith(param, "DRC"))
196+
{
197+
auto val = param.substr(4);
198+
if(gDynamicRangeControl.count(val))
199+
response.OnDynamicRangeControl(gDynamicRangeControl.at(val));
200+
}
183201
if(startswith(param, "LFE"))
184202
{
185203
int val = std::stoi(param.substr(4));
@@ -197,8 +215,8 @@ void ParseResponse(std::string_view line, Response& response)
197215
}
198216
else if(startswith(param, "ROOM"))
199217
{
200-
std::string_view eq = line.substr(10);
201-
//std::cout << "ROOM EQ : '" << eq << "'\n";
218+
std::string_view eq = param.substr(8);
219+
std::cout << "ROOM EQ : '" << eq << "'\n";
202220
}
203221
else if(startswith(param, "DYNEQ"))
204222
{
@@ -211,22 +229,41 @@ void ParseResponse(std::string_view line, Response& response)
211229
if(gDynamicVolume.count(val))
212230
response.OnDynamicVolume(gDynamicVolume.at(val));
213231
}
232+
else if(startswith(param, "MODE"))
233+
{
234+
auto val = param.substr(std::string_view("MODE").size() + 1);
235+
std::cout << "MODE : '" << val << "'\n";
236+
}
214237
else if(startswith(param, "MULTEQ:"))
215238
{
216239
auto val = param.substr(7);
217240
if(gRoomEq.count(val))
218241
response.OnMultiEq(gRoomEq.at(val));
219242
}
243+
else if(startswith(param, "TONE"))
244+
{
245+
auto val = param.substr(std::string_view("TONE").size() + 1);
246+
}
220247
}},
221248
{"ZM", [&](){ response.OnPower(param == "ON"); }},
222249
};
223250

224-
for(auto& h: handlers)
251+
std::string cmd;
252+
for(auto line: lines | std::views::split('\r'))
225253
{
226-
if(startswith(line, h.first))
254+
for (auto cmd_r : line | std::views::split(','))
227255
{
228-
h.second();
229-
break;
256+
if(cmd_r.size() < 3) continue;
257+
cmd.assign(std::begin(cmd_r), std::end(cmd_r)); // cmd_r is contiguous, but the view-types don't know that.
258+
param = cmd.substr(2);
259+
for(auto& h: handlers)
260+
{
261+
if(startswith(cmd, h.first))
262+
{
263+
h.second();
264+
break;
265+
}
266+
}
230267
}
231268
}
232269
}
@@ -252,6 +289,7 @@ void Command::RequestStatus()
252289
"PSDYNEQ ?\r"
253290
"PSDYNVOL ?\r"
254291
"PSCINEMA EQ. ?\r"
292+
"PSMODE: ?\r"
255293
"PSMULTEQ: ?\r"
256294
"ECO?\r"
257295
"SSSMG ?\r"
@@ -308,6 +346,12 @@ void Command::DynamicVolume(Denon::DynamicVolume v)
308346
}
309347

310348

349+
void Command::DynamicRangeControl(DrcMode v)
350+
{
351+
pConn->Send("PSDRC " + lu(gDynamicRangeControl, v) + "\r");
352+
}
353+
354+
311355
void Command::CinemaEq(bool v)
312356
{
313357
pConn->Send(v ? "PSCINEMA EQ.ON\r" : "PSCINEMA EQ.OFF\r");
@@ -328,8 +372,12 @@ void Command::EcoMode(Denon::EcoMode e)
328372

329373
void Command::SoundMode(Denon::SoundMode m)
330374
{
331-
// This doesn't seem to do it:
332-
//pConn->Send("SSSMG " + lu(gSoundMode, m) + "\r");
375+
// This doesn't seem to do it, neither with ':' or without ' '
376+
/*pConn->Send("SSSMG" + lu(gSoundMode, m) + "\r");
377+
pConn->Send("SSSMG:" + lu(gSoundMode, m) + "\r");
378+
pConn->Send("SSSMG " + lu(gSoundMode, m) + "\r");
379+
pConn->Send("SSSMG: " + lu(gSoundMode, m) + "\r");
380+
*/
333381
}
334382

335383

qtui/MainWindow.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ void MainWindow::SetupCommandConnections()
113113
connect(ui.cDynVol, qOverload<int>(&QComboBox::currentIndexChanged), [&](int e){
114114
command.DynamicVolume(static_cast<Denon::DynamicVolume>(e));
115115
});
116+
connect(ui.cDRC, qOverload<int>(&QComboBox::currentIndexChanged), [&](int e){
117+
command.DynamicRangeControl(static_cast<Denon::DrcMode>(e));
118+
});
116119
connect(ui.cCinemaEq, &QCheckBox::clicked, [&](bool b){
117120
command.CinemaEq(b);
118121
});
@@ -338,9 +341,9 @@ void MainWindow::onResponse()
338341
{
339342
Denon::ParseResponse(msg, *this);
340343
}
341-
catch(std::exception& e)
344+
catch(const std::exception& e)
342345
{
343-
std::throw_with_nested(std::runtime_error("Serial Parsing of:" + std::string(msg) + "\n"));
346+
std::throw_with_nested(std::runtime_error("Serial Parsing of:" + std::string(msg) + "\n" + e.what()));
344347
}
345348
}
346349

@@ -436,6 +439,13 @@ void MainWindow::OnDynamicVolume(Denon::DynamicVolume v)
436439
}
437440

438441

442+
void MainWindow::OnDynamicRangeControl(Denon::DrcMode v)
443+
{
444+
SignalBlocker block(ui.cDRC);
445+
ui.cDRC->setCurrentIndex((int)v);
446+
}
447+
448+
439449
void MainWindow::OnCinemaEq(bool v)
440450
{
441451
SignalBlocker block(ui.cCinemaEq);

qtui/MainWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ private slots:
6868
void OnBluetooth(bool on) override;
6969
void OnDynamicEq(bool on) override;
7070
void OnDynamicVolume(Denon::DynamicVolume v) override;
71+
void OnDynamicRangeControl(Denon::DrcMode v) override;
7172
void OnCinemaEq(bool on) override;
7273
void OnMultiEq(Denon::RoomEqualizer e) override;
7374
void OnSpeaker(Denon::Speaker speaker, Denon::SpeakerType type) override;

qtui/SsdpClient.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void SsdpClient::onRead()
4949
}
5050
catch(std::exception& e)
5151
{
52-
std::throw_with_nested(std::runtime_error("Ssdp Parse error"));
52+
std::throw_with_nested(std::runtime_error("Ssdp Parse error: "sv + e.what()));
5353
}
5454
}
5555
};

qtui/UpnpEvents.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void UpnpEvents::onCbRead()
121121
}
122122
catch(std::exception& e)
123123
{
124-
std::throw_with_nested(std::runtime_error("UpnpEvents.onCbRead: Parsing failed"));
124+
std::throw_with_nested(std::runtime_error("UpnpEvents.onCbRead, parsing failed: "sv + e.what()));
125125
}
126126

127127
Denon::Http::Response resp;

0 commit comments

Comments
 (0)