#define NX_SERVICE_ASSUME_NON_DOMAIN #include "service_guard.h" #include "kernel/event.h" #include "runtime/hosversion.h" #include "services/audrec.h" NX_GENERATE_SERVICE_GUARD(audrec); static Service g_audrecUserSrv; Result _audrecInitialize(void) { return smGetService(&g_audrecUserSrv, "audrec:u"); } void _audrecCleanup(void) { serviceClose(&g_audrecUserSrv); } Service* audrecGetServiceSession(void) { return &g_audrecUserSrv; } Result audrecOpenFinalOutputRecorder(AudrecRecorder* recorder_out, FinalOutputRecorderParameter* param_in, u64 aruid, FinalOutputRecorderParameterInternal* param_out) { const struct { FinalOutputRecorderParameter param; u64 aruid; } in = { *param_in, aruid }; struct { FinalOutputRecorderParameterInternal param; } out; Result rc = serviceDispatchInOut(&g_audrecUserSrv, 0, in, out, .in_num_handles = 1, .in_handles = { CUR_PROCESS_HANDLE }, .out_num_objects = 1, .out_objects = &recorder_out->s, ); if (R_SUCCEEDED(rc)) { *param_out = out.param; } return rc; } Result audrecRecorderStart(AudrecRecorder* recorder) { return serviceDispatch(&recorder->s, 1); } Result audrecRecorderStop(AudrecRecorder* recorder) { return serviceDispatch(&recorder->s, 2); } Result audrecRecorderRegisterBufferEvent(AudrecRecorder* recorder, Event* out_event) { Handle tmp_handle; Result rc = serviceDispatch(&recorder->s, 4, .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, .out_handles = &tmp_handle, ); if (R_SUCCEEDED(rc)) { eventLoadRemote(out_event, tmp_handle, 1); } return rc; } Result audrecRecorderAppendFinalOutputRecorderBuffer(AudrecRecorder* recorder, u64 buffer_client_ptr, FinalOutputRecorderBuffer* param) { const struct { u64 buffer_client_ptr; } in = { buffer_client_ptr }; if (hosversionAtLeast(3,0,0)) { return serviceDispatchIn(&recorder->s, 8, in, .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In }, .buffers = { { param, sizeof(*param) } }, ); } else { return serviceDispatchIn(&recorder->s, 3, in, .buffer_attrs = { SfBufferAttr_In }, .buffers = { { param, sizeof(*param) } }, ); } } Result audrecRecorderGetReleasedFinalOutputRecorderBuffers(AudrecRecorder* recorder, u64* out_buffers, u64* inout_count, u64* out_released) { struct { u32 count; u32 padding; u64 released; } out; const struct { } in; Result rc; if (hosversionAtLeast(3,0,0)) { rc = serviceDispatchInOut(&recorder->s, 9, in, out, .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, .buffers = { { out_buffers, sizeof(u64) * (*inout_count) } }, ); } else { rc = serviceDispatchInOut(&recorder->s, 5, in, out, .buffer_attrs = { SfBufferAttr_Out }, .buffers = { { out_buffers, sizeof(u64) * (*inout_count) } }, ); } if (R_SUCCEEDED(rc)) { *inout_count = out.count; *out_released = out.released; } return rc; } void audrecRecorderClose(AudrecRecorder* recorder) { serviceClose(&recorder->s); }