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.Collections.Generic;
5using System.Linq;
6using ManagedBass;
7using osu.Framework.Audio;
8using osu.Framework.IO.Stores;
9using osu.Framework.Threading;
10
11namespace osu.Framework.Tests.Audio
12{
13 /// <summary>
14 /// <see cref="AudioManager"/> that can simulate the loss of a device.
15 /// This will NOT work without a physical audio device!
16 /// </summary>
17 internal class AudioManagerWithDeviceLoss : AudioManager
18 {
19 public AudioManagerWithDeviceLoss(AudioThread audioThread, ResourceStore<byte[]> trackStore, ResourceStore<byte[]> sampleStore)
20 : base(audioThread, trackStore, sampleStore)
21 {
22 }
23
24 public volatile int CurrentDevice = Bass.DefaultDevice;
25
26 private volatile bool simulateLoss;
27
28 protected override bool InitBass(int device)
29 {
30 if (simulateLoss)
31 {
32 if (device != Bass.NoSoundDevice || !base.InitBass(device))
33 return false;
34
35 CurrentDevice = device;
36 return true;
37 }
38
39 if (!base.InitBass(device))
40 return false;
41
42 CurrentDevice = device;
43 return true;
44 }
45
46 protected override IEnumerable<DeviceInfo> EnumerateAllDevices()
47 {
48 var devices = base.EnumerateAllDevices();
49
50 if (simulateLoss)
51 devices = devices.Take(1);
52
53 return devices;
54 }
55
56 protected override bool IsCurrentDeviceValid()
57 {
58 if (simulateLoss)
59 return CurrentDevice == Bass.NoSoundDevice && base.IsCurrentDeviceValid();
60
61 return CurrentDevice != Bass.NoSoundDevice && base.IsCurrentDeviceValid();
62 }
63
64 public void SimulateDeviceLoss()
65 {
66 var current = CurrentDevice;
67
68 simulateLoss = true;
69
70 if (current != Bass.NoSoundDevice)
71 WaitForDeviceChange(current);
72 }
73
74 public void SimulateDeviceRestore()
75 {
76 var current = CurrentDevice;
77
78 simulateLoss = false;
79
80 if (current == Bass.NoSoundDevice)
81 WaitForDeviceChange(current);
82 }
83
84 public void WaitForDeviceChange(int? current = null, int timeoutMs = 5000)
85 {
86 current ??= CurrentDevice;
87
88 AudioThreadTest.WaitForOrAssert(() => CurrentDevice != current, $"Timed out while waiting for the device to change from {current}.", timeoutMs);
89 }
90 }
91}