A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using ManagedBass;
6using osu.Framework.Allocation;
7using osu.Framework.Platform;
8
9namespace osu.Framework.Audio.Callbacks
10{
11 /// <summary>
12 /// Wrapper on <see cref="FileProcedures"/> to provide functionality in <see cref="BassCallback"/>.
13 /// Can delegate to a class implementing the <see cref="IFileProcedures"/> interface.
14 /// </summary>
15 public class FileCallbacks : BassCallback
16 {
17 public FileProcedures Callbacks { get; private set; }
18
19 private FileProcedures instanceProcedures => new FileProcedures
20 {
21 Read = Read,
22 Close = Close,
23 Length = Length,
24 Seek = Seek
25 };
26
27 private static readonly FileProcedures static_procedures = new FileProcedures
28 {
29 Read = readCallback,
30 Close = closeCallback,
31 Length = lengthCallback,
32 Seek = seekCallback
33 };
34
35 private readonly IFileProcedures implementation;
36
37 private readonly FileProcedures procedures;
38
39 public FileCallbacks(IFileProcedures implementation)
40 {
41 Callbacks = RuntimeInfo.SupportsJIT ? instanceProcedures : static_procedures;
42 this.implementation = implementation;
43 procedures = null;
44 }
45
46 public FileCallbacks(FileProcedures procedures)
47 {
48 Callbacks = RuntimeInfo.SupportsJIT ? instanceProcedures : static_procedures;
49 this.procedures = procedures;
50 implementation = null;
51 }
52
53 public long Length(IntPtr user) => implementation?.Length(user) ?? procedures.Length(user);
54
55 public bool Seek(long offset, IntPtr user) => implementation?.Seek(offset, user) ?? procedures.Seek(offset, user);
56
57 public int Read(IntPtr buffer, int length, IntPtr user) => implementation?.Read(buffer, length, user) ?? procedures.Read(buffer, length, user);
58
59 public void Close(IntPtr user)
60 {
61 if (implementation != null)
62 implementation.Close(user);
63 else
64 procedures.Close(user);
65 }
66
67 [MonoPInvokeCallback(typeof(FileReadProcedure))]
68 private static int readCallback(IntPtr buffer, int length, IntPtr user)
69 {
70 var ptr = new ObjectHandle<FileCallbacks>(user);
71 if (ptr.GetTarget(out FileCallbacks target))
72 return target.Read(buffer, length, user);
73
74 return 0;
75 }
76
77 [MonoPInvokeCallback(typeof(FileCloseProcedure))]
78 private static void closeCallback(IntPtr user)
79 {
80 var ptr = new ObjectHandle<FileCallbacks>(user);
81 if (ptr.GetTarget(out FileCallbacks target))
82 target.Close(user);
83 }
84
85 [MonoPInvokeCallback(typeof(FileLengthProcedure))]
86 private static long lengthCallback(IntPtr user)
87 {
88 var ptr = new ObjectHandle<FileCallbacks>(user);
89 if (ptr.GetTarget(out FileCallbacks target))
90 return target.Length(user);
91
92 return 0;
93 }
94
95 [MonoPInvokeCallback(typeof(FileSeekProcedure))]
96 private static bool seekCallback(long offset, IntPtr user)
97 {
98 var ptr = new ObjectHandle<FileCallbacks>(user);
99 if (ptr.GetTarget(out FileCallbacks target))
100 return target.Seek(offset, user);
101
102 return false;
103 }
104 }
105}