aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioRendererManager.cs
blob: 7138d27ce87333d1da8508dbfa69d66a97182e41 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using Ryujinx.Audio.Renderer.Device;
using Ryujinx.Audio.Renderer.Server;
using Ryujinx.Common.Logging;
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Applet;
using Ryujinx.Horizon.Sdk.Sf;

namespace Ryujinx.Horizon.Sdk.Audio.Detail
{
    partial class AudioRendererManager : IAudioRendererManager
    {
        private const uint InitialRevision = ('R' << 0) | ('E' << 8) | ('V' << 16) | ('1' << 24);

        private readonly Ryujinx.Audio.Renderer.Server.AudioRendererManager _impl;
        private readonly VirtualDeviceSessionRegistry _registry;

        public AudioRendererManager(Ryujinx.Audio.Renderer.Server.AudioRendererManager impl, VirtualDeviceSessionRegistry registry)
        {
            _impl = impl;
            _registry = registry;
        }

        [CmifCommand(0)]
        public Result OpenAudioRenderer(
            out IAudioRenderer renderer,
            AudioRendererParameterInternal parameter,
            [CopyHandle] int workBufferHandle,
            [CopyHandle] int processHandle,
            ulong workBufferSize,
            AppletResourceUserId appletResourceId,
            [ClientProcessId] ulong pid)
        {
            var clientMemoryManager = HorizonStatic.Syscall.GetMemoryManagerByProcessHandle(processHandle);
            ulong workBufferAddress = HorizonStatic.Syscall.GetTransferMemoryAddress(workBufferHandle);

            Result result = new Result((int)_impl.OpenAudioRenderer(
                out var renderSystem,
                clientMemoryManager,
                ref parameter.Configuration,
                appletResourceId.Id,
                workBufferAddress,
                workBufferSize,
                (uint)processHandle));

            if (result.IsSuccess)
            {
                renderer = new AudioRenderer(renderSystem, workBufferHandle, processHandle);
            }
            else
            {
                renderer = null;

                HorizonStatic.Syscall.CloseHandle(workBufferHandle);
                HorizonStatic.Syscall.CloseHandle(processHandle);
            }

            return result;
        }

        [CmifCommand(1)]
        public Result GetWorkBufferSize(out long workBufferSize, AudioRendererParameterInternal parameter)
        {
            if (BehaviourContext.CheckValidRevision(parameter.Configuration.Revision))
            {
                workBufferSize = (long)Ryujinx.Audio.Renderer.Server.AudioRendererManager.GetWorkBufferSize(ref parameter.Configuration);

                Logger.Debug?.Print(LogClass.ServiceAudio, $"WorkBufferSize is 0x{workBufferSize:x16}.");

                return Result.Success;
            }
            else
            {
                workBufferSize = 0;

                Logger.Warning?.Print(LogClass.ServiceAudio, $"Library Revision REV{BehaviourContext.GetRevisionNumber(parameter.Configuration.Revision)} is not supported!");

                return AudioResult.UnsupportedRevision;
            }
        }

        [CmifCommand(2)]
        public Result GetAudioDeviceService(out IAudioDevice audioDevice, AppletResourceUserId appletResourceId)
        {
            audioDevice = new AudioDevice(_registry, appletResourceId, InitialRevision);

            return Result.Success;
        }

        [CmifCommand(3)] // 3.0.0+
        public Result OpenAudioRendererForManualExecution(
            out IAudioRenderer renderer,
            AudioRendererParameterInternal parameter,
            ulong workBufferAddress,
            [CopyHandle] int processHandle,
            ulong workBufferSize,
            AppletResourceUserId appletResourceId,
            [ClientProcessId] ulong pid)
        {
            var clientMemoryManager = HorizonStatic.Syscall.GetMemoryManagerByProcessHandle(processHandle);

            Result result = new Result((int)_impl.OpenAudioRenderer(
                out var renderSystem,
                clientMemoryManager,
                ref parameter.Configuration,
                appletResourceId.Id,
                workBufferAddress,
                workBufferSize,
                (uint)processHandle));

            if (result.IsSuccess)
            {
                renderer = new AudioRenderer(renderSystem, 0, processHandle);
            }
            else
            {
                renderer = null;

                HorizonStatic.Syscall.CloseHandle(processHandle);
            }

            return result;
        }

        [CmifCommand(4)] // 4.0.0+
        public Result GetAudioDeviceServiceWithRevisionInfo(out IAudioDevice audioDevice, AppletResourceUserId appletResourceId, uint revision)
        {
            audioDevice = new AudioDevice(_registry, appletResourceId, revision);

            return Result.Success;
        }
    }
}