This commit is contained in:
ITotalJustice 2025-06-13 00:07:24 +02:00 committed by GitHub
commit 3bd2cf256c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 328 additions and 0 deletions

View File

@ -0,0 +1,47 @@
/**
* @file aud.h
* @brief Only available on [11.0.0+].
* @note Only one session may be open at once.
* @author TotalJustice
* @copyright libnx Authors
*/
#pragma once
#include "../types.h"
#include "../sf/service.h"
#define AUD_MAX_DELAY (1000000000ULL)
/// Initialize aud:a. Only available on [11.0.0+].
Result audaInitialize(void);
/// Exit aud:a.
void audaExit(void);
/// Initialize aud:d. Only available on [11.0.0+].
Result auddInitialize(void);
/// Exit aud:d.
void auddExit(void);
/// Gets the Service for aud:a.
Service* audaGetServiceSession(void);
/// Gets the Service for aud:d.
Service* auddGetServiceSession(void);
Result audaRequestSuspendAudio(u64 pid, u64 delay);
Result audaRequestResumeAudio(u64 pid, u64 delay);
Result audaGetAudioOutputProcessMasterVolume(u64 pid, float* volume_out);
Result audaSetAudioOutputProcessMasterVolume(u64 pid, u64 delay, float volume);
Result audaGetAudioInputProcessMasterVolume(u64 pid, float* volume_out);
// Sets both Output and Input volume
Result audaSetAudioInputProcessMasterVolume(u64 pid, u64 delay, float volume);
Result audaGetAudioOutputProcessRecordVolume(u64 pid, float* volume_out);
Result audaSetAudioOutputProcessRecordVolume(u64 pid, u64 delay, float volume);
Result auddRequestSuspendAudioForDebug(u64 pid, u64 delay);
Result auddRequestResumeAudioForDebug(u64 pid, u64 delay);

View File

@ -10,6 +10,8 @@
#include "../audio/audio.h"
#include "../sf/service.h"
#define AUDOUT_MAX_DELAY (1000000000ULL)
typedef enum {
AudioOutState_Started = 0,
AudioOutState_Stopped = 1,
@ -33,12 +35,30 @@ Result audoutInitialize(void);
/// Exit audout.
void audoutExit(void);
/// Initialize audout:a. Removed in [11.0.0].
Result audoutaInitialize(void);
/// Exit audout:a.
void audoutaExit(void);
/// Initialize audout:d. Removed in [11.0.0].
Result audoutdInitialize(void);
/// Exit audout:d.
void audoutdExit(void);
/// Gets the Service object for the actual audout service session.
Service* audoutGetServiceSession(void);
/// Gets the Service object for IAudioOut.
Service* audoutGetServiceSession_AudioOut(void);
/// Gets the Service for audout:a.
Service* audoutaGetServiceSession(void);
/// Gets the Service for audout:d.
Service* audoutdGetServiceSession(void);
Result audoutListAudioOuts(char *DeviceNames, s32 count, u32 *DeviceNamesCount);
Result audoutOpenAudioOut(const char *DeviceNameIn, char *DeviceNameOut, u32 SampleRateIn, u32 ChannelCountIn, u32 *SampleRateOut, u32 *ChannelCountOut, PcmFormat *Format, AudioOutState *State);
Result audoutGetAudioOutState(AudioOutState *State);
@ -83,3 +103,15 @@ u32 audoutGetSampleRate(void); ///< Supported sample rate (
u32 audoutGetChannelCount(void); ///< Supported channel count (2 channels).
PcmFormat audoutGetPcmFormat(void); ///< Supported PCM format (Int16).
AudioOutState audoutGetDeviceState(void); ///< Initial device state (stopped).
Result audoutaRequestSuspendOld(u64 pid, u64 delay, Handle* handle_out); // [1.0.0] - [4.0.0]
Result audoutaRequestResumeOld(u64 pid, u64 delay, Handle* handle_out); // [1.0.0] - [4.0.0]
Result audoutaRequestSuspend(u64 pid, u64 delay); // [4.0.0]+
Result audoutaRequestResume(u64 pid, u64 delay); // [4.0.0]+
Result audoutaGetProcessMasterVolume(u64 pid, float* volume_out);
Result audoutaSetProcessMasterVolume(u64 pid, u64 delay, float volume);
Result audoutaGetProcessRecordVolume(u64 pid, float* volume_out);
Result audoutaSetProcessRecordVolume(u64 pid, u64 delay, float volume);
Result audoutdRequestSuspendForDebug(u64 pid, u64 delay);
Result audoutdRequestResumeForDebug(u64 pid, u64 delay);

115
nx/source/services/aud.c Normal file
View File

@ -0,0 +1,115 @@
#define NX_SERVICE_ASSUME_NON_DOMAIN
#include "service_guard.h"
#include "services/aud.h"
#include "runtime/hosversion.h"
static Service g_audaSrv;
static Service g_auddSrv;
NX_GENERATE_SERVICE_GUARD(auda);
NX_GENERATE_SERVICE_GUARD(audd);
Result _audaInitialize(void) {
if (hosversionBefore(11,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return smGetService(&g_audaSrv, "aud:a");
}
void _audaCleanup(void) {
serviceClose(&g_audaSrv);
}
Result _auddInitialize(void) {
return smGetService(&g_auddSrv, "aud:d");
}
void _auddCleanup(void) {
serviceClose(&g_auddSrv);
}
Service* audaGetServiceSession(void) {
return &g_audaSrv;
}
Service* auddGetServiceSession(void) {
return &g_auddSrv;
}
Result audaRequestSuspendAudio(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audaSrv, 2, in);
}
Result audaRequestResumeAudio(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audaSrv, 3, in);
}
Result audaGetAudioOutputProcessMasterVolume(u64 pid, float* volume_out) {
return serviceDispatchInOut(&g_audaSrv, 4, pid, *volume_out);
}
Result audaSetAudioOutputProcessMasterVolume(u64 pid, u64 delay, float volume) {
const struct {
float volume;
u64 pid;
u64 delay;
} in = { volume, pid, delay };
return serviceDispatchIn(&g_audaSrv, 5, in);
}
Result audaGetAudioInputProcessMasterVolume(u64 pid, float* volume_out) {
return serviceDispatchInOut(&g_audaSrv, 6, pid, *volume_out);
}
Result audaSetAudioInputProcessMasterVolume(u64 pid, u64 delay, float volume) {
const struct {
float volume;
u64 pid;
u64 delay;
} in = { volume, pid, delay };
return serviceDispatchIn(&g_audaSrv, 7, in);
}
Result audaGetAudioOutputProcessRecordVolume(u64 pid, float* volume_out) {
return serviceDispatchInOut(&g_audaSrv, 8, pid, *volume_out);
}
Result audaSetAudioOutputProcessRecordVolume(u64 pid, u64 delay, float volume) {
const struct {
float volume;
u64 pid;
u64 delay;
} in = { volume, pid, delay };
return serviceDispatchIn(&g_audaSrv, 9, in);
}
Result auddRequestSuspendAudioForDebug(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_auddSrv, 0, in);
}
Result auddRequestResumeAudioForDebug(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_auddSrv, 1, in);
}

