1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QPULSEAUDIO_CONTEXTMANAGER_P_H
5#define QPULSEAUDIO_CONTEXTMANAGER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qmap.h>
19#include <QtCore/qbytearray.h>
20#include <QtCore/qreadwritelock.h>
21#include <pulse/pulseaudio.h>
22#include "qpulsehelpers_p.h"
23#include <qaudioformat.h>
24
25QT_BEGIN_NAMESPACE
26
27class QPulseAudioContextManager : public QObject
28{
29 Q_OBJECT
30
31 using PAContextHandle = QPulseAudioInternal::PAContextHandle;
32 using PAOperationHandle = QPulseAudioInternal::PAOperationHandle;
33
34public:
35 explicit QPulseAudioContextManager(QObject *parent = nullptr);
36 ~QPulseAudioContextManager() override;
37
38 static QPulseAudioContextManager *instance();
39 pa_threaded_mainloop *mainloop() { return m_mainLoop.get(); }
40 pa_context *context() { return m_context.get(); }
41
42 inline void lock()
43 {
44 if (m_mainLoop)
45 pa_threaded_mainloop_lock(m: m_mainLoop.get());
46 }
47
48 inline void unlock()
49 {
50 if (m_mainLoop)
51 pa_threaded_mainloop_unlock(m: m_mainLoop.get());
52 }
53
54 inline void wait(const PAOperationHandle &op)
55 {
56 while (m_mainLoop && pa_operation_get_state(o: op.get()) == PA_OPERATION_RUNNING)
57 pa_threaded_mainloop_wait(m: m_mainLoop.get());
58 }
59
60 QList<QAudioDevice> availableDevices(QAudioDevice::Mode mode) const;
61 QByteArray defaultDevice(QAudioDevice::Mode mode) const;
62
63Q_SIGNALS:
64 void contextFailed();
65 void audioInputsChanged();
66 void audioOutputsChanged();
67
68private Q_SLOTS:
69 void prepare();
70 void onContextFailed();
71
72private:
73 static void serverInfoCallback(pa_context *context, const pa_server_info *info, void *userdata);
74 static void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int isLast,
75 void *userdata);
76 static void sourceInfoCallback(pa_context *context, const pa_source_info *info, int isLast,
77 void *userdata);
78 static void eventCallback(pa_context *context, pa_subscription_event_type_t t, uint32_t index,
79 void *userdata);
80 static void contextStateCallbackInit(pa_context *context, void *userdata);
81 static void contextStateCallback(pa_context *c, void *userdata);
82
83 void updateDevices();
84 void release();
85
86 QMap<int, QAudioDevice> m_sinks;
87 QMap<int, QAudioDevice> m_sources;
88
89 QByteArray m_defaultSink;
90 QByteArray m_defaultSource;
91
92 mutable QReadWriteLock m_sinkLock;
93 mutable QReadWriteLock m_sourceLock;
94 mutable QReadWriteLock m_serverLock;
95
96 pa_mainloop_api *m_mainLoopApi{};
97 std::unique_ptr<pa_threaded_mainloop, QPulseAudioInternal::PaMainLoopDeleter> m_mainLoop;
98 PAContextHandle m_context;
99 bool m_prepared{};
100 };
101
102QT_END_NAMESPACE
103
104#endif // QPULSEAUDIO_CONTEXTMANAGER_P_H
105

source code of qtmultimedia/src/multimedia/pulseaudio/qpulseaudio_contextmanager_p.h