mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Recreate ma_device on failure (#4729)
This commit is contained in:
parent
0e83367a2b
commit
5c8c05b1af
|
@ -21,6 +21,7 @@
|
||||||
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
||||||
- Bugfix: Fixed some network errors having `0` as their HTTP status. (#4704)
|
- Bugfix: Fixed some network errors having `0` as their HTTP status. (#4704)
|
||||||
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
||||||
|
- Bugfix: Fixed highlights sometimes not working after changing sound device, or switching users in your operating system. (#4729)
|
||||||
- Bugfix: Fixed key bindings not showing in context menus on Mac. (#4722)
|
- Bugfix: Fixed key bindings not showing in context menus on Mac. (#4722)
|
||||||
- Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637)
|
- Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637)
|
||||||
- Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570)
|
- Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570)
|
||||||
|
|
|
@ -20,7 +20,6 @@ constexpr const auto NUM_SOUNDS = 4;
|
||||||
SoundController::SoundController()
|
SoundController::SoundController()
|
||||||
: context(std::make_unique<ma_context>())
|
: context(std::make_unique<ma_context>())
|
||||||
, resourceManager(std::make_unique<ma_resource_manager>())
|
, resourceManager(std::make_unique<ma_resource_manager>())
|
||||||
, device(std::make_unique<ma_device>())
|
|
||||||
, engine(std::make_unique<ma_engine>())
|
, engine(std::make_unique<ma_engine>())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -66,27 +65,9 @@ void SoundController::initialize(Settings &settings, Paths &paths)
|
||||||
this->defaultPingData = defaultPingFile.readAll();
|
this->defaultPingData = defaultPingFile.readAll();
|
||||||
|
|
||||||
/// Initialize a sound device
|
/// Initialize a sound device
|
||||||
auto deviceConfig = ma_device_config_init(ma_device_type_playback);
|
if (!this->recreateDevice())
|
||||||
deviceConfig.playback.pDeviceID = nullptr;
|
|
||||||
deviceConfig.playback.format = this->resourceManager->config.decodedFormat;
|
|
||||||
deviceConfig.playback.channels = 0;
|
|
||||||
deviceConfig.pulse.pStreamNamePlayback = "Chatterino MA";
|
|
||||||
deviceConfig.sampleRate = this->resourceManager->config.decodedSampleRate;
|
|
||||||
deviceConfig.dataCallback = ma_engine_data_callback_internal;
|
|
||||||
deviceConfig.pUserData = this->engine.get();
|
|
||||||
|
|
||||||
result =
|
|
||||||
ma_device_init(this->context.get(), &deviceConfig, this->device.get());
|
|
||||||
if (result != MA_SUCCESS)
|
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoSound) << "Error initializing device:" << result;
|
qCWarning(chatterinoSound) << "Failed to create the initial device";
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ma_device_start(this->device.get());
|
|
||||||
if (result != MA_SUCCESS)
|
|
||||||
{
|
|
||||||
qCWarning(chatterinoSound) << "Error starting device:" << result;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +153,11 @@ SoundController::~SoundController()
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_engine_uninit(this->engine.get());
|
ma_engine_uninit(this->engine.get());
|
||||||
ma_device_uninit(this->device.get());
|
if (this->device)
|
||||||
|
{
|
||||||
|
ma_device_uninit(this->device.get());
|
||||||
|
this->device.reset();
|
||||||
|
}
|
||||||
ma_resource_manager_uninit(this->resourceManager.get());
|
ma_resource_manager_uninit(this->resourceManager.get());
|
||||||
ma_context_uninit(this->context.get());
|
ma_context_uninit(this->context.get());
|
||||||
}
|
}
|
||||||
|
@ -204,7 +189,12 @@ void SoundController::play(const QUrl &sound)
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoSound)
|
qCWarning(chatterinoSound)
|
||||||
<< "Failed to start the sound device" << result;
|
<< "Failed to start the sound device" << result;
|
||||||
return;
|
|
||||||
|
if (!this->recreateDevice())
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoSound) << "Failed to recreate device";
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qCInfo(chatterinoSound) << "Successfully restarted the sound device";
|
qCInfo(chatterinoSound) << "Successfully restarted the sound device";
|
||||||
|
@ -234,4 +224,44 @@ void SoundController::play(const QUrl &sound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SoundController::recreateDevice()
|
||||||
|
{
|
||||||
|
ma_result result{};
|
||||||
|
|
||||||
|
if (this->device)
|
||||||
|
{
|
||||||
|
// Release the previous device first
|
||||||
|
qCDebug(chatterinoSound) << "Uniniting previously created device";
|
||||||
|
ma_device_uninit(this->device.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
this->device = std::make_unique<ma_device>();
|
||||||
|
|
||||||
|
auto deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
|
deviceConfig.playback.pDeviceID = nullptr;
|
||||||
|
deviceConfig.playback.format = this->resourceManager->config.decodedFormat;
|
||||||
|
deviceConfig.playback.channels = 0;
|
||||||
|
deviceConfig.pulse.pStreamNamePlayback = "Chatterino MA";
|
||||||
|
deviceConfig.sampleRate = this->resourceManager->config.decodedSampleRate;
|
||||||
|
deviceConfig.dataCallback = ma_engine_data_callback_internal;
|
||||||
|
deviceConfig.pUserData = this->engine.get();
|
||||||
|
|
||||||
|
result =
|
||||||
|
ma_device_init(this->context.get(), &deviceConfig, this->device.get());
|
||||||
|
if (result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoSound) << "Error initializing device:" << result;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ma_device_start(this->device.get());
|
||||||
|
if (result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoSound) << "Error starting device:" << result;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -45,7 +45,7 @@ private:
|
||||||
// Used for storing & reusing sounds to be played
|
// Used for storing & reusing sounds to be played
|
||||||
std::unique_ptr<ma_resource_manager> resourceManager;
|
std::unique_ptr<ma_resource_manager> resourceManager;
|
||||||
// The sound device we're playing sound into
|
// The sound device we're playing sound into
|
||||||
std::unique_ptr<ma_device> device;
|
std::unique_ptr<ma_device> device{nullptr};
|
||||||
// The engine is a high-level API for playing sounds from paths in a simple & efficient-enough manner
|
// The engine is a high-level API for playing sounds from paths in a simple & efficient-enough manner
|
||||||
std::unique_ptr<ma_engine> engine;
|
std::unique_ptr<ma_engine> engine;
|
||||||
|
|
||||||
|
@ -64,6 +64,13 @@ private:
|
||||||
|
|
||||||
bool initialized{false};
|
bool initialized{false};
|
||||||
|
|
||||||
|
// Recreates the sound device
|
||||||
|
// This is used during initialization, and can also be used if the device
|
||||||
|
// needs to be recreated during playback
|
||||||
|
//
|
||||||
|
// Returns false on failure
|
||||||
|
bool recreateDevice();
|
||||||
|
|
||||||
friend class Application;
|
friend class Application;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue