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 void lock()
43 {
44 if (m_mainLoop)
45 pa_threaded_mainloop_lock(m: m_mainLoop.get());
46 }
47
48 void unlock()
49 {
50 if (m_mainLoop)
51 pa_threaded_mainloop_unlock(m: m_mainLoop.get());
52 }
53
54 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 bool waitForAsyncOperation(pa_operation *op);
61
62 bool isInMainLoop() const
63 {
64 return m_mainLoop && pa_threaded_mainloop_in_thread(m: m_mainLoop.get());
65 }
66
67 QList<QAudioDevice> availableDevices(QAudioDevice::Mode mode) const;
68 QByteArray defaultDevice(QAudioDevice::Mode mode) const;
69
70 pa_context_state_t getContextState();
71 bool contextIsGood();
72
73 QString serverName();
74
75Q_SIGNALS:
76 void audioInputsChanged();
77 void audioOutputsChanged();
78
79private Q_SLOTS:
80 void prepare();
81 void onContextFailed();
82
83private:
84 static void serverInfoCallback(pa_context *context, const pa_server_info *info, void *userdata);
85 static void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int isLast,
86 void *userdata);
87 static void sourceInfoCallback(pa_context *context, const pa_source_info *info, int isLast,
88 void *userdata);
89 static void eventCallback(pa_context *context, pa_subscription_event_type_t t, uint32_t index,
90 void *userdata);
91 static void contextStateCallbackInit(pa_context *context, void *userdata);
92 static void contextStateCallback(pa_context *c, void *userdata);
93
94 void updateDevices();
95 void release();
96
97 QMap<int, QAudioDevice> m_sinks;
98 QMap<int, QAudioDevice> m_sources;
99
100 QByteArray m_defaultSink;
101 QByteArray m_defaultSource;
102
103 mutable QReadWriteLock m_sinkLock;
104 mutable QReadWriteLock m_sourceLock;
105 mutable QReadWriteLock m_serverLock;
106
107 pa_mainloop_api *m_mainLoopApi{};
108 std::unique_ptr<pa_threaded_mainloop, QPulseAudioInternal::PaMainLoopDeleter> m_mainLoop;
109 PAContextHandle m_context;
110 bool m_prepared{};
111
112 QString m_serverName;
113 };
114
115QT_END_NAMESPACE
116
117#endif // QPULSEAUDIO_CONTEXTMANAGER_P_H
118

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