@@ -483,6 +483,11 @@ namespace platf::audio {
|
|||||||
|
|
||||||
// Check if the default audio device has changed
|
// Check if the default audio device has changed
|
||||||
if (endpt_notification.check_default_render_device_changed()) {
|
if (endpt_notification.check_default_render_device_changed()) {
|
||||||
|
// Invoke the audio_control_t's callback if it wants one
|
||||||
|
if (default_endpt_changed_cb) {
|
||||||
|
(*default_endpt_changed_cb)();
|
||||||
|
}
|
||||||
|
|
||||||
// Reinitialize to pick up the new default device
|
// Reinitialize to pick up the new default device
|
||||||
return capture_e::reinit;
|
return capture_e::reinit;
|
||||||
}
|
}
|
||||||
@@ -555,6 +560,8 @@ namespace platf::audio {
|
|||||||
audio_capture_t audio_capture;
|
audio_capture_t audio_capture;
|
||||||
|
|
||||||
audio_notification_t endpt_notification;
|
audio_notification_t endpt_notification;
|
||||||
|
std::optional<std::function<void()>> default_endpt_changed_cb;
|
||||||
|
|
||||||
REFERENCE_TIME default_latency_ms;
|
REFERENCE_TIME default_latency_ms;
|
||||||
|
|
||||||
util::buffer_t<std::int16_t> sample_buf;
|
util::buffer_t<std::int16_t> sample_buf;
|
||||||
@@ -667,6 +674,34 @@ namespace platf::audio {
|
|||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets information encoded in the raw sink name
|
||||||
|
*
|
||||||
|
* @param sink The raw sink name
|
||||||
|
*
|
||||||
|
* @return A pair of type and the real sink name
|
||||||
|
*/
|
||||||
|
std::pair<format_t::type_e, std::string_view>
|
||||||
|
get_sink_info(const std::string &sink) {
|
||||||
|
std::string_view sv { sink.c_str(), sink.size() };
|
||||||
|
|
||||||
|
// sink format:
|
||||||
|
// [virtual-(format name)]device_id
|
||||||
|
auto prefix = "virtual-"sv;
|
||||||
|
if (sv.find(prefix) == 0) {
|
||||||
|
sv = sv.substr(prefix.size(), sv.size() - prefix.size());
|
||||||
|
|
||||||
|
for (auto &format : formats) {
|
||||||
|
auto &name = format.name;
|
||||||
|
if (sv.find(name) == 0) {
|
||||||
|
return std::make_pair(format.type, sv.substr(name.size(), sv.size() - name.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(format_t::none, sv);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<mic_t>
|
std::unique_ptr<mic_t>
|
||||||
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override {
|
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override {
|
||||||
auto mic = std::make_unique<mic_wasapi_t>();
|
auto mic = std::make_unique<mic_wasapi_t>();
|
||||||
@@ -675,6 +710,15 @@ namespace platf::audio {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a virtual sink, set a callback that will change the sink back if it's changed
|
||||||
|
auto sink_info = get_sink_info(assigned_sink);
|
||||||
|
if (sink_info.first != format_t::none) {
|
||||||
|
mic->default_endpt_changed_cb = [this] {
|
||||||
|
BOOST_LOG(info) << "Resetting sink to ["sv << assigned_sink << "] after default changed";
|
||||||
|
set_sink(assigned_sink);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return mic;
|
return mic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,30 +732,12 @@ namespace platf::audio {
|
|||||||
*/
|
*/
|
||||||
std::optional<std::wstring>
|
std::optional<std::wstring>
|
||||||
set_format(const std::string &sink) {
|
set_format(const std::string &sink) {
|
||||||
std::string_view sv { sink.c_str(), sink.size() };
|
auto sink_info = get_sink_info(sink);
|
||||||
|
|
||||||
format_t::type_e type = format_t::none;
|
|
||||||
// sink format:
|
|
||||||
// [virtual-(format name)]device_id
|
|
||||||
auto prefix = "virtual-"sv;
|
|
||||||
if (sv.find(prefix) == 0) {
|
|
||||||
sv = sv.substr(prefix.size(), sv.size() - prefix.size());
|
|
||||||
|
|
||||||
for (auto &format : formats) {
|
|
||||||
auto &name = format.name;
|
|
||||||
if (sv.find(name) == 0) {
|
|
||||||
type = format.type;
|
|
||||||
sv = sv.substr(name.size(), sv.size() - name.size());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the sink isn't a device name, we'll assume it's a device ID
|
// If the sink isn't a device name, we'll assume it's a device ID
|
||||||
auto wstring_device_id = find_device_id_by_name(sink).value_or(converter.from_bytes(sv.data()));
|
auto wstring_device_id = find_device_id_by_name(sink).value_or(converter.from_bytes(sink_info.second.data()));
|
||||||
|
|
||||||
if (type == format_t::none) {
|
if (sink_info.first == format_t::none) {
|
||||||
// wstring_device_id does not contain virtual-(format name)
|
// wstring_device_id does not contain virtual-(format name)
|
||||||
// It's a simple deviceId, just pass it back
|
// It's a simple deviceId, just pass it back
|
||||||
return std::make_optional(std::move(wstring_device_id));
|
return std::make_optional(std::move(wstring_device_id));
|
||||||
@@ -725,14 +751,14 @@ namespace platf::audio {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_wave_format(wave_format, formats[(int) type - 1]);
|
set_wave_format(wave_format, formats[(int) sink_info.first - 1]);
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE p {};
|
WAVEFORMATEXTENSIBLE p {};
|
||||||
status = policy->SetDeviceFormat(wstring_device_id.c_str(), wave_format.get(), (WAVEFORMATEX *) &p);
|
status = policy->SetDeviceFormat(wstring_device_id.c_str(), wave_format.get(), (WAVEFORMATEX *) &p);
|
||||||
|
|
||||||
// Surround 5.1 might contain side-{left, right} instead of speaker in the back
|
// Surround 5.1 might contain side-{left, right} instead of speaker in the back
|
||||||
// Try again with different speaker mask.
|
// Try again with different speaker mask.
|
||||||
if (status == 0x88890008 && type == format_t::surr51) {
|
if (status == 0x88890008 && sink_info.first == format_t::surr51) {
|
||||||
set_wave_format(wave_format, surround_51_side_speakers);
|
set_wave_format(wave_format, surround_51_side_speakers);
|
||||||
status = policy->SetDeviceFormat(wstring_device_id.c_str(), wave_format.get(), (WAVEFORMATEX *) &p);
|
status = policy->SetDeviceFormat(wstring_device_id.c_str(), wave_format.get(), (WAVEFORMATEX *) &p);
|
||||||
}
|
}
|
||||||
@@ -768,6 +794,12 @@ namespace platf::audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remember the assigned sink name, so we have it for later if we need to set it
|
||||||
|
// back after another application changes it
|
||||||
|
if (!failure) {
|
||||||
|
assigned_sink = sink;
|
||||||
|
}
|
||||||
|
|
||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -867,6 +899,7 @@ namespace platf::audio {
|
|||||||
~audio_control_t() override {}
|
~audio_control_t() override {}
|
||||||
|
|
||||||
policy_t policy;
|
policy_t policy;
|
||||||
|
std::string assigned_sink;
|
||||||
};
|
};
|
||||||
} // namespace platf::audio
|
} // namespace platf::audio
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user