View File

@ -11,6 +11,8 @@
static Service g_audoutSrv;
static Service g_audoutIAudioOut;
static Service g_audoutaSrv;
static Service g_audoutdSrv;
static Event g_audoutBufferEvent;
@ -22,6 +24,8 @@ static AudioOutState g_deviceState = AudioOutState_Stopped;
static Result _audoutRegisterBufferEvent(Event *BufferEvent);
NX_GENERATE_SERVICE_GUARD(audout);
NX_GENERATE_SERVICE_GUARD(audouta);
NX_GENERATE_SERVICE_GUARD(audoutd);
Result _audoutInitialize(void) {
Result rc = 0;
@ -56,6 +60,28 @@ void _audoutCleanup(void) {
serviceClose(&g_audoutSrv);
}
Result _audoutaInitialize(void) {
if (hosversionAtLeast(11,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return smGetService(&g_audoutaSrv, "audout:a");
}
void _audoutaCleanup(void) {
serviceClose(&g_audoutaSrv);
}
Result _audoutdInitialize(void) {
if (hosversionAtLeast(11,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return smGetService(&g_audoutdSrv, "audout:d");
}
void _audoutdCleanup(void) {
serviceClose(&g_audoutdSrv);
}
Service* audoutGetServiceSession(void) {
return &g_audoutSrv;
}
@ -64,6 +90,14 @@ Service* audoutGetServiceSession_AudioOut(void) {
return &g_audoutIAudioOut;
}
Service* audoutaGetServiceSession(void) {
return &g_audoutaSrv;
}
Service* audoutdGetServiceSession(void) {
return &g_audoutdSrv;
}
u32 audoutGetSampleRate(void) {
return g_sampleRate;
}
@ -259,3 +293,103 @@ Result audoutGetAudioOutVolume(float *volume) {
return serviceDispatchOut(&g_audoutIAudioOut, 13, *volume);
}
Result audoutaRequestSuspendOld(u64 pid, u64 delay, Handle* handle_out) {
if (hosversionAtLeast(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchInOut(&g_audoutaSrv, 0, in, *handle_out);
}
Result audoutaRequestResumeOld(u64 pid, u64 delay, Handle* handle_out) {
if (hosversionAtLeast(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchInOut(&g_audoutaSrv, 1, in, *handle_out);
}
Result audoutaRequestSuspend(u64 pid, u64 delay) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audoutaSrv, 0, in);
}
Result audoutaRequestResume(u64 pid, u64 delay) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audoutaSrv, 1, in);
}
Result audoutaGetProcessMasterVolume(u64 pid, float* volume_out) {
return serviceDispatchInOut(&g_audoutaSrv, 2, pid, *volume_out);
}
Result audoutaSetProcessMasterVolume(u64 pid, u64 delay, float volume) {
const struct {
float volume;
u64 pid;
u64 delay;
} in = { volume, pid, delay };
return serviceDispatchIn(&g_audoutaSrv, 3, in);
}
Result audoutaGetProcessRecordVolume(u64 pid, float* volume_out) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_audoutaSrv, 4, pid, *volume_out);
}
Result audoutaSetProcessRecordVolume(u64 pid, u64 delay, float volume) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
float volume;
u64 pid;
u64 delay;
} in = { volume, pid, delay };
return serviceDispatchIn(&g_audoutaSrv, 5, in);
}
Result audoutdRequestSuspendForDebug(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audoutdSrv, 0, in);
}
Result audoutdRequestResumeForDebug(u64 pid, u64 delay) {
const struct {
u64 pid;
u64 delay;
} in = { pid, delay };
return serviceDispatchIn(&g_audoutdSrv, 1, in);
}