Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
mock_audio_io_device.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <cassert>
7
8#include <juce_wrapper.h>
9
10namespace zrythm::test_helpers
11{
12class MockAudioIODevice : public juce::AudioIODevice
13{
14public:
15 MockAudioIODevice ()
16 : AudioIODevice ("Mock Audio Device", "Mock Audio"),
17 sample_rate_ (44100.0), buffer_size_ (512), is_running_ (false)
18 {
19 }
20
21 juce::StringArray getOutputChannelNames () override
22 {
23 return { "Left", "Right" };
24 }
25
26 juce::StringArray getInputChannelNames () override
27 {
28 return { "Input Left", "Input Right" };
29 }
30
31 juce::Array<double> getAvailableSampleRates () override
32 {
33 return { 44100.0, 48000.0, 96000.0 };
34 }
35
36 juce::Array<int> getAvailableBufferSizes () override
37 {
38 return { 128, 256, 512, 1024 };
39 }
40
41 juce::String open (
42 const juce::BigInteger &inputChannels,
43 const juce::BigInteger &outputChannels,
44 double requestedSampleRate,
45 int requestedBufferSize) override
46 {
47 sample_rate_ = requestedSampleRate;
48 buffer_size_ = requestedBufferSize;
49 return {};
50 }
51
52 void close () override { is_running_ = false; }
53
54 bool isOpen () override { return true; }
55
56 void start (juce::AudioIODeviceCallback * callback) override
57 {
58 if (callback != nullptr)
59 {
60 is_running_ = true;
61 this->callback_ = callback;
62 callback->audioDeviceAboutToStart (this);
63 }
64 }
65
66 void stop () override
67 {
68 if (callback_ != nullptr)
69 {
70 callback_->audioDeviceStopped ();
71 callback_ = nullptr;
72 }
73 is_running_ = false;
74 }
75
76 bool isPlaying () override { return is_running_; }
77
78 juce::String getLastError () override { return {}; }
79
80 int getCurrentBufferSizeSamples () override { return buffer_size_; }
81 double getCurrentSampleRate () override { return sample_rate_; }
82 int getCurrentBitDepth () override { return 16; }
83
84 juce::BigInteger getActiveOutputChannels () const override
85 {
86 juce::BigInteger channels;
87 channels.setRange (0, 2, true);
88 return channels;
89 }
90
91 juce::BigInteger getActiveInputChannels () const override
92 {
93 juce::BigInteger channels;
94 channels.setRange (0, 2, true);
95 return channels;
96 }
97
98 int getOutputLatencyInSamples () override { return 0; }
99 int getInputLatencyInSamples () override { return 0; }
100
101 int getDefaultBufferSize () override { return 256; }
102
103private:
104 double sample_rate_;
105 int buffer_size_;
106 bool is_running_;
107 juce::AudioIODeviceCallback * callback_ = nullptr;
108};
109
110class MockAudioIODeviceType : public juce::AudioIODeviceType
111{
112public:
113 MockAudioIODeviceType () : AudioIODeviceType ("Mock Audio") { }
114
115 void scanForDevices () override
116 {
117 // No-op for mock
118 }
119
120 juce::StringArray getDeviceNames (bool wantInputNames) const override
121 {
122 return { "Mock Audio Device" };
123 }
124
125 int getDefaultDeviceIndex (bool forInput) const override { return 0; }
126
127 int
128 getIndexOfDevice (juce::AudioIODevice * device, bool asInput) const override
129 {
130 return 0;
131 }
132
133 bool hasSeparateInputsAndOutputs () const override { return false; }
134
135 juce::AudioIODevice * createDevice (
136 const juce::String &outputDeviceName,
137 const juce::String &inputDeviceName) override
138 {
139 return new MockAudioIODevice ();
140 }
141};
142
143static inline std::unique_ptr<juce::AudioDeviceManager>
144create_audio_device_manager_with_dummy_device ()
145{
146 auto audio_device_manager = std::make_unique<juce::AudioDeviceManager> ();
147 audio_device_manager->addAudioDeviceType (
148 std::make_unique<MockAudioIODeviceType> ());
149
150 // Initialize with a dummy audio device setup for testing
151 juce::AudioDeviceManager::AudioDeviceSetup setup;
152 setup.sampleRate = 48000.0;
153 setup.bufferSize = 256;
154 setup.inputDeviceName = "Mock Audio Device";
155 setup.outputDeviceName = "Mock Audio Device";
156 const auto error = audio_device_manager->setAudioDeviceSetup (setup, true);
157 assert (error.isEmpty ());
158 audio_device_manager->initialise (0, 2, nullptr, true, {}, nullptr);
159 // Need to call this again for the setup to take effect...
160 // https://forum.juce.com/t/setaudiodevicesetup/3275
161 audio_device_manager->setAudioDeviceSetup (setup, true);
162 return audio_device_manager;
163}
164}