|
25 | 25 | #ifndef LMMS_AUDIO_PORTAUDIO_H |
26 | 26 | #define LMMS_AUDIO_PORTAUDIO_H |
27 | 27 |
|
28 | | -#include <QObject> |
29 | | - |
30 | 28 | #include "lmmsconfig.h" |
31 | | -#include "ComboBoxModel.h" |
32 | 29 |
|
33 | 30 | #ifdef LMMS_HAVE_PORTAUDIO |
34 | 31 |
|
35 | | -# include <portaudio.h> |
36 | | - |
37 | | -# include "AudioDevice.h" |
38 | | -# include "AudioDeviceSetupWidget.h" |
39 | | - |
40 | | -# if defined paNeverDropInput || defined paNonInterleaved |
41 | | -# define PORTAUDIO_V19 |
42 | | -# else |
43 | | -# define PORTAUDIO_V18 |
44 | | -# endif |
| 32 | +#include <QComboBox> |
| 33 | +#include <QFormLayout> |
| 34 | +#include <QString> |
| 35 | +#include <QWidget> |
| 36 | +#include <portaudio.h> |
45 | 37 |
|
46 | | -#endif |
| 38 | +#include "AudioDevice.h" |
| 39 | +#include "AudioDeviceSetupWidget.h" |
47 | 40 |
|
| 41 | +namespace lmms { |
48 | 42 |
|
49 | | -namespace lmms |
| 43 | +namespace detail { |
| 44 | +class PortAudioInitializationGuard |
50 | 45 | { |
51 | | - |
52 | | -class AudioPortAudioSetupUtil : public QObject |
53 | | -{ |
54 | | -Q_OBJECT |
55 | | -public slots: |
56 | | - void updateBackends(); |
57 | | - void updateDevices(); |
58 | | - void updateChannels(); |
59 | | - |
60 | 46 | public: |
61 | | - ComboBoxModel m_backendModel; |
62 | | - ComboBoxModel m_deviceModel; |
63 | | -}; |
64 | | - |
65 | | - |
66 | | -#ifdef LMMS_HAVE_PORTAUDIO |
| 47 | + PortAudioInitializationGuard() |
| 48 | + : m_error(Pa_Initialize()) |
| 49 | + { |
| 50 | + if (m_error != paNoError) { throw std::runtime_error{"PortAudio: could not initialize"}; } |
| 51 | + } |
67 | 52 |
|
| 53 | + ~PortAudioInitializationGuard() |
| 54 | + { |
| 55 | + if (m_error == paNoError) { Pa_Terminate(); } |
| 56 | + } |
68 | 57 |
|
69 | | -namespace gui |
70 | | -{ |
71 | | -class ComboBox; |
72 | | -} |
| 58 | + PortAudioInitializationGuard(const PortAudioInitializationGuard&) = delete; |
| 59 | + PortAudioInitializationGuard(PortAudioInitializationGuard&&) = delete; |
| 60 | + PortAudioInitializationGuard& operator=(const PortAudioInitializationGuard&) = delete; |
| 61 | + PortAudioInitializationGuard& operator=(PortAudioInitializationGuard&&) = delete; |
73 | 62 |
|
| 63 | +private: |
| 64 | + PaError m_error = paNoError; |
| 65 | +}; |
| 66 | +} // namespace detail |
74 | 67 |
|
75 | 68 | class AudioPortAudio : public AudioDevice |
76 | 69 | { |
77 | 70 | public: |
78 | | - AudioPortAudio( bool & _success_ful, AudioEngine* audioEngine ); |
| 71 | + AudioPortAudio(bool& successful, AudioEngine* engine); |
79 | 72 | ~AudioPortAudio() override; |
80 | 73 |
|
81 | | - inline static QString name() |
82 | | - { |
83 | | - return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" ); |
84 | | - } |
85 | | - |
86 | | - int process_callback(const float* _inputBuffer, float* _outputBuffer, f_cnt_t _framesPerBuffer); |
87 | | - |
88 | | - class setupWidget : public gui::AudioDeviceSetupWidget |
89 | | - { |
90 | | - public: |
91 | | - setupWidget( QWidget * _parent ); |
92 | | - ~setupWidget() override; |
93 | | - |
94 | | - void saveSettings() override; |
95 | | - void show() override; |
96 | | - |
97 | | - private: |
98 | | - gui::ComboBox * m_backend; |
99 | | - gui::ComboBox * m_device; |
100 | | - AudioPortAudioSetupUtil m_setupUtil; |
| 74 | + AudioPortAudio(const AudioPortAudio&) = delete; |
| 75 | + AudioPortAudio(AudioPortAudio&&) = delete; |
| 76 | + AudioPortAudio& operator=(const AudioPortAudio&) = delete; |
| 77 | + AudioPortAudio& operator=(AudioPortAudio&&) = delete; |
101 | 78 |
|
102 | | - } ; |
103 | | - |
104 | | -private: |
105 | 79 | void startProcessing() override; |
106 | 80 | void stopProcessing() override; |
107 | 81 |
|
108 | | -#ifdef PORTAUDIO_V19 |
109 | | - static int _process_callback( const void *_inputBuffer, void * _outputBuffer, |
110 | | - unsigned long _framesPerBuffer, |
111 | | - const PaStreamCallbackTimeInfo * _timeInfo, |
112 | | - PaStreamCallbackFlags _statusFlags, |
113 | | - void *arg ); |
114 | | - |
115 | | -#else |
| 82 | + static auto name() -> QString { return QT_TRANSLATE_NOOP("AudioDeviceSetupWidget", "PortAudio"); } |
116 | 83 |
|
117 | | -#define paContinue 0 |
118 | | -#define paComplete 1 |
119 | | -#define Pa_GetDeviceCount Pa_CountDevices |
120 | | -#define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID |
121 | | -#define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID |
122 | | -#define Pa_IsStreamActive Pa_StreamActive |
123 | | - |
124 | | - static int _process_callback( void * _inputBuffer, void * _outputBuffer, |
125 | | - unsigned long _framesPerBuffer, PaTimestamp _outTime, void * _arg ); |
126 | | - |
127 | | - |
128 | | - using PaTime = double; |
129 | | - using PaDeviceIndex = PaDeviceID; |
130 | | - |
131 | | - using PaStreamParameters = struct |
132 | | - { |
133 | | - PaDeviceIndex device; |
134 | | - int channelCount; |
135 | | - PaSampleFormat sampleFormat; |
136 | | - PaTime suggestedLatency; |
137 | | - void *hostApiSpecificStreamInfo; |
138 | | - |
139 | | - } PaStreamParameters; |
140 | | -#endif // PORTAUDIO_V19 |
| 84 | +private: |
| 85 | + static int processCallback(const void* input, void* output, unsigned long frameCount, |
| 86 | + const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData); |
141 | 87 |
|
142 | | - PaStream * m_paStream; |
143 | | - PaStreamParameters m_outputParameters; |
144 | | - PaStreamParameters m_inputParameters; |
| 88 | + detail::PortAudioInitializationGuard m_initGuard; |
145 | 89 |
|
146 | | - bool m_wasPAInitError; |
| 90 | + PaStream* m_paStream = nullptr; |
| 91 | + std::vector<SampleFrame> m_outBuf; |
| 92 | + std::size_t m_outBufPos = 0; |
| 93 | +}; |
| 94 | +} // namespace lmms |
147 | 95 |
|
148 | | - SampleFrame* m_outBuf; |
149 | | - std::size_t m_outBufPos; |
150 | | - fpp_t m_outBufSize; |
| 96 | +namespace lmms::gui { |
| 97 | +class AudioPortAudioSetupWidget : public AudioDeviceSetupWidget |
| 98 | +{ |
| 99 | +public: |
| 100 | + AudioPortAudioSetupWidget(QWidget* parent); |
151 | 101 |
|
152 | | - bool m_stopped; |
| 102 | + void show() override; |
| 103 | + void saveSettings() override; |
153 | 104 |
|
154 | | -} ; |
| 105 | +private: |
| 106 | + class DeviceSelectorWidget; |
| 107 | + QComboBox* m_backendComboBox = nullptr; |
| 108 | + DeviceSelectorWidget* m_inputDevice = nullptr; |
| 109 | + DeviceSelectorWidget* m_outputDevice = nullptr; |
| 110 | +}; |
| 111 | +} // namespace lmms::gui |
155 | 112 |
|
156 | 113 | #endif // LMMS_HAVE_PORTAUDIO |
157 | 114 |
|
158 | | -} // namespace lmms |
159 | | - |
160 | 115 | #endif // LMMS_AUDIO_PORTAUDIO_H |
0 commit comments