mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-11 13:42:14 +02:00
Compare commits
4 Commits
dac63f2e07
...
ca7a9c4f85
Author | SHA1 | Date | |
---|---|---|---|
|
ca7a9c4f85 | ||
|
8cff58d5af | ||
|
3bd9654c54 | ||
|
dd1d520276 |
47
nx/include/switch/services/aud.h
Normal file
47
nx/include/switch/services/aud.h
Normal 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);
|
@ -10,6 +10,8 @@
|
|||||||
#include "../audio/audio.h"
|
#include "../audio/audio.h"
|
||||||
#include "../sf/service.h"
|
#include "../sf/service.h"
|
||||||
|
|
||||||
|
#define AUDOUT_MAX_DELAY (1000000000ULL)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AudioOutState_Started = 0,
|
AudioOutState_Started = 0,
|
||||||
AudioOutState_Stopped = 1,
|
AudioOutState_Stopped = 1,
|
||||||
@ -33,12 +35,30 @@ Result audoutInitialize(void);
|
|||||||
/// Exit audout.
|
/// Exit audout.
|
||||||
void audoutExit(void);
|
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.
|
/// Gets the Service object for the actual audout service session.
|
||||||
Service* audoutGetServiceSession(void);
|
Service* audoutGetServiceSession(void);
|
||||||
|
|
||||||
/// Gets the Service object for IAudioOut.
|
/// Gets the Service object for IAudioOut.
|
||||||
Service* audoutGetServiceSession_AudioOut(void);
|
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 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 audoutOpenAudioOut(const char *DeviceNameIn, char *DeviceNameOut, u32 SampleRateIn, u32 ChannelCountIn, u32 *SampleRateOut, u32 *ChannelCountOut, PcmFormat *Format, AudioOutState *State);
|
||||||
Result audoutGetAudioOutState(AudioOutState *State);
|
Result audoutGetAudioOutState(AudioOutState *State);
|
||||||
@ -83,3 +103,15 @@ u32 audoutGetSampleRate(void); ///< Supported sample rate (
|
|||||||
u32 audoutGetChannelCount(void); ///< Supported channel count (2 channels).
|
u32 audoutGetChannelCount(void); ///< Supported channel count (2 channels).
|
||||||
PcmFormat audoutGetPcmFormat(void); ///< Supported PCM format (Int16).
|
PcmFormat audoutGetPcmFormat(void); ///< Supported PCM format (Int16).
|
||||||
AudioOutState audoutGetDeviceState(void); ///< Initial device state (stopped).
|
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);
|
||||||
|
@ -36,6 +36,10 @@ static void _dynProcessRela(uintptr_t base, const Elf64_Rela* rela, size_t relas
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case R_AARCH64_NONE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case R_AARCH64_RELATIVE: {
|
case R_AARCH64_RELATIVE: {
|
||||||
u64* ptr = (u64*)(base + rela->r_offset);
|
u64* ptr = (u64*)(base + rela->r_offset);
|
||||||
*ptr = base + rela->r_addend;
|
*ptr = base + rela->r_addend;
|
||||||
@ -45,6 +49,25 @@ static void _dynProcessRela(uintptr_t base, const Elf64_Rela* rela, size_t relas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _dynProcessRelr(uintptr_t base, const Elf64_Relr* relr, size_t relrsz)
|
||||||
|
{
|
||||||
|
u64* ptr = NULL;
|
||||||
|
for (; relrsz--; relr++) {
|
||||||
|
if ((*relr & 1) == 0) {
|
||||||
|
ptr = (u64*)(base + *relr);
|
||||||
|
*ptr++ += base;
|
||||||
|
} else {
|
||||||
|
u64 bitmap = *relr >> 1;
|
||||||
|
while (bitmap) {
|
||||||
|
unsigned id = __builtin_ffsl(bitmap)-1;
|
||||||
|
bitmap &= ~(1UL << id);
|
||||||
|
ptr[id] += base;
|
||||||
|
}
|
||||||
|
ptr += 63;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
||||||
{
|
{
|
||||||
// Return early if MOD0 header has been invalidated
|
// Return early if MOD0 header has been invalidated
|
||||||
@ -65,6 +88,8 @@ void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
|||||||
// Extract relevant information from the ELF dynamic section
|
// Extract relevant information from the ELF dynamic section
|
||||||
const Elf64_Rela* rela = NULL;
|
const Elf64_Rela* rela = NULL;
|
||||||
size_t relasz = 0;
|
size_t relasz = 0;
|
||||||
|
const Elf64_Relr* relr = NULL;
|
||||||
|
size_t relrsz = 0;
|
||||||
for (; dyn->d_tag != DT_NULL; dyn++) {
|
for (; dyn->d_tag != DT_NULL; dyn++) {
|
||||||
switch (dyn->d_tag) {
|
switch (dyn->d_tag) {
|
||||||
case DT_RELA:
|
case DT_RELA:
|
||||||
@ -74,6 +99,14 @@ void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
|||||||
case DT_RELASZ:
|
case DT_RELASZ:
|
||||||
relasz = dyn->d_un.d_val / sizeof(Elf64_Rela);
|
relasz = dyn->d_un.d_val / sizeof(Elf64_Rela);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DT_RELR:
|
||||||
|
relr = (const Elf64_Relr*)(base + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_RELRSZ:
|
||||||
|
relrsz = dyn->d_un.d_val / sizeof(Elf64_Relr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +115,11 @@ void __nx_dynamic(uintptr_t base, const Mod0Header* mod0)
|
|||||||
_dynProcessRela(base, rela, relasz);
|
_dynProcessRela(base, rela, relasz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply RELR relocations if present
|
||||||
|
if (relr && relrsz) {
|
||||||
|
_dynProcessRelr(base, relr, relrsz);
|
||||||
|
}
|
||||||
|
|
||||||
// Return early if LNY0/LNY1 extensions are not present
|
// Return early if LNY0/LNY1 extensions are not present
|
||||||
if (mod0->magic_lny0 != 0x30594e4c || mod0->magic_lny1 != 0x31594e4c) { // LNY0, LNY1
|
if (mod0->magic_lny0 != 0x30594e4c || mod0->magic_lny1 != 0x31594e4c) { // LNY0, LNY1
|
||||||
return;
|
return;
|
||||||
|
115
nx/source/services/aud.c
Normal file
115
nx/source/services/aud.c
Normal 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);
|
||||||
|
}
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
static Service g_audoutSrv;
|
static Service g_audoutSrv;
|
||||||
static Service g_audoutIAudioOut;
|
static Service g_audoutIAudioOut;
|
||||||
|
static Service g_audoutaSrv;
|
||||||
|
static Service g_audoutdSrv;
|
||||||
|
|
||||||
static Event g_audoutBufferEvent;
|
static Event g_audoutBufferEvent;
|
||||||
|
|
||||||
@ -22,6 +24,8 @@ static AudioOutState g_deviceState = AudioOutState_Stopped;
|
|||||||
static Result _audoutRegisterBufferEvent(Event *BufferEvent);
|
static Result _audoutRegisterBufferEvent(Event *BufferEvent);
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(audout);
|
NX_GENERATE_SERVICE_GUARD(audout);
|
||||||
|
NX_GENERATE_SERVICE_GUARD(audouta);
|
||||||
|
NX_GENERATE_SERVICE_GUARD(audoutd);
|
||||||
|
|
||||||
Result _audoutInitialize(void) {
|
Result _audoutInitialize(void) {
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
@ -56,6 +60,28 @@ void _audoutCleanup(void) {
|
|||||||
serviceClose(&g_audoutSrv);
|
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) {
|
Service* audoutGetServiceSession(void) {
|
||||||
return &g_audoutSrv;
|
return &g_audoutSrv;
|
||||||
}
|
}
|
||||||
@ -64,6 +90,14 @@ Service* audoutGetServiceSession_AudioOut(void) {
|
|||||||
return &g_audoutIAudioOut;
|
return &g_audoutIAudioOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Service* audoutaGetServiceSession(void) {
|
||||||
|
return &g_audoutaSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* audoutdGetServiceSession(void) {
|
||||||
|
return &g_audoutdSrv;
|
||||||
|
}
|
||||||
|
|
||||||
u32 audoutGetSampleRate(void) {
|
u32 audoutGetSampleRate(void) {
|
||||||
return g_sampleRate;
|
return g_sampleRate;
|
||||||
}
|
}
|
||||||
@ -259,3 +293,103 @@ Result audoutGetAudioOutVolume(float *volume) {
|
|||||||
|
|
||||||
return serviceDispatchOut(&g_audoutIAudioOut, 13, *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);
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
*link:
|
*link:
|
||||||
+ -T %:getenv(DEVKITPRO /libnx/switch.ld) -pie --no-dynamic-linker --spare-dynamic-tags=0 --gc-sections -z text -z now -z nodynamic-undefined-weak --build-id=sha1 --nx-module-name
|
+ -T %:getenv(DEVKITPRO /libnx/switch.ld) -pie --no-dynamic-linker --spare-dynamic-tags=0 --gc-sections -z text -z now -z nodynamic-undefined-weak -z pack-relative-relocs --build-id=sha1 --nx-module-name
|
||||||
|
|
||||||
*startfile:
|
*startfile:
|
||||||
crti%O%s crtbegin%O%s --require-defined=main
|
crti%O%s crtbegin%O%s --require-defined=main
|
||||||
|
Loading…
Reference in New Issue
Block a user