···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "AudioHardwareImplPAInput.h"
2121+#include "AudioHardwareStreamPAInput.h"
2222+2323+AudioHardwareImplPAInput::AudioHardwareImplPAInput(AudioObjectID myId)
2424+: AudioHardwareImplPA(myId)
2525+{
2626+ m_uid = CFSTR("PulseAudio:Input");
2727+}
2828+2929+OSStatus AudioHardwareImplPAInput::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
3030+ const void* inQualifierData, UInt32* ioDataSize, void* outData)
3131+{
3232+ if (inAddress->mSelector == kAudioDevicePropertyStreamConfiguration)
3333+ {
3434+ size_t size = sizeof(AudioBufferList);
3535+3636+ if (inAddress->mScope == kAudioDevicePropertyScopeOutput)
3737+ size += 1* sizeof(AudioBuffer);
3838+3939+ // Number of returned buffers is the number of channels
4040+ if (AudioBufferList* abl = static_cast<AudioBufferList*>(outData); abl && *ioDataSize >= size)
4141+ {
4242+ if (inAddress->mScope == kAudioDevicePropertyScopeOutput)
4343+ {
4444+ abl->mNumberBuffers = 1;
4545+ abl->mBuffers[0].mNumberChannels = 2;
4646+4747+ // TODO: Is the below stuff ever used? How?
4848+ abl->mBuffers[0].mData = nullptr;
4949+ abl->mBuffers[0].mDataByteSize = 0;
5050+ }
5151+ else
5252+ abl->mNumberBuffers = 0;
5353+ }
5454+5555+ *ioDataSize = size;
5656+ return kAudioHardwareNoError;
5757+ }
5858+5959+ return AudioHardwareImplPA::getPropertyData(inAddress, inQualifierDataSize, inQualifierData, ioDataSize, outData);
6060+}
6161+6262+OSStatus AudioHardwareImplPAInput::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
6363+ const void* inQualifierData, UInt32 inDataSize, const void* inData)
6464+{
6565+ return AudioHardwareImplPA::setPropertyData(inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
6666+}
6767+6868+AudioHardwareStream* AudioHardwareImplPAInput::createStream(AudioDeviceIOProc callback, void* clientData)
6969+{
7070+ return new AudioHardwareStreamPAInput(this, callback, clientData);
7171+}
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef AUDIOHARDWAREIMPLPAINPUT_H
2121+#define AUDIOHARDWAREIMPLPAINPUT_H
2222+#include "AudioHardwareImplPA.h"
2323+2424+class AudioHardwareImplPAInput : public AudioHardwareImplPA
2525+{
2626+public:
2727+ AudioHardwareImplPAInput(AudioObjectID myId);
2828+2929+ OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
3030+ const void* inQualifierData, UInt32* ioDataSize, void* outData) override;
3131+3232+ OSStatus setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
3333+ const void* inQualifierData, UInt32 inDataSize, const void* inData) override;
3434+protected:
3535+ AudioHardwareStream* createStream(AudioDeviceIOProc callback, void* clientData) override;
3636+};
3737+3838+#endif
3939+
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "AudioHardwareStreamPAInput.h"
2121+#include "AudioHardwareImplPA.h"
2222+#include <iostream>
2323+#include <vector>
2424+2525+AudioHardwareStreamPAInput::AudioHardwareStreamPAInput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData)
2626+: AudioHardwareStreamPA(hw, callback, clientData)
2727+{
2828+ // m_dump.open("/tmp/dump.raw", std::ios_base::out | std::ios_base::binary);
2929+}
3030+3131+void AudioHardwareStreamPAInput::paStreamReadCB(pa_stream* s, size_t length, void* self)
3232+{
3333+ AudioHardwareStreamPAInput* This = static_cast<AudioHardwareStreamPAInput*>(self);
3434+3535+ AudioTimeStamp fake = {0};
3636+ AudioBufferList* abl = static_cast<AudioBufferList*>(alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer)));
3737+ std::vector<uint8_t> hole;
3838+3939+ // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB()\n";
4040+4141+ while (true)
4242+ {
4343+ abl->mNumberBuffers = 1;
4444+ abl->mBuffers[0].mNumberChannels = 2;
4545+4646+ size_t nbytes;
4747+4848+ int rv = pa_stream_peek(This->m_stream, (const void**) &abl->mBuffers[0].mData, &nbytes);
4949+5050+ if (rv < 0 || !nbytes)
5151+ {
5252+ // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB(): peek rv=" << rv << ", nbytes=" << nbytes << std::endl;
5353+ break;
5454+ }
5555+5656+ if (nbytes && !abl->mBuffers[0].mData)
5757+ {
5858+ // "If there is a hole, data will be NULL and nbytes will contain the length of the hole."
5959+ hole.resize(nbytes);
6060+ abl->mBuffers[0].mData = hole.data();
6161+ }
6262+ abl->mBuffers[0].mDataByteSize = nbytes;
6363+6464+ // This->m_dump.write((char*) abl->mBuffers[0].mData, nbytes);
6565+ // This->m_dump.flush();
6666+6767+ // std::cout << "AudioHardwareStreamPAInput::paStreamReadCB(): bytes=" << nbytes << std::endl;
6868+ OSStatus status = This->m_callback(This->m_hw->id(), &fake, abl, &fake, nullptr, nullptr, This->m_clientData);
6969+7070+ pa_stream_drop(This->m_stream);
7171+7272+ if (status != noErr)
7373+ {
7474+ pa_stream_cork(This->m_stream, true, [](pa_stream*, int, void*) {}, nullptr);
7575+ break;
7676+ }
7777+ }
7878+}
7979+8080+void AudioHardwareStreamPAInput::start()
8181+{
8282+ struct pa_buffer_attr battr;
8383+8484+ battr.fragsize = uint32_t(-1);
8585+ battr.maxlength = uint32_t(m_bufferSize);
8686+ battr.minreq = uint32_t(-1);
8787+ battr.prebuf = battr.maxlength;
8888+ battr.tlength = uint32_t(-1);
8989+9090+ // std::cout << "AudioHardwareStreamPAInput::start()\n";
9191+9292+ pa_stream_set_read_callback(m_stream, paStreamReadCB, this);
9393+9494+ int rv = pa_stream_connect_record(m_stream, nullptr, &battr,
9595+ pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE)
9696+ );
9797+9898+ // std::cout << "AudioHardwareStreamPAInput::start() rv = " << rv << std::endl;
9999+}
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef AUDIOHARDWARESTREAMPAINPUT_H
2121+#define AUDIOHARDWARESTREAMPAINPUT_H
2222+#include "AudioHardwareStreamPA.h"
2323+#include <fstream>
2424+2525+class AudioHardwareStreamPAInput : public AudioHardwareStreamPA
2626+{
2727+public:
2828+ AudioHardwareStreamPAInput(AudioHardwareImpl* hw, AudioDeviceIOProc callback, void* clientData);
2929+private:
3030+ void start() override;
3131+ static void paStreamReadCB(pa_stream* s, size_t length, void* self);
3232+3333+ // std::ofstream m_dump;
3434+};
3535+3636+#endif /* AUDIOHARDWARESTREAMPA_H */
3737+