mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 04:22:50 +02:00
audctl: Initial commit
This commit is contained in:
parent
f486127615
commit
a1ddefd3ca
65
nx/include/switch/services/audctl.h
Normal file
65
nx/include/switch/services/audctl.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AudioTarget_Invalid = 0,
|
||||||
|
AudioTarget_Speaker = 1,
|
||||||
|
AudioTarget_Headphone = 2,
|
||||||
|
AudioTarget_Tv = 3,
|
||||||
|
AudioTarget_UsbOutputDevice = 4,
|
||||||
|
} AudioTarget;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AudioOutputMode_Invalid = 0,
|
||||||
|
AudioOutputMode_Pcm1ch = 1,
|
||||||
|
AudioOutputMode_Pcm2ch = 2,
|
||||||
|
AudioOutputMode_Pcm6ch = 3,
|
||||||
|
AudioOutputMode_PcmAuto = 4,
|
||||||
|
} AudioOutputMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AudioForceMutePolicy_Disable = 0,
|
||||||
|
AudioForceMutePolicy_SpeakerMuteOnHeadphoneUnplugged = 1,
|
||||||
|
} AudioForceMutePolicy;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HeadphoneOutputLevelMode_Normal = 0,
|
||||||
|
HeadphoneOutputLevelMode_HighPower = 1,
|
||||||
|
} HeadphoneOutputLevelMode;
|
||||||
|
|
||||||
|
Result audctlInitialize(void);
|
||||||
|
void audctlExit(void);
|
||||||
|
Service* audctlGetServiceSession(void);
|
||||||
|
|
||||||
|
Result audctlGetTargetVolume(float* volume_out, AudioTarget target);
|
||||||
|
Result audctlSetTargetVolume(AudioTarget target, float volume);
|
||||||
|
Result audctlGetTargetVolumeMin(float* volume_out);
|
||||||
|
Result audctlGetTargetVolumeMax(float* volume_out);
|
||||||
|
Result audctlIsTargetMute(bool* mute_out, AudioTarget target);
|
||||||
|
Result audctlSetTargetMute(AudioTarget target, bool mute);
|
||||||
|
Result audctlIsTargetConnected(bool* connected_out, AudioTarget target);
|
||||||
|
Result audctlSetDefaultTarget(AudioTarget target, u64 fade_in_ns, u64 fade_out_ns);
|
||||||
|
Result audctlGetDefaultTarget(AudioTarget* target_out);
|
||||||
|
Result audctlGetAudioOutputMode(AudioOutputMode* mode_out, AudioTarget target);
|
||||||
|
Result audctlSetAudioOutputMode(AudioTarget target, AudioOutputMode mode);
|
||||||
|
Result audctlSetForceMutePolicy(AudioForceMutePolicy policy);
|
||||||
|
Result audctlGetForceMutePolicy(AudioForceMutePolicy* policy_out);
|
||||||
|
Result audctlGetOutputModeSetting(AudioOutputMode* mode_out, AudioTarget target);
|
||||||
|
Result audctlSetOutputModeSetting(AudioTarget target, AudioOutputMode mode);
|
||||||
|
Result audctlSetOutputTarget(AudioTarget target);
|
||||||
|
Result audctlSetInputTargetForceEnabled(bool enable);
|
||||||
|
Result audctlSetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode mode);
|
||||||
|
Result audctlGetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode* mode_out);
|
||||||
|
Result audctlAcquireAudioVolumeUpdateEventForPlayReport(Event* event_out);
|
||||||
|
Result audctlAcquireAudioOutputDeviceUpdateEventForPlayReport(Event* event_out);
|
||||||
|
Result audctlGetAudioOutputTargetForPlayReport(AudioTarget* target_out);
|
||||||
|
Result audctlNotifyHeadphoneVolumeWarningDisplayedEvent(void);
|
||||||
|
Result audctlSetSystemOutputMasterVolume(float volume);
|
||||||
|
Result audctlGetSystemOutputMasterVolume(float* volume_out);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
342
nx/source/services/audctl.c
Normal file
342
nx/source/services/audctl.c
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "kernel/event.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
#include "services/audctl.h"
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(audctl);
|
||||||
|
|
||||||
|
static Service g_audctlSrv;
|
||||||
|
|
||||||
|
Result _audctlInitialize(void) {
|
||||||
|
return smGetService(&g_audctlSrv, "audctl");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _audctlCleanup(void) {
|
||||||
|
serviceClose(&g_audctlSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* audctlGetServiceSession(void) {
|
||||||
|
return &g_audctlSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetTargetVolume(float* volume_out, AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float volume;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_audctlSrv, 0, in, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*volume_out = out.volume;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetTargetVolume(AudioTarget target, float volume) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
float volume;
|
||||||
|
} in = { target, volume };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 1, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetTargetVolumeMin(float* volume_out) {
|
||||||
|
struct {
|
||||||
|
float volume;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 2, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*volume_out = out.volume;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetTargetVolumeMax(float* volume_out) {
|
||||||
|
struct {
|
||||||
|
float volume;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 3, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*volume_out = out.volume;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlIsTargetMute(bool* mute_out, AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 mute;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_audctlSrv, 4, in, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*mute_out = out.mute;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetTargetMute(AudioTarget target, bool mute) {
|
||||||
|
const struct {
|
||||||
|
u32 mute;
|
||||||
|
u32 target;
|
||||||
|
} in = { mute, target };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 5, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlIsTargetConnected(bool* connected_out, AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 connected;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_audctlSrv, 6, in, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*connected_out = out.connected;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetDefaultTarget(AudioTarget target, u64 fade_in_ns, u64 fade_out_ns) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
u32 padding;
|
||||||
|
u64 fade_in_ns;
|
||||||
|
u64 fade_out_ns;
|
||||||
|
} in = { target, 0, fade_in_ns, fade_out_ns };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 7, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetDefaultTarget(AudioTarget* target_out) {
|
||||||
|
struct {
|
||||||
|
u32 target;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 8, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*target_out = out.target;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetAudioOutputMode(AudioOutputMode* mode_out, AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 mode;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_audctlSrv, 9, in, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*mode_out = out.mode;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetAudioOutputMode(AudioTarget target, AudioOutputMode mode) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
u32 mode;
|
||||||
|
} in = { target, mode };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 10, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetForceMutePolicy(AudioForceMutePolicy policy) {
|
||||||
|
const struct {
|
||||||
|
u32 policy;
|
||||||
|
} in = { policy };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 11, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetForceMutePolicy(AudioForceMutePolicy* policy_out) {
|
||||||
|
struct {
|
||||||
|
u32 policy;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 12, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*policy_out = out.policy;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetOutputModeSetting(AudioOutputMode* mode_out, AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 mode;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_audctlSrv, 13, in, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*mode_out = out.mode;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetOutputModeSetting(AudioTarget target, AudioOutputMode mode) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
u32 mode;
|
||||||
|
} in = { target, mode };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 14, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetOutputTarget(AudioTarget target) {
|
||||||
|
const struct {
|
||||||
|
u32 target;
|
||||||
|
} in = { target };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 15, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetInputTargetForceEnabled(bool enable) {
|
||||||
|
const struct {
|
||||||
|
bool enable;
|
||||||
|
} in = { enable };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 16, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode mode) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
u32 mode;
|
||||||
|
} in = { mode };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 17, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode* mode_out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 mode;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 18, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*mode_out = out.mode;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlAcquireAudioVolumeUpdateEventForPlayReport(Event* event_out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
Handle tmp_handle;
|
||||||
|
|
||||||
|
Result rc = serviceDispatch(&g_audctlSrv, 19,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = &tmp_handle,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
eventLoadRemote(event_out, tmp_handle, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlAcquireAudioOutputDeviceUpdateEventForPlayReport(Event* event_out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
Handle tmp_handle;
|
||||||
|
|
||||||
|
Result rc = serviceDispatch(&g_audctlSrv, 20,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = &tmp_handle,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
eventLoadRemote(event_out, tmp_handle, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetAudioOutputTargetForPlayReport(AudioTarget* target_out) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 target;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 21, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*target_out = out.target;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlNotifyHeadphoneVolumeWarningDisplayedEvent(void) {
|
||||||
|
if (hosversionBefore(3,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatch(&g_audctlSrv, 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlSetSystemOutputMasterVolume(float volume) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
float volume;
|
||||||
|
} in = { volume };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_audctlSrv, 23, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result audctlGetSystemOutputMasterVolume(float* volume_out) {
|
||||||
|
if (hosversionBefore(4,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float volume;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchOut(&g_audctlSrv, 24, out);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*volume_out = out.volume;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user