summaryrefslogtreecommitdiffstats
path: root/src/audio_core/audio_manager.h
blob: 8cbd95e22e3f93bdee96b10ae513879f78c2fb27 (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
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>
#include <atomic>
#include <functional>
#include <mutex>
#include <thread>

#include "audio_core/audio_event.h"
#include "core/hle/service/audio/errors.h"

namespace Core {
class System;
}

namespace AudioCore {

namespace AudioOut {
class Manager;
}

namespace AudioIn {
class Manager;
}

/**
 * The AudioManager's main purpose is to wait for buffer events for the audio in and out managers,
 * and call an associated callback to release buffers.
 *
 * Execution pattern is:
 *     Buffers appended ->
 *     Buffers queued and played by the backend stream ->
 *     When consumed, set the corresponding manager event and signal the audio manager ->
 *     Consumed buffers are released, game is signalled ->
 *     Game appends more buffers.
 *
 * This is only used by audio in and audio out.
 */
class AudioManager {
    using BufferEventFunc = std::function<void()>;

public:
    explicit AudioManager(Core::System& system);

    /**
     * Shutdown the audio manager.
     */
    void Shutdown();

    /**
     * Register the out manager, keeping a function to be called when the out event is signalled.
     *
     * @param buffer_func - Function to be called on signal.
     * @return Result code.
     */
    Result SetOutManager(BufferEventFunc buffer_func);

    /**
     * Register the in manager, keeping a function to be called when the in event is signalled.
     *
     * @param buffer_func - Function to be called on signal.
     * @return Result code.
     */
    Result SetInManager(BufferEventFunc buffer_func);

    /**
     * Set an event to signalled, and signal the thread.
     *
     * @param type      - Manager type to set.
     * @param signalled - Set the event to true or false?
     */
    void SetEvent(Event::Type type, bool signalled);

private:
    /**
     * Main thread, waiting on a manager signal and calling the registered function.
     */
    void ThreadFunc();

    /// Core system
    Core::System& system;
    /// Have sessions started palying?
    bool sessions_started{};
    /// Is the main thread running?
    std::atomic<bool> running{};
    /// Unused
    bool needs_update{};
    /// Events to be set and signalled
    Event events{};
    /// Callbacks for each manager
    std::array<BufferEventFunc, 3> buffer_events{};
    /// General lock
    std::mutex lock{};
    /// Main thread for waiting and callbacks
    std::jthread thread;
};

} // namespace AudioCore