this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

CoreAudio: PulseAudio recording support

+332 -89
+2 -1
src/CoreAudio/CoreAudio/AudioHardware.cpp
··· 21 21 #include "AudioHardwareImpl.h" 22 22 #include "pulse/AudioHardwareImplPA.h" 23 23 #include "pulse/AudioHardwareImplPAOutput.h" 24 + #include "pulse/AudioHardwareImplPAInput.h" 24 25 #include <CoreServices/MacErrors.h> 25 26 #include <dispatch/dispatch.h> 26 27 #include <memory> ··· 36 37 // TODO: Or ALSA 37 38 g_objects.insert(std::make_pair(kAudioObjectSystemObject, std::make_unique<AudioHardwareImplPA>(kAudioObjectSystemObject))); 38 39 g_objects.insert(std::make_pair(kAudioObjectSystemObject + 1, std::make_unique<AudioHardwareImplPAOutput>(kAudioObjectSystemObject + 1))); 39 - // TODO: PA input 40 + g_objects.insert(std::make_pair(kAudioObjectSystemObject + 2, std::make_unique<AudioHardwareImplPAInput>(kAudioObjectSystemObject + 2))); 40 41 }); 41 42 } 42 43
+6 -2
src/CoreAudio/CoreAudio/AudioHardwareStream.cpp
··· 20 20 #include "AudioHardwareStream.h" 21 21 #include "AudioHardwareImpl.h" 22 22 23 - AudioHardwareStream::AudioHardwareStream(AudioHardwareImpl* hw) 23 + AudioHardwareStream::AudioHardwareStream(AudioHardwareImpl* hw, bool needBuffer) 24 24 : m_hw(hw) 25 25 { 26 26 m_bufferSize = hw->bufferSize(); 27 - m_buffer = new uint8_t[m_bufferSize]; 27 + 28 + if (needBuffer) 29 + m_buffer = new uint8_t[m_bufferSize]; 30 + else 31 + m_buffer = nullptr; 28 32 } 29 33 30 34 AudioHardwareStream::~AudioHardwareStream()
+1 -1
src/CoreAudio/CoreAudio/AudioHardwareStream.h
··· 26 26 class AudioHardwareStream 27 27 { 28 28 public: 29 - AudioHardwareStream(AudioHardwareImpl* hw); 29 + AudioHardwareStream(AudioHardwareImpl* hw, bool needBuffer = true); 30 30 virtual ~AudioHardwareStream(); 31 31 32 32 virtual void stop(void(^cbDone)()) = 0;
+2
src/CoreAudio/CoreAudio/CMakeLists.txt
··· 8 8 AudioHardware.cpp 9 9 AudioHardwareImpl.cpp 10 10 pulse/AudioHardwareImplPA.cpp 11 + pulse/AudioHardwareImplPAInput.cpp 11 12 pulse/AudioHardwareImplPAOutput.cpp 12 13 AudioHardwareStream.cpp 13 14 pulse/AudioHardwareStreamPA.cpp 15 + pulse/AudioHardwareStreamPAInput.cpp 14 16 pulse/AudioHardwareStreamPAOutput.cpp 15 17 pulse/PADispatchMainLoop.cpp 16 18 )
+2 -2
src/CoreAudio/CoreAudio/pulse/AudioHardwareImplPA.cpp
··· 112 112 pa_context_state_t state = pa_context_get_state(c); 113 113 if (state == PA_CONTEXT_READY) 114 114 { 115 - std::cout << "PA_CONTEXT_READY\n"; 115 + // std::cout << "PA_CONTEXT_READY\n"; 116 116 117 117 cb(c); 118 118 Block_release(cb); ··· 122 122 } 123 123 else if (state == PA_CONTEXT_FAILED) 124 124 { 125 - std::cout << "PA_CONTEXT_FAILED\n"; 125 + std::cerr << "PulseAudio error: PA_CONTEXT_FAILED\n"; 126 126 127 127 cb(nullptr); 128 128 Block_release(cb);
+71
src/CoreAudio/CoreAudio/pulse/AudioHardwareImplPAInput.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "AudioHardwareImplPAInput.h" 21 + #include "AudioHardwareStreamPAInput.h" 22 + 23 + AudioHardwareImplPAInput::AudioHardwareImplPAInput(AudioObjectID myId) 24 + : AudioHardwareImplPA(myId) 25 + { 26 + m_uid = CFSTR("PulseAudio:Input"); 27 + } 28 + 29 + OSStatus AudioHardwareImplPAInput::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 30 + const void* inQualifierData, UInt32* ioDataSize, void* outData) 31 + { 32 + if (inAddress->mSelector == kAudioDevicePropertyStreamConfiguration) 33 + { 34 + size_t size = sizeof(AudioBufferList); 35 + 36 + if (inAddress->mScope == kAudioDevicePropertyScopeOutput) 37 + size += 1* sizeof(AudioBuffer); 38 + 39 + // Number of returned buffers is the number of channels 40 + if (AudioBufferList* abl = static_cast<AudioBufferList*>(outData); abl && *ioDataSize >= size) 41 + { 42 + if (inAddress->mScope == kAudioDevicePropertyScopeOutput) 43 + { 44 + abl->mNumberBuffers = 1; 45 + abl->mBuffers[0].mNumberChannels = 2; 46 + 47 + // TODO: Is the below stuff ever used? How? 48 + abl->mBuffers[0].mData = nullptr; 49 + abl->mBuffers[0].mDataByteSize = 0; 50 + } 51 + else 52 + abl->mNumberBuffers = 0; 53 + } 54 + 55 + *ioDataSize = size; 56 + return kAudioHardwareNoError; 57 + } 58 + 59 + return AudioHardwareImplPA::getPropertyData(inAddress, inQualifierDataSize, inQualifierData, ioDataSize, outData); 60 + } 61 + 62 + OSStatus AudioHardwareImplPAInput::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 63 + const void* inQualifierData, UInt32 inDataSize, const void* inData) 64 + { 65 + return AudioHardwareImplPA::setPropertyData(inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData); 66 + } 67 + 68 + AudioHardwareStream* AudioHardwareImplPAInput::createStream(AudioDeviceIOProc callback, void* clientData) 69 + { 70 + return new AudioHardwareStreamPAInput(this, callback, clientData); 71 + }
+39
src/CoreAudio/CoreAudio/pulse/AudioHardwareImplPAInput.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef AUDIOHARDWAREIMPLPAINPUT_H 21 + #define AUDIOHARDWAREIMPLPAINPUT_H 22 + #include "AudioHardwareImplPA.h" 23 + 24 + class AudioHardwareImplPAInput : public AudioHardwareImplPA 25 + { 26 + public: 27 + AudioHardwareImplPAInput(AudioObjectID myId); 28 + 29 + OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 30 + const void* inQualifierData, UInt32* ioDataSize, void* outData) override; 31 + 32 + OSStatus setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 33 + const void* inQualifierData, UInt32 inDataSize, const void* inData) override; 34 + protected: 35 + AudioHardwareStream* createStream(AudioDeviceIOProc callback, void* clientData) override; 36 + }; 37 + 38 + #endif 39 +
-4
src/CoreAudio/CoreAudio/pulse/AudioHardwareImplPAOutput.cpp
··· 26 26 m_uid = CFSTR("PulseAudio:Output"); 27 27 } 28 28 29 - AudioHardwareImplPAOutput::~AudioHardwareImplPAOutput() 30 - { 31 - } 32 - 33 29 OSStatus AudioHardwareImplPAOutput::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 34 30 const void* inQualifierData, UInt32* ioDataSize, void* outData) 35 31 {
-1
src/CoreAudio/CoreAudio/pulse/AudioHardwareImplPAOutput.h
··· 25 25 { 26 26 public: 27 27 AudioHardwareImplPAOutput(AudioObjectID myId); 28 - ~AudioHardwareImplPAOutput(); 29 28 30 29 OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 31 30 const void* inQualifierData, UInt32* ioDataSize, void* outData) override;
+57 -1
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPA.cpp
··· 18 18 */ 19 19 20 20 #include "AudioHardwareStreamPA.h" 21 + #include "AudioHardwareImplPA.h" 22 + #include <iostream> 21 23 22 24 AudioHardwareStreamPA::AudioHardwareStreamPA(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData) 23 - : AudioHardwareStream(hw), m_callback(callback), m_clientData(clientData) 25 + : AudioHardwareStream(hw, false), m_callback(callback), m_clientData(clientData) 24 26 { 27 + AudioHardwareImplPA::getPAContext(^(pa_context* context) { 28 + if (!context) 29 + { 30 + std::cerr << "Failed to get PulseAudio context\n"; 31 + return; 32 + } 33 + 34 + pa_sample_spec spec; 35 + 36 + spec.rate = 44100; 37 + spec.channels = 2; 38 + #if defined(__BIG_ENDIAN__) 39 + spec.format = PA_SAMPLE_FLOAT32BE; 40 + #elif defined(__LITTLE_ENDIAN__) 41 + spec.format = PA_SAMPLE_FLOAT32LE; 42 + #else 43 + # error Unknown endianess! 44 + #endif 45 + if (!pa_sample_spec_valid(&spec)) 46 + { 47 + std::cerr << "Failed to create a valid pa_sample_spec\n"; 48 + return; 49 + } 50 + 51 + m_stream = pa_stream_new(context, "CoreAudio", &spec, nullptr); 25 52 53 + //pa_stream_set_state_callback(m_stream, [](pa_stream *s, void *userdata) { 54 + //std::cout << "Stream state: " << pa_stream_get_state(s) << std::endl; 55 + /*if (pa_stream_get_state(s) == 2) 56 + pa_stream_trigger(s, [](pa_stream *s, int success, void *userdata){}, nullptr);*/ 57 + //}, this); 58 + 59 + //pa_stream_set_underflow_callback(m_stream, [](pa_stream *s, void *userdata) { 60 + // std::cerr << "Underflow!\n"; 61 + //}, nullptr); 62 + 63 + start(); 64 + }); 26 65 } 27 66 28 67 AudioHardwareStreamPA::~AudioHardwareStreamPA() 29 68 { 69 + if (m_stream) 70 + pa_stream_unref(m_stream); 71 + } 30 72 73 + void AudioHardwareStreamPA::stop(void(^cbDone)()) 74 + { 75 + // std::cerr << "AudioHardwareStreamPA::stop()\n"; 76 + m_cbDone = Block_copy(cbDone); 77 + 78 + pa_stream_cork(m_stream, true, [](pa_stream*, int, void* self) { 79 + AudioHardwareStreamPA* This = static_cast<AudioHardwareStreamPA*>(self); 80 + 81 + pa_stream_disconnect(This->m_stream); 82 + This->m_cbDone(); 83 + 84 + Block_release(This->m_cbDone); 85 + }, this); 31 86 } 87 +
+6
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPA.h
··· 29 29 public: 30 30 AudioHardwareStreamPA(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData); 31 31 ~AudioHardwareStreamPA(); 32 + 33 + void stop(void(^cbDone)()) override; 34 + protected: 35 + virtual void start() = 0; 32 36 protected: 33 37 AudioDeviceIOProc m_callback; 34 38 void* m_clientData; 39 + pa_stream* m_stream; 40 + void(^m_cbDone)(); 35 41 }; 36 42 37 43 #endif /* AUDIOHARDWARESTREAMPA_H */
+99
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPAInput.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "AudioHardwareStreamPAInput.h" 21 + #include "AudioHardwareImplPA.h" 22 + #include <iostream> 23 + #include <vector> 24 + 25 + AudioHardwareStreamPAInput::AudioHardwareStreamPAInput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData) 26 + : AudioHardwareStreamPA(hw, callback, clientData) 27 + { 28 + // m_dump.open("/tmp/dump.raw", std::ios_base::out | std::ios_base::binary); 29 + } 30 + 31 + void AudioHardwareStreamPAInput::paStreamReadCB(pa_stream* s, size_t length, void* self) 32 + { 33 + AudioHardwareStreamPAInput* This = static_cast<AudioHardwareStreamPAInput*>(self); 34 + 35 + AudioTimeStamp fake = {0}; 36 + AudioBufferList* abl = static_cast<AudioBufferList*>(alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer))); 37 + std::vector<uint8_t> hole; 38 + 39 + // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB()\n"; 40 + 41 + while (true) 42 + { 43 + abl->mNumberBuffers = 1; 44 + abl->mBuffers[0].mNumberChannels = 2; 45 + 46 + size_t nbytes; 47 + 48 + int rv = pa_stream_peek(This->m_stream, (const void**) &abl->mBuffers[0].mData, &nbytes); 49 + 50 + if (rv < 0 || !nbytes) 51 + { 52 + // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB(): peek rv=" << rv << ", nbytes=" << nbytes << std::endl; 53 + break; 54 + } 55 + 56 + if (nbytes && !abl->mBuffers[0].mData) 57 + { 58 + // "If there is a hole, data will be NULL and nbytes will contain the length of the hole." 59 + hole.resize(nbytes); 60 + abl->mBuffers[0].mData = hole.data(); 61 + } 62 + abl->mBuffers[0].mDataByteSize = nbytes; 63 + 64 + // This->m_dump.write((char*) abl->mBuffers[0].mData, nbytes); 65 + // This->m_dump.flush(); 66 + 67 + // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB(): bytes=" << nbytes << std::endl; 68 + OSStatus status = This->m_callback(This->m_hw->id(), &fake, abl, &fake, nullptr, nullptr, This->m_clientData); 69 + 70 + pa_stream_drop(This->m_stream); 71 + 72 + if (status != noErr) 73 + { 74 + pa_stream_cork(This->m_stream, true, [](pa_stream*, int, void*) {}, nullptr); 75 + break; 76 + } 77 + } 78 + } 79 + 80 + void AudioHardwareStreamPAInput::start() 81 + { 82 + struct pa_buffer_attr battr; 83 + 84 + battr.fragsize = uint32_t(-1); 85 + battr.maxlength = uint32_t(m_bufferSize); 86 + battr.minreq = uint32_t(-1); 87 + battr.prebuf = battr.maxlength; 88 + battr.tlength = uint32_t(-1); 89 + 90 + // std::cout << "AudioHardwareStreamPAInput::start()\n"; 91 + 92 + pa_stream_set_read_callback(m_stream, paStreamReadCB, this); 93 + 94 + int rv = pa_stream_connect_record(m_stream, nullptr, &battr, 95 + pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE) 96 + ); 97 + 98 + // std::cout << "AudioHardwareStreamPAInput::start() rv = " << rv << std::endl; 99 + }
+37
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPAInput.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef AUDIOHARDWARESTREAMPAINPUT_H 21 + #define AUDIOHARDWARESTREAMPAINPUT_H 22 + #include "AudioHardwareStreamPA.h" 23 + #include <fstream> 24 + 25 + class AudioHardwareStreamPAInput : public AudioHardwareStreamPA 26 + { 27 + public: 28 + AudioHardwareStreamPAInput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData); 29 + private: 30 + void start() override; 31 + static void paStreamReadCB(pa_stream* s, size_t length, void* self); 32 + 33 + // std::ofstream m_dump; 34 + }; 35 + 36 + #endif /* AUDIOHARDWARESTREAMPA_H */ 37 +
+9 -70
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPAOutput.cpp
··· 25 25 AudioHardwareStreamPAOutput::AudioHardwareStreamPAOutput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData) 26 26 : AudioHardwareStreamPA(hw, callback, clientData) 27 27 { 28 - // TODO: Abstract this into our superclass 29 - AudioHardwareImplPA::getPAContext(^(pa_context* context) { 30 - if (!context) 31 - { 32 - std::cerr << "Failed to get PulseAudio context\n"; 33 - return; 34 - } 35 - 36 - pa_sample_spec spec; 37 - 38 - spec.rate = 44100; 39 - spec.channels = 2; 40 - #if defined(__BIG_ENDIAN__) 41 - spec.format = PA_SAMPLE_FLOAT32BE; 42 - #elif defined(__LITTLE_ENDIAN__) 43 - spec.format = PA_SAMPLE_FLOAT32LE; 44 - #else 45 - # error Unknown endianess! 46 - #endif 47 - if (!pa_sample_spec_valid(&spec)) 48 - { 49 - std::cerr << "Failed to create a valid pa_sample_spec\n"; 50 - return; 51 - } 52 - 53 - m_stream = pa_stream_new(context, "CoreAudio", &spec, nullptr); 54 - 55 - //pa_stream_set_state_callback(m_stream, [](pa_stream *s, void *userdata) { 56 - //std::cout << "Stream state: " << pa_stream_get_state(s) << std::endl; 57 - /*if (pa_stream_get_state(s) == 2) 58 - pa_stream_trigger(s, [](pa_stream *s, int success, void *userdata){}, nullptr);*/ 59 - //}, this); 60 - pa_stream_set_write_callback(m_stream, paStreamWriteCB, this); 61 - //pa_stream_set_underflow_callback(m_stream, [](pa_stream *s, void *userdata) { 62 - // std::cerr << "Underflow!\n"; 63 - //}, nullptr); 64 - 65 - start(); 66 - }); 67 - } 68 - 69 - AudioHardwareStreamPAOutput::~AudioHardwareStreamPAOutput() 70 - { 71 - // std::cout << "AudioHardwareStreamPAOutput::~AudioHardwareStreamPAOutput()\n"; 72 - if (m_stream) 73 - pa_stream_unref(m_stream); 74 28 } 75 29 76 30 void AudioHardwareStreamPAOutput::paStreamWriteCB(pa_stream* s, size_t length, void* self) ··· 81 35 AudioTimeStamp fake = {0}; 82 36 AudioBufferList* abl = static_cast<AudioBufferList*>(alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer))); 83 37 84 - // Non-interleaved (planar) audio would have multiple buffers, but PA doesn't even support that AFAIK 85 - abl->mNumberBuffers = 1; 86 - 87 - abl->mBuffers[0].mNumberChannels = 2; 88 - 89 - /*size_t nbytes = This->m_bufferSize; 90 - pa_stream_begin_write(This->m_stream, (void**) &abl->mBuffers[0].mData, &nbytes); 91 - abl->mBuffers[0].mDataByteSize = nbytes;*/ 92 - 93 38 size_t done = 0; 94 39 95 40 while (done < length) 96 41 { 97 - abl->mBuffers[0].mData = This->m_buffer; 42 + // Non-interleaved (planar) audio would have multiple buffers, but PA doesn't even support that AFAIK 43 + abl->mNumberBuffers = 1; 44 + 45 + abl->mBuffers[0].mNumberChannels = 2; 46 + // abl->mBuffers[0].mData = This->m_buffer; 98 47 99 48 // std::cout << "AudioHardwareStreamPAOutput() length req=" << length << ", done=" << done << std::endl; 100 49 size_t rqsize = std::min<UInt32>(This->m_bufferSize, length-done); 50 + pa_stream_begin_write(This->m_stream, (void**) &abl->mBuffers[0].mData, &rqsize); 51 + 101 52 abl->mBuffers[0].mDataByteSize = rqsize; 102 53 103 54 // Call the client for more data ··· 135 86 battr.prebuf = battr.maxlength; 136 87 battr.tlength = uint32_t(-1); 137 88 89 + pa_stream_set_write_callback(m_stream, paStreamWriteCB, this); 90 + 138 91 pa_stream_connect_playback(m_stream, nullptr, &battr, pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING 139 92 |PA_STREAM_ADJUST_LATENCY 140 93 |PA_STREAM_AUTO_TIMING_UPDATE) /* PA_STREAM_START_CORKED */, ··· 143 96 // pa_stream_cork(m_stream, false, [](pa_stream*, int, void*) {}, nullptr); 144 97 } 145 98 146 - void AudioHardwareStreamPAOutput::stop(void(^cbDone)()) 147 - { 148 - // std::cerr << "AudioHardwareStreamPAOutput::stop()\n"; 149 - m_cbDone = Block_copy(cbDone); 150 - 151 - pa_stream_cork(m_stream, true, [](pa_stream*, int, void* self) { 152 - AudioHardwareStreamPAOutput* This = static_cast<AudioHardwareStreamPAOutput*>(self); 153 - 154 - pa_stream_disconnect(This->m_stream); 155 - This->m_cbDone(); 156 - 157 - Block_release(This->m_cbDone); 158 - }, this); 159 - }
+1 -7
src/CoreAudio/CoreAudio/pulse/AudioHardwareStreamPAOutput.h
··· 25 25 { 26 26 public: 27 27 AudioHardwareStreamPAOutput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData); 28 - ~AudioHardwareStreamPAOutput(); 29 - 30 - void stop(void(^cbDone)()) override; 31 28 private: 32 - void start(); 29 + void start() override; 33 30 static void paStreamWriteCB(pa_stream* s, size_t length, void* self); 34 - private: 35 - pa_stream* m_stream; 36 - void(^m_cbDone)(); 37 31 }; 38 32 39 33 #endif /* AUDIOHARDWARESTREAMPA_H */