mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
Add launcher microphone selection and SDL AudioIn capture
This commit is contained in:
@@ -43,6 +43,10 @@ int32_t GetUserId() {
|
|||||||
return g_config->user_id;
|
return g_config->user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& GetAudioInputDevice() {
|
||||||
|
return g_config->audio_input_device;
|
||||||
|
}
|
||||||
|
|
||||||
PresentMode GetPresentMode() {
|
PresentMode GetPresentMode() {
|
||||||
return g_config->present_mode;
|
return g_config->present_mode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ struct ConfigOptions {
|
|||||||
uint32_t screen_height = 720;
|
uint32_t screen_height = 720;
|
||||||
std::string user_name = "Kyty";
|
std::string user_name = "Kyty";
|
||||||
int32_t user_id = DEFAULT_USER_ID;
|
int32_t user_id = DEFAULT_USER_ID;
|
||||||
|
std::string audio_input_device;
|
||||||
PresentMode present_mode = PresentMode::Mailbox;
|
PresentMode present_mode = PresentMode::Mailbox;
|
||||||
int32_t gpu_index = -1;
|
int32_t gpu_index = -1;
|
||||||
bool fullscreen_enabled = false;
|
bool fullscreen_enabled = false;
|
||||||
@@ -77,6 +78,7 @@ uint32_t GetScreenWidth();
|
|||||||
uint32_t GetScreenHeight();
|
uint32_t GetScreenHeight();
|
||||||
const std::string& GetUserName();
|
const std::string& GetUserName();
|
||||||
int32_t GetUserId();
|
int32_t GetUserId();
|
||||||
|
const std::string& GetAudioInputDevice();
|
||||||
PresentMode GetPresentMode();
|
PresentMode GetPresentMode();
|
||||||
int32_t GetGpuIndex();
|
int32_t GetGpuIndex();
|
||||||
bool FullscreenEnabled();
|
bool FullscreenEnabled();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ add_executable(launcher WIN32
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries(launcher Qt6::Concurrent Qt6::Network Qt6::Widgets Vulkan::Headers kyty_git_version)
|
target_link_libraries(launcher Qt6::Concurrent Qt6::Network Qt6::Widgets Vulkan::Headers SDL2-static kyty_git_version)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(launcher setupapi)
|
target_link_libraries(launcher setupapi)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -75,7 +75,25 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" rowspan="2">
|
<item row="2" column="0">
|
||||||
|
<widget class="QGroupBox" name="audio_group">
|
||||||
|
<property name="title"><string>Audio</string></property>
|
||||||
|
<layout class="QFormLayout" name="audioLayout">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_audio_input_device">
|
||||||
|
<property name="text"><string>Microphone:</string></property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox_audio_input_device"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" rowspan="3">
|
||||||
<widget class="QGroupBox" name="graphics_group">
|
<widget class="QGroupBox" name="graphics_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Graphics && display</string>
|
<string>Graphics && display</string>
|
||||||
@@ -152,7 +170,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="debug_group">
|
<widget class="QGroupBox" name="debug_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Debugging && logs</string>
|
<string>Debugging && logs</string>
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public:
|
|||||||
Resolution screen_resolution = Resolution::R1280X720;
|
Resolution screen_resolution = Resolution::R1280X720;
|
||||||
QString user_name = "Kyty";
|
QString user_name = "Kyty";
|
||||||
int user_id = Config::DEFAULT_USER_ID;
|
int user_id = Config::DEFAULT_USER_ID;
|
||||||
|
QString audio_input_device;
|
||||||
PresentMode present_mode = PresentMode::Mailbox;
|
PresentMode present_mode = PresentMode::Mailbox;
|
||||||
int gpu_index = -1;
|
int gpu_index = -1;
|
||||||
bool fullscreen_enabled = false;
|
bool fullscreen_enabled = false;
|
||||||
@@ -115,6 +116,7 @@ public:
|
|||||||
screen_resolution = other.screen_resolution;
|
screen_resolution = other.screen_resolution;
|
||||||
user_name = other.user_name;
|
user_name = other.user_name;
|
||||||
user_id = other.user_id;
|
user_id = other.user_id;
|
||||||
|
audio_input_device = other.audio_input_device;
|
||||||
present_mode = other.present_mode;
|
present_mode = other.present_mode;
|
||||||
gpu_index = other.gpu_index;
|
gpu_index = other.gpu_index;
|
||||||
fullscreen_enabled = other.fullscreen_enabled;
|
fullscreen_enabled = other.fullscreen_enabled;
|
||||||
@@ -160,6 +162,7 @@ public:
|
|||||||
KYTY_CFG_SET(screen_resolution);
|
KYTY_CFG_SET(screen_resolution);
|
||||||
KYTY_CFG_SET(user_name);
|
KYTY_CFG_SET(user_name);
|
||||||
KYTY_CFG_SET(user_id);
|
KYTY_CFG_SET(user_id);
|
||||||
|
KYTY_CFG_SET(audio_input_device);
|
||||||
KYTY_CFG_SET(present_mode);
|
KYTY_CFG_SET(present_mode);
|
||||||
KYTY_CFG_SET(gpu_index);
|
KYTY_CFG_SET(gpu_index);
|
||||||
KYTY_CFG_SET(fullscreen_enabled);
|
KYTY_CFG_SET(fullscreen_enabled);
|
||||||
@@ -196,6 +199,7 @@ public:
|
|||||||
user_id = user_id_ok && Config::IsConfiguredUserIdValid(saved_user_id)
|
user_id = user_id_ok && Config::IsConfiguredUserIdValid(saved_user_id)
|
||||||
? saved_user_id
|
? saved_user_id
|
||||||
: Config::DEFAULT_USER_ID;
|
: Config::DEFAULT_USER_ID;
|
||||||
|
audio_input_device = s->value("audio_input_device", audio_input_device).toString();
|
||||||
KYTY_CFG_GET(present_mode);
|
KYTY_CFG_GET(present_mode);
|
||||||
gpu_index = s->value("gpu_index", -1).toInt();
|
gpu_index = s->value("gpu_index", -1).toInt();
|
||||||
if (EnumToText(present_mode).isEmpty()) {
|
if (EnumToText(present_mode).isEmpty()) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "common/emulatorConfig.h"
|
#include "common/emulatorConfig.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "mandatoryLineEdit.h"
|
#include "mandatoryLineEdit.h"
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
#include <QAbstractItemView>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
@@ -167,6 +168,31 @@ void ConfigurationEditDialog::Init(const Configuration& info) {
|
|||||||
m_ui->lineEdit_user_name->setMaxLength(static_cast<int>(Config::MAX_USER_NAME_LENGTH));
|
m_ui->lineEdit_user_name->setMaxLength(static_cast<int>(Config::MAX_USER_NAME_LENGTH));
|
||||||
m_ui->lineEdit_user_name->setText(info.user_name);
|
m_ui->lineEdit_user_name->setText(info.user_name);
|
||||||
m_ui->spinBox_user_id->setValue(info.user_id);
|
m_ui->spinBox_user_id->setValue(info.user_id);
|
||||||
|
auto* microphone = m_ui->comboBox_audio_input_device;
|
||||||
|
microphone->clear();
|
||||||
|
microphone->addItem(tr("None"), QString {});
|
||||||
|
microphone->setToolTip(tr("Microphone used by games. None supplies silence."));
|
||||||
|
SDL_SetMainReady();
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) == 0) {
|
||||||
|
const int device_count = SDL_GetNumAudioDevices(SDL_TRUE);
|
||||||
|
for (int i = 0; i < device_count; i++) {
|
||||||
|
if (const auto* device = SDL_GetAudioDeviceName(i, SDL_TRUE); device != nullptr) {
|
||||||
|
const auto name = QString::fromUtf8(device);
|
||||||
|
if (microphone->findData(name) < 0) {
|
||||||
|
microphone->addItem(name, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
} else {
|
||||||
|
microphone->setToolTip(tr("Microphones could not be listed: %1")
|
||||||
|
.arg(QString::fromUtf8(SDL_GetError())));
|
||||||
|
}
|
||||||
|
if (microphone->findData(info.audio_input_device) < 0) {
|
||||||
|
microphone->addItem(tr("%1 (unavailable)").arg(info.audio_input_device),
|
||||||
|
info.audio_input_device);
|
||||||
|
}
|
||||||
|
microphone->setCurrentIndex(microphone->findData(info.audio_input_device));
|
||||||
ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution);
|
ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution);
|
||||||
ListInit(m_ui->comboBox_present_mode, info.present_mode);
|
ListInit(m_ui->comboBox_present_mode, info.present_mode);
|
||||||
m_ui->comboBox_gpu->clear();
|
m_ui->comboBox_gpu->clear();
|
||||||
@@ -340,6 +366,7 @@ void ConfigurationEditDialog::resizeEvent(QResizeEvent* event) {
|
|||||||
static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
|
static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
|
||||||
info.user_name = ui.lineEdit_user_name->text().trimmed();
|
info.user_name = ui.lineEdit_user_name->text().trimmed();
|
||||||
info.user_id = ui.spinBox_user_id->value();
|
info.user_id = ui.spinBox_user_id->value();
|
||||||
|
info.audio_input_device = ui.comboBox_audio_input_device->currentData().toString();
|
||||||
info.screen_resolution =
|
info.screen_resolution =
|
||||||
TextToEnum<Configuration::Resolution>(ui.comboBox_screen_resolution->currentText());
|
TextToEnum<Configuration::Resolution>(ui.comboBox_screen_resolution->currentText());
|
||||||
info.present_mode =
|
info.present_mode =
|
||||||
|
|||||||
@@ -228,6 +228,9 @@ static QStringList CreateEmulatorArgs(const Configuration& info) {
|
|||||||
args << "--screen-height" << r.at(1);
|
args << "--screen-height" << r.at(1);
|
||||||
args << "--user-name" << info.user_name;
|
args << "--user-name" << info.user_name;
|
||||||
args << "--user-id" << QString::number(info.user_id);
|
args << "--user-id" << QString::number(info.user_id);
|
||||||
|
if (!info.audio_input_device.isEmpty()) {
|
||||||
|
args << "--mic" << info.audio_input_device;
|
||||||
|
}
|
||||||
args << "--present-mode" << EnumToText(info.present_mode);
|
args << "--present-mode" << EnumToText(info.present_mode);
|
||||||
if (info.gpu_index >= 0) {
|
if (info.gpu_index >= 0) {
|
||||||
args << "--gpu" << QString::number(info.gpu_index);
|
args << "--gpu" << QString::number(info.gpu_index);
|
||||||
|
|||||||
+91
-12
@@ -3,6 +3,7 @@
|
|||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
#include "common/emulatorConfig.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/magicEnum.h"
|
#include "common/magicEnum.h"
|
||||||
#include "common/stringUtils.h"
|
#include "common/stringUtils.h"
|
||||||
@@ -38,6 +39,9 @@ constexpr int AUDIO_OUT_PORT_TYPE_AUX = 127;
|
|||||||
|
|
||||||
constexpr uint32_t AUDIO_OUT_PARAM_FORMAT_MASK = 0x000000ffu;
|
constexpr uint32_t AUDIO_OUT_PARAM_FORMAT_MASK = 0x000000ffu;
|
||||||
|
|
||||||
|
constexpr int AUDIO_IN_SILENT_STATE_DEVICE_NONE = 0x1;
|
||||||
|
constexpr uint32_t AUDIO_IN_GRAIN_MAX_ASYNC = 384;
|
||||||
|
|
||||||
static bool audio_out_port_type_is_valid(int type) {
|
static bool audio_out_port_type_is_valid(int type) {
|
||||||
return (type >= AUDIO_OUT_PORT_TYPE_MAIN && type <= AUDIO_OUT_PORT_TYPE_PADSPK) ||
|
return (type >= AUDIO_OUT_PORT_TYPE_MAIN && type <= AUDIO_OUT_PORT_TYPE_PADSPK) ||
|
||||||
type == AUDIO_OUT_PORT_TYPE_VIBRATION || type == AUDIO_OUT_PORT_TYPE_AUDIO3D ||
|
type == AUDIO_OUT_PORT_TYPE_VIBRATION || type == AUDIO_OUT_PORT_TYPE_AUDIO3D ||
|
||||||
@@ -91,7 +95,7 @@ public:
|
|||||||
|
|
||||||
Id AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous);
|
Id AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous);
|
||||||
int AudioInClose(Id handle);
|
int AudioInClose(Id handle);
|
||||||
bool AudioInValid(Id handle);
|
int AudioInGetSilentState(Id handle);
|
||||||
int AudioInInput(Id handle, void* dest);
|
int AudioInInput(Id handle, void* dest);
|
||||||
|
|
||||||
static constexpr int OUT_PORTS_MAX = 32;
|
static constexpr int OUT_PORTS_MAX = 32;
|
||||||
@@ -120,6 +124,7 @@ private:
|
|||||||
uint32_t freq = 0;
|
uint32_t freq = 0;
|
||||||
uint32_t bytes_per_frame = 0;
|
uint32_t bytes_per_frame = 0;
|
||||||
uint64_t last_input_time = 0;
|
uint64_t last_input_time = 0;
|
||||||
|
SDL_AudioDeviceID audio_device = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
PortIn* GetAudioInPort(Id handle); // Caller holds m_mutex.
|
PortIn* GetAudioInPort(Id handle); // Caller holds m_mutex.
|
||||||
@@ -135,6 +140,8 @@ private:
|
|||||||
static SDL_AudioFormat SdlFormat(Format format);
|
static SDL_AudioFormat SdlFormat(Format format);
|
||||||
static bool OpenSdlDevice(PortOut* port);
|
static bool OpenSdlDevice(PortOut* port);
|
||||||
static void CloseSdlDevice(PortOut* port);
|
static void CloseSdlDevice(PortOut* port);
|
||||||
|
static void OpenSdlDevice(PortIn* port, Format format);
|
||||||
|
static void CloseSdlDevice(PortIn* port);
|
||||||
static const void* PrepareOutputBuffer(const PortOut& port, const void* data,
|
static const void* PrepareOutputBuffer(const PortOut& port, const void* data,
|
||||||
std::vector<uint8_t>* buffer);
|
std::vector<uint8_t>* buffer);
|
||||||
static bool QueueSdlAudio(PortOut* port, const void* data, bool blocking);
|
static bool QueueSdlAudio(PortOut* port, const void* data, bool blocking);
|
||||||
@@ -202,6 +209,9 @@ Audio::~Audio() {
|
|||||||
for (auto& port: m_out_ports) {
|
for (auto& port: m_out_ports) {
|
||||||
CloseSdlDevice(&port);
|
CloseSdlDevice(&port);
|
||||||
}
|
}
|
||||||
|
for (auto& port: m_in_ports) {
|
||||||
|
CloseSdlDevice(&port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Audio::FormatIsFloat(Format format) {
|
bool Audio::FormatIsFloat(Format format) {
|
||||||
@@ -570,6 +580,38 @@ uint32_t Audio::AudioOutOutputs(OutputParam* params, uint32_t num, bool blocking
|
|||||||
return first_port.samples_num;
|
return first_port.samples_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Audio::OpenSdlDevice(PortIn* port, Format format) {
|
||||||
|
const auto& name = Config::GetAudioInputDevice();
|
||||||
|
if (name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||||
|
LOGF("AudioIn: SDL init failed: %s\n", SDL_GetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_AudioSpec desired {};
|
||||||
|
desired.freq = static_cast<int>(port->freq);
|
||||||
|
desired.format = SdlFormat(format);
|
||||||
|
desired.channels = static_cast<Uint8>(port->bytes_per_frame / BytesPerSample(format));
|
||||||
|
desired.samples = static_cast<Uint16>(port->samples_num);
|
||||||
|
// SDL converts capture data to the guest format when allowed_changes is zero.
|
||||||
|
port->audio_device = SDL_OpenAudioDevice(name.c_str(), 1, &desired, nullptr, 0);
|
||||||
|
if (port->audio_device == 0) {
|
||||||
|
LOGF("AudioIn: cannot open '%s': %s; using silence\n", name.c_str(), SDL_GetError());
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOGF("AudioIn: opened '%s' (%u Hz, %u ch)\n", name.c_str(), port->freq, desired.channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::CloseSdlDevice(PortIn* port) {
|
||||||
|
if (port->audio_device != 0) {
|
||||||
|
SDL_CloseAudioDevice(port->audio_device);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
port->audio_device = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Audio::Id Audio::AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous) {
|
Audio::Id Audio::AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous) {
|
||||||
Common::LockGuard lock(m_mutex);
|
Common::LockGuard lock(m_mutex);
|
||||||
|
|
||||||
@@ -586,6 +628,7 @@ Audio::Id Audio::AudioInOpen(uint32_t samples_num, uint32_t freq, Format format,
|
|||||||
if (format == Format::Signed16bitStereo || format == Format::FloatStereo) {
|
if (format == Format::Signed16bitStereo || format == Format::FloatStereo) {
|
||||||
port.bytes_per_frame *= 2;
|
port.bytes_per_frame *= 2;
|
||||||
}
|
}
|
||||||
|
OpenSdlDevice(&port, format);
|
||||||
|
|
||||||
return Id::Create(id);
|
return Id::Create(id);
|
||||||
}
|
}
|
||||||
@@ -611,13 +654,22 @@ int Audio::AudioInClose(Id handle) {
|
|||||||
if (port->busy) {
|
if (port->busy) {
|
||||||
return AUDIO_IN_ERROR_BUSY;
|
return AUDIO_IN_ERROR_BUSY;
|
||||||
}
|
}
|
||||||
|
CloseSdlDevice(port);
|
||||||
*port = {};
|
*port = {};
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Audio::AudioInValid(Id handle) {
|
int Audio::AudioInGetSilentState(Id handle) {
|
||||||
Common::LockGuard lock(m_mutex);
|
Common::LockGuard lock(m_mutex);
|
||||||
return GetAudioInPort(handle) != nullptr;
|
auto* port = GetAudioInPort(handle);
|
||||||
|
if (port == nullptr) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (port->audio_device == 0 ||
|
||||||
|
SDL_GetAudioDeviceStatus(port->audio_device) == SDL_AUDIO_STOPPED) {
|
||||||
|
return AUDIO_IN_SILENT_STATE_DEVICE_NONE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Audio::AudioInInput(Id handle, void* dest) {
|
int Audio::AudioInInput(Id handle, void* dest) {
|
||||||
@@ -634,6 +686,9 @@ int Audio::AudioInInput(Id handle, void* dest) {
|
|||||||
port->busy = true;
|
port->busy = true;
|
||||||
snapshot = *port;
|
snapshot = *port;
|
||||||
}
|
}
|
||||||
|
if (snapshot.audio_device != 0 && dest != nullptr) {
|
||||||
|
SDL_PauseAudioDevice(snapshot.audio_device, 0);
|
||||||
|
}
|
||||||
|
|
||||||
const uint64_t block_time = (1000000ULL * snapshot.samples_num) / snapshot.freq;
|
const uint64_t block_time = (1000000ULL * snapshot.samples_num) / snapshot.freq;
|
||||||
uint64_t wait_time = 0;
|
uint64_t wait_time = 0;
|
||||||
@@ -641,7 +696,7 @@ int Audio::AudioInInput(Id handle, void* dest) {
|
|||||||
if (dest != nullptr) {
|
if (dest != nullptr) {
|
||||||
wait_time = block_time;
|
wait_time = block_time;
|
||||||
}
|
}
|
||||||
} else if (snapshot.last_input_time != 0) {
|
} else if (snapshot.last_input_time != 0 && (snapshot.audio_device == 0 || dest == nullptr)) {
|
||||||
const auto now = LibKernel::KernelGetProcessTime();
|
const auto now = LibKernel::KernelGetProcessTime();
|
||||||
const auto next = snapshot.last_input_time + block_time;
|
const auto next = snapshot.last_input_time + block_time;
|
||||||
if (next > now) {
|
if (next > now) {
|
||||||
@@ -649,17 +704,44 @@ int Audio::AudioInInput(Id handle, void* dest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Common::Thread::SleepMicro(wait_time);
|
Common::Thread::SleepMicro(wait_time);
|
||||||
|
uint32_t frames = snapshot.samples_num;
|
||||||
|
bool failed = false;
|
||||||
if (dest != nullptr) {
|
if (dest != nullptr) {
|
||||||
// No input device backend: return silence matching AUDIO_IN_SILENT_STATE_DEVICE_NONE.
|
if (snapshot.audio_device != 0) {
|
||||||
std::memset(dest, 0, snapshot.samples_num * snapshot.bytes_per_frame);
|
while (!snapshot.asynchronous &&
|
||||||
|
SDL_GetQueuedAudioSize(snapshot.audio_device) <
|
||||||
|
frames * snapshot.bytes_per_frame &&
|
||||||
|
SDL_GetAudioDeviceStatus(snapshot.audio_device) == SDL_AUDIO_PLAYING) {
|
||||||
|
Common::Thread::SleepMicro(1000);
|
||||||
|
}
|
||||||
|
failed = SDL_GetAudioDeviceStatus(snapshot.audio_device) != SDL_AUDIO_PLAYING;
|
||||||
|
if (!failed) {
|
||||||
|
if (snapshot.asynchronous) {
|
||||||
|
frames = AUDIO_IN_GRAIN_MAX_ASYNC;
|
||||||
|
}
|
||||||
|
frames = SDL_DequeueAudio(snapshot.audio_device, dest,
|
||||||
|
frames * snapshot.bytes_per_frame) /
|
||||||
|
snapshot.bytes_per_frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (snapshot.audio_device == 0 || failed) {
|
||||||
|
std::memset(dest, 0, frames * snapshot.bytes_per_frame);
|
||||||
|
}
|
||||||
|
} else if (snapshot.audio_device != 0) {
|
||||||
|
SDL_PauseAudioDevice(snapshot.audio_device, 1);
|
||||||
|
SDL_ClearQueuedAudio(snapshot.audio_device);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Common::LockGuard lock(m_mutex);
|
Common::LockGuard lock(m_mutex);
|
||||||
auto& port = m_in_ports[handle.GetId()];
|
auto& port = m_in_ports[handle.GetId()];
|
||||||
|
if (failed) {
|
||||||
|
LOGF("AudioIn: capture stopped; using silence\n");
|
||||||
|
CloseSdlDevice(&port);
|
||||||
|
}
|
||||||
port.last_input_time = dest != nullptr ? LibKernel::KernelGetProcessTime() : 0;
|
port.last_input_time = dest != nullptr ? LibKernel::KernelGetProcessTime() : 0;
|
||||||
port.busy = false;
|
port.busy = false;
|
||||||
}
|
}
|
||||||
return dest != nullptr ? static_cast<int>(snapshot.samples_num) : 0;
|
return dest != nullptr ? static_cast<int>(frames) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace AudioOut {
|
namespace AudioOut {
|
||||||
@@ -851,8 +933,6 @@ namespace AudioIn {
|
|||||||
|
|
||||||
LIB_NAME("AudioIn", "AudioIn");
|
LIB_NAME("AudioIn", "AudioIn");
|
||||||
|
|
||||||
constexpr int AUDIO_IN_SILENT_STATE_DEVICE_NONE = 0x1;
|
|
||||||
|
|
||||||
static int OpenPort(int user_id, int type, int index, uint32_t len, uint32_t freq,
|
static int OpenPort(int user_id, int type, int index, uint32_t len, uint32_t freq,
|
||||||
uint32_t param, bool asynchronous) {
|
uint32_t param, bool asynchronous) {
|
||||||
LOGF("\t user_id = %d\n"
|
LOGF("\t user_id = %d\n"
|
||||||
@@ -935,12 +1015,11 @@ int KYTY_SYSV_ABI AudioInGetSilentState(int handle) {
|
|||||||
|
|
||||||
EXIT_IF(g_audio == nullptr);
|
EXIT_IF(g_audio == nullptr);
|
||||||
|
|
||||||
if (handle <= 0 || !g_audio->AudioInValid(Audio::Id(handle))) {
|
if (handle <= 0) {
|
||||||
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio input has no device backend yet, so every valid port receives silence.
|
return g_audio->AudioInGetSilentState(Audio::Id(handle));
|
||||||
return AUDIO_IN_SILENT_STATE_DEVICE_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AudioIn
|
} // namespace AudioIn
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ static void PrintUsage() {
|
|||||||
" --user-name <name> Local user name (1-16 bytes). Default: Kyty.\n");
|
" --user-name <name> Local user name (1-16 bytes). Default: Kyty.\n");
|
||||||
::printf(" --user-id <num> Local user ID. Default: %d.\n",
|
::printf(" --user-id <num> Local user ID. Default: %d.\n",
|
||||||
Config::DEFAULT_USER_ID);
|
Config::DEFAULT_USER_ID);
|
||||||
|
::printf(" --mic <name> Capture from this microphone; omit for silence.\n");
|
||||||
::printf(
|
::printf(
|
||||||
" --present-mode <value> Fifo, Mailbox, or Immediate. Default: Mailbox.\n");
|
" --present-mode <value> Fifo, Mailbox, or Immediate. Default: Mailbox.\n");
|
||||||
::printf(
|
::printf(
|
||||||
@@ -241,6 +242,8 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he
|
|||||||
::printf("invalid user ID: %s\n", value.c_str());
|
::printf("invalid user ID: %s\n", value.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (arg == "--mic") {
|
||||||
|
options.config.audio_input_device = value;
|
||||||
} else if (arg == "--present-mode") {
|
} else if (arg == "--present-mode") {
|
||||||
if (!ParseEnum(value, options.config.present_mode)) {
|
if (!ParseEnum(value, options.config.present_mode)) {
|
||||||
::printf("invalid present mode: %s\n", value.c_str());
|
::printf("invalid present mode: %s\n", value.c_str());
|
||||||
|
|||||||
Reference in New Issue
Block a user