[APU] Add ALSA apu on Linux
This commit is contained in:
94
src/xenia/apu/alsa/alsa_audio_system.cc
Normal file
94
src/xenia/apu/alsa/alsa_audio_system.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/apu/alsa/alsa_audio_system.h"
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "xenia/apu/alsa/alsa_audio_driver.h"
|
||||
#include "xenia/apu/apu_flags.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace apu {
|
||||
namespace alsa {
|
||||
|
||||
ALSAAudioSystem::ALSAAudioSystem(cpu::Processor* processor)
|
||||
: AudioSystem(processor) {}
|
||||
|
||||
ALSAAudioSystem::~ALSAAudioSystem() {}
|
||||
|
||||
bool ALSAAudioSystem::IsAvailable() {
|
||||
// Check if ALSA is available by trying to open a dummy PCM device
|
||||
snd_pcm_t* pcm = nullptr;
|
||||
int err =
|
||||
snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
if (err >= 0 && pcm) {
|
||||
snd_pcm_close(pcm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ALSAAudioSystem::Initialize() {}
|
||||
|
||||
std::unique_ptr<AudioSystem> ALSAAudioSystem::Create(
|
||||
cpu::Processor* processor) {
|
||||
if (!IsAvailable()) {
|
||||
XELOGE("ALSA is not available on this system");
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<ALSAAudioSystem>(processor);
|
||||
}
|
||||
|
||||
X_RESULT ALSAAudioSystem::CreateDriver(size_t index,
|
||||
xe::threading::Semaphore* semaphore,
|
||||
AudioDriver** out_driver) {
|
||||
assert_not_null(out_driver);
|
||||
|
||||
XELOGI("ALSAAudioSystem::CreateDriver for client index {}", index);
|
||||
|
||||
// Create a new driver for each client
|
||||
// ALSA's dmix plugin should handle mixing multiple streams
|
||||
auto driver = new ALSAAudioDriver(semaphore);
|
||||
if (!driver->Initialize()) {
|
||||
XELOGE("Failed to initialize ALSA driver for client index {}", index);
|
||||
delete driver;
|
||||
*out_driver = nullptr;
|
||||
return X_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_driver = driver;
|
||||
XELOGI("Successfully created ALSA driver for client index {}", index);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
AudioDriver* ALSAAudioSystem::CreateDriver(xe::threading::Semaphore* semaphore,
|
||||
uint32_t frequency,
|
||||
uint32_t channels,
|
||||
bool need_format_conversion) {
|
||||
auto driver = new ALSAAudioDriver(semaphore, frequency, channels,
|
||||
need_format_conversion);
|
||||
if (!driver->Initialize()) {
|
||||
delete driver;
|
||||
return nullptr;
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
void ALSAAudioSystem::DestroyDriver(AudioDriver* driver) {
|
||||
assert_not_null(driver);
|
||||
ALSAAudioDriver* alsa_driver = static_cast<ALSAAudioDriver*>(driver);
|
||||
alsa_driver->Shutdown();
|
||||
delete alsa_driver;
|
||||
}
|
||||
|
||||
} // namespace alsa
|
||||
} // namespace apu
|
||||
} // namespace xe
|
||||
Reference in New Issue
Block a user