diff options
Diffstat (limited to 'src/plugins/coreaudio')
-rw-r--r-- | src/plugins/coreaudio/coreaudio.json | 3 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudio.pro | 39 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiodeviceinfo.h | 82 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiodeviceinfo.mm | 346 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioinput.h | 266 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioinput.mm | 1005 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiooutput.h | 205 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiooutput.mm | 752 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioplugin.h | 66 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioplugin.mm | 82 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiosessionmanager.h | 125 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudiosessionmanager.mm | 472 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioutils.h | 93 | ||||
-rw-r--r-- | src/plugins/coreaudio/coreaudioutils.mm | 198 |
14 files changed, 0 insertions, 3734 deletions
diff --git a/src/plugins/coreaudio/coreaudio.json b/src/plugins/coreaudio/coreaudio.json deleted file mode 100644 index a31d52107..000000000 --- a/src/plugins/coreaudio/coreaudio.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": ["default"] -} diff --git a/src/plugins/coreaudio/coreaudio.pro b/src/plugins/coreaudio/coreaudio.pro deleted file mode 100644 index 50159311a..000000000 --- a/src/plugins/coreaudio/coreaudio.pro +++ /dev/null @@ -1,39 +0,0 @@ -TARGET = qtaudio_coreaudio -QT += multimedia-private - -OTHER_FILES += \ - coreaudio.json - -#DEFINES += QT_DEBUG_COREAUDIO - -HEADERS += \ - coreaudiodeviceinfo.h \ - coreaudioinput.h \ - coreaudiooutput.h \ - coreaudioplugin.h \ - coreaudioutils.h - -OBJECTIVE_SOURCES += \ - coreaudiodeviceinfo.mm \ - coreaudioinput.mm \ - coreaudiooutput.mm \ - coreaudioplugin.mm \ - coreaudioutils.mm - -ios|tvos { - HEADERS += coreaudiosessionmanager.h - OBJECTIVE_SOURCES += coreaudiosessionmanager.mm - LIBS += -framework Foundation -framework AVFoundation -} else { - LIBS += \ - -framework ApplicationServices \ - -framework AudioUnit -} - -LIBS += \ - -framework CoreAudio \ - -framework AudioToolbox - -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = CoreAudioPlugin -load(qt_plugin) diff --git a/src/plugins/coreaudio/coreaudiodeviceinfo.h b/src/plugins/coreaudio/coreaudiodeviceinfo.h deleted file mode 100644 index 08c3961e6..000000000 --- a/src/plugins/coreaudio/coreaudiodeviceinfo.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IOSAUDIODEVICEINFO_H -#define IOSAUDIODEVICEINFO_H - -#include <qaudiosystem.h> - -#if defined(Q_OS_OSX) -# include <CoreAudio/CoreAudio.h> -#endif - -QT_BEGIN_NAMESPACE - -class CoreAudioDeviceInfo : public QAbstractAudioDeviceInfo -{ - Q_OBJECT - -public: - CoreAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode); - ~CoreAudioDeviceInfo() {} - - QAudioFormat preferredFormat() const; - bool isFormatSupported(const QAudioFormat &format) const; - QString deviceName() const; - QStringList supportedCodecs(); - QList<int> supportedSampleRates(); - QList<int> supportedChannelCounts(); - QList<int> supportedSampleSizes(); - QList<QAudioFormat::Endian> supportedByteOrders(); - QList<QAudioFormat::SampleType> supportedSampleTypes(); - - static QByteArray defaultDevice(QAudio::Mode mode); - static QList<QByteArray> availableDevices(QAudio::Mode mode); - -private: -#if defined(Q_OS_OSX) - AudioDeviceID m_deviceId; -#endif - - QString m_device; - QAudio::Mode m_mode; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/coreaudio/coreaudiodeviceinfo.mm b/src/plugins/coreaudio/coreaudiodeviceinfo.mm deleted file mode 100644 index 94ed6dc24..000000000 --- a/src/plugins/coreaudio/coreaudiodeviceinfo.mm +++ /dev/null @@ -1,346 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "coreaudiodeviceinfo.h" -#include "coreaudioutils.h" -#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) -# include "coreaudiosessionmanager.h" -#endif - -#include <QtCore/QDataStream> -#include <QtCore/QDebug> -#include <QtCore/QSet> -#include <QIODevice> - -QT_BEGIN_NAMESPACE - -CoreAudioDeviceInfo::CoreAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode) - : m_mode(mode) -{ -#if defined(Q_OS_OSX) - quint32 deviceID; - - QDataStream dataStream(device); - dataStream >> deviceID >> m_device; - m_deviceId = AudioDeviceID(deviceID); -#else //iOS - m_device = device; -#endif -} - - -QAudioFormat CoreAudioDeviceInfo::preferredFormat() const -{ - QAudioFormat format; - -#if defined(Q_OS_OSX) - UInt32 propSize = 0; - AudioObjectPropertyScope audioDevicePropertyScope = m_mode == QAudio::AudioInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - AudioObjectPropertyAddress audioDevicePropertyStreamsAddress = { kAudioDevicePropertyStreams, - audioDevicePropertyScope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyDataSize(m_deviceId, &audioDevicePropertyStreamsAddress, 0, NULL, &propSize) == noErr) { - - const int sc = propSize / sizeof(AudioStreamID); - - if (sc > 0) { - AudioStreamID* streams = new AudioStreamID[sc]; - - if (AudioObjectGetPropertyData(m_deviceId, &audioDevicePropertyStreamsAddress, 0, NULL, &propSize, streams) == noErr) { - - AudioObjectPropertyAddress audioDevicePhysicalFormatPropertyAddress = { kAudioStreamPropertyPhysicalFormat, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - for (int i = 0; i < sc; ++i) { - if (AudioObjectGetPropertyDataSize(streams[i], &audioDevicePhysicalFormatPropertyAddress, 0, NULL, &propSize) == noErr) { - AudioStreamBasicDescription sf; - - if (AudioObjectGetPropertyData(streams[i], &audioDevicePhysicalFormatPropertyAddress, 0, NULL, &propSize, &sf) == noErr) { - format = CoreAudioUtils::toQAudioFormat(sf); - break; - } else { - qWarning() << "QAudioDeviceInfo: Unable to find perferedFormat for stream"; - } - } else { - qWarning() << "QAudioDeviceInfo: Unable to find size of perferedFormat for stream"; - } - } - } - - delete[] streams; - } - } -#else //iOS - format.setSampleSize(16); - if (m_mode == QAudio::AudioInput) { - format.setChannelCount(1); - format.setSampleRate(8000); - } else { - format.setChannelCount(2); - format.setSampleRate(44100); - } - format.setCodec(QString::fromLatin1("audio/pcm")); - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); -#endif - - return format; -} - - -bool CoreAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const -{ - CoreAudioDeviceInfo *self = const_cast<CoreAudioDeviceInfo*>(this); - - //Sample rates are more of a suggestion with CoreAudio so as long as we get a - //sane value then we can likely use it. - return format.isValid() - && format.codec() == QString::fromLatin1("audio/pcm") - && format.sampleRate() > 0 - && self->supportedChannelCounts().contains(format.channelCount()) - && self->supportedSampleSizes().contains(format.sampleSize()); -} - - -QString CoreAudioDeviceInfo::deviceName() const -{ - return m_device; -} - - -QStringList CoreAudioDeviceInfo::supportedCodecs() -{ - return QStringList() << QString::fromLatin1("audio/pcm"); -} - - -QList<int> CoreAudioDeviceInfo::supportedSampleRates() -{ - QSet<int> sampleRates; - -#if defined(Q_OS_OSX) - UInt32 propSize = 0; - AudioObjectPropertyScope scope = m_mode == QAudio::AudioInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - AudioObjectPropertyAddress availableNominalSampleRatesAddress = { kAudioDevicePropertyAvailableNominalSampleRates, - scope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyDataSize(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize) == noErr) { - const int pc = propSize / sizeof(AudioValueRange); - - if (pc > 0) { - AudioValueRange* vr = new AudioValueRange[pc]; - - if (AudioObjectGetPropertyData(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize, vr) == noErr) { - for (int i = 0; i < pc; ++i) { - sampleRates << vr[i].mMinimum << vr[i].mMaximum; - } - } - - delete[] vr; - } - } -#else //iOS - //iOS doesn't have a way to query available sample rates - //instead we provide reasonable targets - //It may be necessary have CoreAudioSessionManger test combinations - //with available hardware - sampleRates << 8000 << 11025 << 22050 << 44100 << 48000; -#endif - return sampleRates.values(); -} - - -QList<int> CoreAudioDeviceInfo::supportedChannelCounts() -{ - static QList<int> supportedChannels; - - if (supportedChannels.isEmpty()) { - // If the number of channels is not supported by an audio device, Core Audio will - // automatically convert the audio data. - for (int i = 1; i <= 16; ++i) - supportedChannels.append(i); - } - - return supportedChannels; -} - - -QList<int> CoreAudioDeviceInfo::supportedSampleSizes() -{ - return QList<int>() << 8 << 16 << 24 << 32 << 64; -} - - -QList<QAudioFormat::Endian> CoreAudioDeviceInfo::supportedByteOrders() -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian; -} - - -QList<QAudioFormat::SampleType> CoreAudioDeviceInfo::supportedSampleTypes() -{ - return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float; -} - -#if defined(Q_OS_OSX) -// XXX: remove at some future date -static inline QString cfStringToQString(CFStringRef str) -{ - CFIndex length = CFStringGetLength(str); - const UniChar *chars = CFStringGetCharactersPtr(str); - if (chars) - return QString(reinterpret_cast<const QChar *>(chars), length); - - UniChar buffer[length]; - CFStringGetCharacters(str, CFRangeMake(0, length), buffer); - return QString(reinterpret_cast<const QChar *>(buffer), length); -} - -static QByteArray get_device_info(AudioDeviceID audioDevice, QAudio::Mode mode) -{ - UInt32 size; - QByteArray device; - QDataStream ds(&device, QIODevice::WriteOnly); - AudioStreamBasicDescription sf; - CFStringRef name; - Boolean isInput = mode == QAudio::AudioInput; - AudioObjectPropertyScope audioPropertyScope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - - // Id - ds << quint32(audioDevice); - - // Mode //TODO: Why don't we use the Stream Format we ask for? - size = sizeof(AudioStreamBasicDescription); - AudioObjectPropertyAddress audioDeviceStreamFormatPropertyAddress = { kAudioDevicePropertyStreamFormat, - audioPropertyScope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyData(audioDevice, &audioDeviceStreamFormatPropertyAddress, 0, NULL, &size, &sf) != noErr) { - return QByteArray(); - } - - // Name - size = sizeof(CFStringRef); - AudioObjectPropertyAddress audioDeviceNamePropertyAddress = { kAudioObjectPropertyName, - audioPropertyScope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyData(audioDevice, &audioDeviceNamePropertyAddress, 0, NULL, &size, &name) != noErr) { - qWarning() << "QAudioDeviceInfo: Unable to find device name"; - return QByteArray(); - } - ds << cfStringToQString(name); - - CFRelease(name); - - return device; -} -#endif - -QByteArray CoreAudioDeviceInfo::defaultDevice(QAudio::Mode mode) -{ -#if defined(Q_OS_OSX) - AudioDeviceID audioDevice; - UInt32 size = sizeof(audioDevice); - const AudioObjectPropertySelector selector = (mode == QAudio::AudioOutput) ? kAudioHardwarePropertyDefaultOutputDevice - : kAudioHardwarePropertyDefaultInputDevice; - AudioObjectPropertyAddress defaultDevicePropertyAddress = { selector, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyData(kAudioObjectSystemObject, - &defaultDevicePropertyAddress, - 0, NULL, &size, &audioDevice) != noErr) { - qWarning("QAudioDeviceInfo: Unable to find default %s device", (mode == QAudio::AudioOutput) ? "output" : "input"); - return QByteArray(); - } - - return get_device_info(audioDevice, mode); -#else //iOS - const auto &devices = (mode == QAudio::AudioOutput) ? CoreAudioSessionManager::instance().outputDevices() - : CoreAudioSessionManager::instance().inputDevices(); - return !devices.isEmpty() ? devices.first() : QByteArray(); -#endif -} - -QList<QByteArray> CoreAudioDeviceInfo::availableDevices(QAudio::Mode mode) -{ - QList<QByteArray> devices; -#if defined(Q_OS_OSX) - UInt32 propSize = 0; - AudioObjectPropertyAddress audioDevicesPropertyAddress = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, - &audioDevicesPropertyAddress, - 0, NULL, &propSize) == noErr) { - - const int dc = propSize / sizeof(AudioDeviceID); - - if (dc > 0) { - AudioDeviceID* audioDevices = new AudioDeviceID[dc]; - - if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &audioDevicesPropertyAddress, 0, NULL, &propSize, audioDevices) == noErr) { - for (int i = 0; i < dc; ++i) { - const QByteArray &info = get_device_info(audioDevices[i], mode); - if (!info.isNull()) - devices << info; - } - } - - delete[] audioDevices; - } - } -#else //iOS - if (mode == QAudio::AudioOutput) - return CoreAudioSessionManager::instance().outputDevices(); - if (mode == QAudio::AudioInput) - return CoreAudioSessionManager::instance().inputDevices(); -#endif - - return devices; -} - -QT_END_NAMESPACE - -#include "moc_coreaudiodeviceinfo.cpp" diff --git a/src/plugins/coreaudio/coreaudioinput.h b/src/plugins/coreaudio/coreaudioinput.h deleted file mode 100644 index 40455b3db..000000000 --- a/src/plugins/coreaudio/coreaudioinput.h +++ /dev/null @@ -1,266 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IOSAUDIOINPUT_H -#define IOSAUDIOINPUT_H - -#include <qaudiosystem.h> -#include <AudioUnit/AudioUnit.h> -#include <CoreAudio/CoreAudioTypes.h> -#include <AudioToolbox/AudioToolbox.h> - -#include <QtCore/QIODevice> -#include <QtCore/QWaitCondition> -#include <QtCore/QMutex> -#include <QtCore/QTimer> - -QT_BEGIN_NAMESPACE - -class CoreAudioRingBuffer; -class CoreAudioPacketFeeder; -class CoreAudioInputBuffer; -class CoreAudioInputDevice; - -class CoreAudioBufferList -{ -public: - CoreAudioBufferList(AudioStreamBasicDescription const& streamFormat); - CoreAudioBufferList(AudioStreamBasicDescription const& streamFormat, char *buffer, int bufferSize); - CoreAudioBufferList(AudioStreamBasicDescription const& streamFormat, int framesToBuffer); - - ~CoreAudioBufferList(); - - AudioBufferList* audioBufferList() const { return m_bufferList; } - char *data(int buffer = 0) const; - qint64 bufferSize(int buffer = 0) const; - int frameCount(int buffer = 0) const; - int packetCount(int buffer = 0) const; - int packetSize() const; - void reset(); - -private: - bool m_owner; - int m_dataSize; - AudioStreamBasicDescription m_streamDescription; - AudioBufferList *m_bufferList; -}; - -class CoreAudioPacketFeeder -{ -public: - CoreAudioPacketFeeder(CoreAudioBufferList *abl); - - bool feed(AudioBufferList& dst, UInt32& packetCount); - bool empty() const; - -private: - UInt32 m_totalPackets; - UInt32 m_position; - CoreAudioBufferList *m_audioBufferList; -}; - -class CoreAudioInputBuffer : public QObject -{ - Q_OBJECT - -public: - CoreAudioInputBuffer(int bufferSize, - int maxPeriodSize, - AudioStreamBasicDescription const& inputFormat, - AudioStreamBasicDescription const& outputFormat, - QObject *parent); - - ~CoreAudioInputBuffer(); - - qreal volume() const; - void setVolume(qreal v); - - qint64 renderFromDevice(AudioUnit audioUnit, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames); - - qint64 readBytes(char *data, qint64 len); - - void setFlushDevice(QIODevice *device); - - void startFlushTimer(); - void stopFlushTimer(); - - void flush(bool all = false); - void reset(); - int available() const; - int used() const; - -signals: - void readyRead(); - -private slots: - void flushBuffer(); - -private: - bool m_deviceError; - int m_maxPeriodSize; - int m_periodTime; - QIODevice *m_device; - QTimer *m_flushTimer; - CoreAudioRingBuffer *m_buffer; - CoreAudioBufferList *m_inputBufferList; - AudioConverterRef m_audioConverter; - AudioStreamBasicDescription m_inputFormat; - AudioStreamBasicDescription m_outputFormat; - QAudioFormat m_qFormat; - qreal m_volume; - - const static OSStatus as_empty = 'qtem'; - - // Converter callback - static OSStatus converterCallback(AudioConverterRef inAudioConverter, - UInt32 *ioNumberDataPackets, - AudioBufferList *ioData, - AudioStreamPacketDescription **outDataPacketDescription, - void *inUserData); -}; - -class CoreAudioInputDevice : public QIODevice -{ - Q_OBJECT - -public: - CoreAudioInputDevice(CoreAudioInputBuffer *audioBuffer, QObject *parent); - - qint64 readData(char *data, qint64 len); - qint64 writeData(const char *data, qint64 len); - - bool isSequential() const { return true; } - -private: - CoreAudioInputBuffer *m_audioBuffer; -}; - -class CoreAudioInput : public QAbstractAudioInput -{ - Q_OBJECT - -public: - CoreAudioInput(const QByteArray &device); - ~CoreAudioInput(); - - void start(QIODevice *device); - QIODevice *start(); - void stop(); - void reset(); - void suspend(); - void resume(); - int bytesReady() const; - int periodSize() const; - void setBufferSize(int value); - int bufferSize() const; - void setNotifyInterval(int milliSeconds); - int notifyInterval() const; - qint64 processedUSecs() const; - qint64 elapsedUSecs() const; - QAudio::Error error() const; - QAudio::State state() const; - void setFormat(const QAudioFormat &format); - QAudioFormat format() const; - - void setVolume(qreal volume); - qreal volume() const; - -private slots: - void deviceStoppped(); - -private: - enum { - Running, - Stopped - }; - - bool open(); - void close(); - - void audioThreadStart(); - void audioThreadStop(); - - void audioDeviceStop(); - void audioDeviceActive(); - void audioDeviceFull(); - void audioDeviceError(); - - void startTimers(); - void stopTimers(); - - // Input callback - static OSStatus inputCallback(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); - - QByteArray m_device; - bool m_isOpen; - int m_periodSizeBytes; - int m_internalBufferSize; - qint64 m_totalFrames; - QAudioFormat m_audioFormat; - QIODevice *m_audioIO; - AudioUnit m_audioUnit; -#if defined(Q_OS_OSX) - AudioDeviceID m_audioDeviceId; -#endif - Float64 m_clockFrequency; - UInt64 m_startTime; - QAudio::Error m_errorCode; - QAudio::State m_stateCode; - CoreAudioInputBuffer *m_audioBuffer; - QMutex m_mutex; - QWaitCondition m_threadFinished; - QAtomicInt m_audioThreadState; - QTimer *m_intervalTimer; - AudioStreamBasicDescription m_streamFormat; - AudioStreamBasicDescription m_deviceFormat; - QAbstractAudioDeviceInfo *m_audioDeviceInfo; - qreal m_volume; -}; - -QT_END_NAMESPACE - -#endif // IOSAUDIOINPUT_H diff --git a/src/plugins/coreaudio/coreaudioinput.mm b/src/plugins/coreaudio/coreaudioinput.mm deleted file mode 100644 index 9f6a1f7bc..000000000 --- a/src/plugins/coreaudio/coreaudioinput.mm +++ /dev/null @@ -1,1005 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "coreaudioinput.h" -#include "coreaudiosessionmanager.h" -#include "coreaudiodeviceinfo.h" -#include "coreaudioutils.h" - -#if defined(Q_OS_OSX) -# include <AudioUnit/AudioComponent.h> -#endif - -#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) -# include "coreaudiosessionmanager.h" -#endif - -#include <QtMultimedia/private/qaudiohelpers_p.h> -#include <QtCore/QDataStream> -#include <QtCore/QDebug> - -QT_BEGIN_NAMESPACE - -static const int DEFAULT_BUFFER_SIZE = 4 * 1024; - -CoreAudioBufferList::CoreAudioBufferList(const AudioStreamBasicDescription &streamFormat) - : m_owner(false) - , m_streamDescription(streamFormat) -{ - const bool isInterleaved = (m_streamDescription.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0; - const int numberOfBuffers = isInterleaved ? 1 : m_streamDescription.mChannelsPerFrame; - - m_dataSize = 0; - - m_bufferList = reinterpret_cast<AudioBufferList*>(malloc(sizeof(AudioBufferList) + - (sizeof(AudioBuffer) * numberOfBuffers))); - - m_bufferList->mNumberBuffers = numberOfBuffers; - for (int i = 0; i < numberOfBuffers; ++i) { - m_bufferList->mBuffers[i].mNumberChannels = isInterleaved ? numberOfBuffers : 1; - m_bufferList->mBuffers[i].mDataByteSize = 0; - m_bufferList->mBuffers[i].mData = 0; - } -} - -CoreAudioBufferList::CoreAudioBufferList(const AudioStreamBasicDescription &streamFormat, char *buffer, int bufferSize) - : m_owner(false) - , m_streamDescription(streamFormat) - , m_bufferList(0) -{ - m_dataSize = bufferSize; - - m_bufferList = reinterpret_cast<AudioBufferList*>(malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer))); - - m_bufferList->mNumberBuffers = 1; - m_bufferList->mBuffers[0].mNumberChannels = 1; - m_bufferList->mBuffers[0].mDataByteSize = m_dataSize; - m_bufferList->mBuffers[0].mData = buffer; -} - -CoreAudioBufferList::CoreAudioBufferList(const AudioStreamBasicDescription &streamFormat, int framesToBuffer) - : m_owner(true) - , m_streamDescription(streamFormat) - , m_bufferList(0) -{ - const bool isInterleaved = (m_streamDescription.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0; - const int numberOfBuffers = isInterleaved ? 1 : m_streamDescription.mChannelsPerFrame; - - m_dataSize = framesToBuffer * m_streamDescription.mBytesPerFrame; - - m_bufferList = reinterpret_cast<AudioBufferList*>(malloc(sizeof(AudioBufferList) + - (sizeof(AudioBuffer) * numberOfBuffers))); - m_bufferList->mNumberBuffers = numberOfBuffers; - for (int i = 0; i < numberOfBuffers; ++i) { - m_bufferList->mBuffers[i].mNumberChannels = isInterleaved ? numberOfBuffers : 1; - m_bufferList->mBuffers[i].mDataByteSize = m_dataSize; - m_bufferList->mBuffers[i].mData = malloc(m_dataSize); - } -} - -CoreAudioBufferList::~CoreAudioBufferList() -{ - if (m_owner) { - for (UInt32 i = 0; i < m_bufferList->mNumberBuffers; ++i) - free(m_bufferList->mBuffers[i].mData); - } - - free(m_bufferList); -} - -char *CoreAudioBufferList::data(int buffer) const -{ - return static_cast<char*>(m_bufferList->mBuffers[buffer].mData); -} - -qint64 CoreAudioBufferList::bufferSize(int buffer) const -{ - return m_bufferList->mBuffers[buffer].mDataByteSize; -} - -int CoreAudioBufferList::frameCount(int buffer) const -{ - return m_bufferList->mBuffers[buffer].mDataByteSize / m_streamDescription.mBytesPerFrame; -} - -int CoreAudioBufferList::packetCount(int buffer) const -{ - return m_bufferList->mBuffers[buffer].mDataByteSize / m_streamDescription.mBytesPerPacket; -} - -int CoreAudioBufferList::packetSize() const -{ - return m_streamDescription.mBytesPerPacket; -} - -void CoreAudioBufferList::reset() -{ - for (UInt32 i = 0; i < m_bufferList->mNumberBuffers; ++i) { - m_bufferList->mBuffers[i].mDataByteSize = m_dataSize; - m_bufferList->mBuffers[i].mData = 0; - } -} - -CoreAudioPacketFeeder::CoreAudioPacketFeeder(CoreAudioBufferList *abl) - : m_audioBufferList(abl) -{ - m_totalPackets = m_audioBufferList->packetCount(); - m_position = 0; -} - -bool CoreAudioPacketFeeder::feed(AudioBufferList &dst, UInt32 &packetCount) -{ - if (m_position == m_totalPackets) { - dst.mBuffers[0].mDataByteSize = 0; - packetCount = 0; - return false; - } - - if (m_totalPackets - m_position < packetCount) - packetCount = m_totalPackets - m_position; - - dst.mBuffers[0].mDataByteSize = packetCount * m_audioBufferList->packetSize(); - dst.mBuffers[0].mData = m_audioBufferList->data() + (m_position * m_audioBufferList->packetSize()); - - m_position += packetCount; - - return true; -} - -bool CoreAudioPacketFeeder::empty() const -{ - return m_position == m_totalPackets; -} - -CoreAudioInputBuffer::CoreAudioInputBuffer(int bufferSize, int maxPeriodSize, const AudioStreamBasicDescription &inputFormat, const AudioStreamBasicDescription &outputFormat, QObject *parent) - : QObject(parent) - , m_deviceError(false) - , m_device(0) - , m_audioConverter(0) - , m_inputFormat(inputFormat) - , m_outputFormat(outputFormat) - , m_volume(qreal(1.0f)) -{ - m_maxPeriodSize = maxPeriodSize; - m_periodTime = m_maxPeriodSize / m_outputFormat.mBytesPerFrame * 1000 / m_outputFormat.mSampleRate; - - m_buffer = new CoreAudioRingBuffer(bufferSize); - - m_inputBufferList = new CoreAudioBufferList(m_inputFormat); - - m_flushTimer = new QTimer(this); - connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer())); - - if (CoreAudioUtils::toQAudioFormat(inputFormat) != CoreAudioUtils::toQAudioFormat(outputFormat)) { - if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) { - qWarning() << "QAudioInput: Unable to create an Audio Converter"; - m_audioConverter = 0; - } - } - - m_qFormat = CoreAudioUtils::toQAudioFormat(inputFormat); // we adjust volume before conversion -} - -CoreAudioInputBuffer::~CoreAudioInputBuffer() -{ - delete m_buffer; -} - -qreal CoreAudioInputBuffer::volume() const -{ - return m_volume; -} - -void CoreAudioInputBuffer::setVolume(qreal v) -{ - m_volume = v; -} - -qint64 CoreAudioInputBuffer::renderFromDevice(AudioUnit audioUnit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames) -{ - const bool pullMode = m_device == 0; - - OSStatus err; - qint64 framesRendered = 0; - - m_inputBufferList->reset(); - err = AudioUnitRender(audioUnit, - ioActionFlags, - inTimeStamp, - inBusNumber, - inNumberFrames, - m_inputBufferList->audioBufferList()); - - // adjust volume, if necessary - if (!qFuzzyCompare(m_volume, qreal(1.0f))) { - QAudioHelperInternal::qMultiplySamples(m_volume, - m_qFormat, - m_inputBufferList->data(), /* input */ - m_inputBufferList->data(), /* output */ - m_inputBufferList->bufferSize()); - } - - if (m_audioConverter != 0) { - CoreAudioPacketFeeder feeder(m_inputBufferList); - - int copied = 0; - const int available = m_buffer->free(); - - while (err == noErr && !feeder.empty()) { - CoreAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(available - copied); - - if (region.second == 0) - break; - - AudioBufferList output; - output.mNumberBuffers = 1; - output.mBuffers[0].mNumberChannels = 1; - output.mBuffers[0].mDataByteSize = region.second; - output.mBuffers[0].mData = region.first; - - UInt32 packetSize = region.second / m_outputFormat.mBytesPerPacket; - err = AudioConverterFillComplexBuffer(m_audioConverter, - converterCallback, - &feeder, - &packetSize, - &output, - 0); - region.second = output.mBuffers[0].mDataByteSize; - copied += region.second; - - m_buffer->releaseWriteRegion(region); - } - - framesRendered += copied / m_outputFormat.mBytesPerFrame; - } - else { - const int available = m_inputBufferList->bufferSize(); - bool wecan = true; - int copied = 0; - - while (wecan && copied < available) { - CoreAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(available - copied); - - if (region.second > 0) { - memcpy(region.first, m_inputBufferList->data() + copied, region.second); - copied += region.second; - } - else - wecan = false; - - m_buffer->releaseWriteRegion(region); - } - - framesRendered = copied / m_outputFormat.mBytesPerFrame; - } - - if (pullMode && framesRendered > 0) - emit readyRead(); - - return framesRendered; -} - -qint64 CoreAudioInputBuffer::readBytes(char *data, qint64 len) -{ - bool wecan = true; - qint64 bytesCopied = 0; - - len -= len % m_maxPeriodSize; - while (wecan && bytesCopied < len) { - CoreAudioRingBuffer::Region region = m_buffer->acquireReadRegion(len - bytesCopied); - - if (region.second > 0) { - memcpy(data + bytesCopied, region.first, region.second); - bytesCopied += region.second; - } - else - wecan = false; - - m_buffer->releaseReadRegion(region); - } - - return bytesCopied; -} - -void CoreAudioInputBuffer::setFlushDevice(QIODevice *device) -{ - if (m_device != device) - m_device = device; -} - -void CoreAudioInputBuffer::startFlushTimer() -{ - if (m_device != 0) { - // We use the period time for the timer, since that's - // around the buffer size (pre conversion >.>) - m_flushTimer->start(qMax(1, m_periodTime)); - } -} - -void CoreAudioInputBuffer::stopFlushTimer() -{ - m_flushTimer->stop(); -} - -void CoreAudioInputBuffer::flush(bool all) -{ - if (m_device == 0) - return; - - const int used = m_buffer->used(); - const int readSize = all ? used : used - (used % m_maxPeriodSize); - - if (readSize > 0) { - bool wecan = true; - int flushed = 0; - - while (!m_deviceError && wecan && flushed < readSize) { - CoreAudioRingBuffer::Region region = m_buffer->acquireReadRegion(readSize - flushed); - - if (region.second > 0) { - int bytesWritten = m_device->write(region.first, region.second); - if (bytesWritten < 0) { - stopFlushTimer(); - m_deviceError = true; - } - else { - region.second = bytesWritten; - flushed += bytesWritten; - wecan = bytesWritten != 0; - } - } - else - wecan = false; - - m_buffer->releaseReadRegion(region); - } - } -} - -void CoreAudioInputBuffer::reset() -{ - m_buffer->reset(); - m_deviceError = false; -} - -int CoreAudioInputBuffer::available() const -{ - return m_buffer->free(); -} - -int CoreAudioInputBuffer::used() const -{ - return m_buffer->used(); -} - -void CoreAudioInputBuffer::flushBuffer() -{ - flush(); -} - -OSStatus CoreAudioInputBuffer::converterCallback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) -{ - Q_UNUSED(inAudioConverter); - Q_UNUSED(outDataPacketDescription); - - CoreAudioPacketFeeder* feeder = static_cast<CoreAudioPacketFeeder*>(inUserData); - - if (!feeder->feed(*ioData, *ioNumberDataPackets)) - return as_empty; - - return noErr; -} - -CoreAudioInputDevice::CoreAudioInputDevice(CoreAudioInputBuffer *audioBuffer, QObject *parent) - : QIODevice(parent) - , m_audioBuffer(audioBuffer) -{ - open(QIODevice::ReadOnly | QIODevice::Unbuffered); - connect(m_audioBuffer, SIGNAL(readyRead()), SIGNAL(readyRead())); -} - -qint64 CoreAudioInputDevice::readData(char *data, qint64 len) -{ - return m_audioBuffer->readBytes(data, len); -} - -qint64 CoreAudioInputDevice::writeData(const char *data, qint64 len) -{ - Q_UNUSED(data); - Q_UNUSED(len); - - return 0; -} - -CoreAudioInput::CoreAudioInput(const QByteArray &device) - : m_isOpen(false) - , m_internalBufferSize(DEFAULT_BUFFER_SIZE) - , m_totalFrames(0) - , m_audioUnit(0) - , m_clockFrequency(CoreAudioUtils::frequency() / 1000) - , m_startTime(0) - , m_errorCode(QAudio::NoError) - , m_stateCode(QAudio::StoppedState) - , m_audioBuffer(0) - , m_volume(1.0) -{ -#if defined(Q_OS_OSX) - quint32 deviceId; - QDataStream dataStream(device); - dataStream >> deviceId >> m_device; - m_audioDeviceId = AudioDeviceID(deviceId); -#else //iOS - m_device = device; -#endif - - m_audioDeviceInfo = new CoreAudioDeviceInfo(device, QAudio::AudioInput); - - m_intervalTimer = new QTimer(this); - m_intervalTimer->setInterval(1000); - connect(m_intervalTimer, SIGNAL(timeout()), this, SIGNAL(notify())); -} - - -CoreAudioInput::~CoreAudioInput() -{ - close(); - delete m_audioDeviceInfo; -} - -bool CoreAudioInput::open() -{ -#if defined(Q_OS_IOS) - CoreAudioSessionManager::instance().setCategory(CoreAudioSessionManager::PlayAndRecord, CoreAudioSessionManager::MixWithOthers); - CoreAudioSessionManager::instance().setActive(true); -#endif - - if (m_isOpen) - return true; - - UInt32 size = 0; - - AudioComponentDescription componentDescription; - componentDescription.componentType = kAudioUnitType_Output; -#if defined(Q_OS_OSX) - componentDescription.componentSubType = kAudioUnitSubType_HALOutput; -#else - componentDescription.componentSubType = kAudioUnitSubType_RemoteIO; -#endif - componentDescription.componentManufacturer = kAudioUnitManufacturer_Apple; - componentDescription.componentFlags = 0; - componentDescription.componentFlagsMask = 0; - - AudioComponent component = AudioComponentFindNext(0, &componentDescription); - if (component == 0) { - qWarning() << "QAudioInput: Failed to find Output component"; - return false; - } - - if (AudioComponentInstanceNew(component, &m_audioUnit) != noErr) { - qWarning() << "QAudioInput: Unable to Open Output Component"; - return false; - } - - // Set mode - // switch to input mode - UInt32 enable = 1; - if (AudioUnitSetProperty(m_audioUnit, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Input, - 1, - &enable, - sizeof(enable)) != noErr) { - qWarning() << "QAudioInput: Unable to switch to input mode (Enable Input)"; - return false; - } - - enable = 0; - if (AudioUnitSetProperty(m_audioUnit, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Output, - 0, - &enable, - sizeof(enable)) != noErr) { - qWarning() << "QAudioInput: Unable to switch to input mode (Disable output)"; - return false; - } - - // register callback - AURenderCallbackStruct callback; - callback.inputProc = inputCallback; - callback.inputProcRefCon = this; - - if (AudioUnitSetProperty(m_audioUnit, - kAudioOutputUnitProperty_SetInputCallback, - kAudioUnitScope_Global, - 0, - &callback, - sizeof(callback)) != noErr) { - qWarning() << "QAudioInput: Failed to set AudioUnit callback"; - return false; - } - -#if defined(Q_OS_OSX) - //Set Audio Device - if (AudioUnitSetProperty(m_audioUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &m_audioDeviceId, - sizeof(m_audioDeviceId)) != noErr) { - qWarning() << "QAudioInput: Unable to use configured device"; - return false; - } -#endif - - //set format - m_streamFormat = CoreAudioUtils::toAudioStreamBasicDescription(m_audioFormat); - -#if defined(Q_OS_OSX) - if (m_audioFormat == m_audioDeviceInfo->preferredFormat()) { -#endif - - m_deviceFormat = m_streamFormat; - AudioUnitSetProperty(m_audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 1, - &m_deviceFormat, - sizeof(m_deviceFormat)); -#if defined(Q_OS_OSX) - } else { - size = sizeof(m_deviceFormat); - if (AudioUnitGetProperty(m_audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 1, - &m_deviceFormat, - &size) != noErr) { - qWarning() << "QAudioInput: Unable to retrieve device format"; - return false; - } - - if (AudioUnitSetProperty(m_audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 1, - &m_deviceFormat, - sizeof(m_deviceFormat)) != noErr) { - qWarning() << "QAudioInput: Unable to set device format"; - return false; - } - } -#endif - - //setup buffers - UInt32 numberOfFrames; -#if defined(Q_OS_OSX) - size = sizeof(UInt32); - if (AudioUnitGetProperty(m_audioUnit, - kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, - 0, - &numberOfFrames, - &size) != noErr) { - qWarning() << "QAudioInput: Failed to get audio period size"; - return false; - } - //BUG: numberOfFrames gets ignored after this point - - AudioValueRange bufferRange; - size = sizeof(AudioValueRange); - - if (AudioUnitGetProperty(m_audioUnit, - kAudioDevicePropertyBufferFrameSizeRange, - kAudioUnitScope_Global, - 0, - &bufferRange, - &size) != noErr) { - qWarning() << "QAudioInput: Failed to get audio period size range"; - return false; - } - - // See if the requested buffer size is permissible - numberOfFrames = qBound((UInt32)bufferRange.mMinimum, m_internalBufferSize / m_streamFormat.mBytesPerFrame, (UInt32)bufferRange.mMaximum); - - // Set it back - if (AudioUnitSetProperty(m_audioUnit, - kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, - 0, - &numberOfFrames, - sizeof(UInt32)) != noErr) { - qWarning() << "QAudioInput: Failed to set audio buffer size"; - return false; - } -#else //iOS - Float32 bufferSize = CoreAudioSessionManager::instance().currentIOBufferDuration(); - bufferSize *= m_streamFormat.mSampleRate; - numberOfFrames = bufferSize; -#endif - - // Now allocate a few buffers to be safe. - m_periodSizeBytes = m_internalBufferSize = numberOfFrames * m_streamFormat.mBytesPerFrame; - - m_audioBuffer = new CoreAudioInputBuffer(m_internalBufferSize * 4, - m_periodSizeBytes, - m_deviceFormat, - m_streamFormat, - this); - - m_audioBuffer->setVolume(m_volume); - m_audioIO = new CoreAudioInputDevice(m_audioBuffer, this); - - // Init - if (AudioUnitInitialize(m_audioUnit) != noErr) { - qWarning() << "QAudioInput: Failed to initialize AudioUnit"; - return false; - } - - m_isOpen = true; - - return m_isOpen; - -} - -void CoreAudioInput::close() -{ - if (m_audioUnit != 0) { - AudioOutputUnitStop(m_audioUnit); - AudioUnitUninitialize(m_audioUnit); - AudioComponentInstanceDispose(m_audioUnit); - } - - delete m_audioBuffer; -} - -void CoreAudioInput::start(QIODevice *device) -{ - QIODevice* op = device; - - if (!m_audioDeviceInfo->isFormatSupported(m_audioFormat) || !open()) { - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::OpenError; - return; - } - - reset(); - m_audioBuffer->reset(); - m_audioBuffer->setFlushDevice(op); - - if (op == 0) - op = m_audioIO; - - // Start - m_startTime = CoreAudioUtils::currentTime(); - m_totalFrames = 0; - - m_stateCode = QAudio::IdleState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - - audioThreadStart(); -} - - -QIODevice *CoreAudioInput::start() -{ - QIODevice* op = 0; - - if (!m_audioDeviceInfo->isFormatSupported(m_audioFormat) || !open()) { - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::OpenError; - return m_audioIO; - } - - reset(); - m_audioBuffer->reset(); - m_audioBuffer->setFlushDevice(op); - - if (op == 0) - op = m_audioIO; - - // Start - m_startTime = CoreAudioUtils::currentTime(); - m_totalFrames = 0; - - m_stateCode = QAudio::IdleState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - - audioThreadStart(); - - return op; -} - - -void CoreAudioInput::stop() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode != QAudio::StoppedState) { - audioThreadStop(); - m_audioBuffer->flush(true); - - m_errorCode = QAudio::NoError; - m_stateCode = QAudio::StoppedState; - QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, m_stateCode)); - } -} - - -void CoreAudioInput::reset() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode != QAudio::StoppedState) { - audioThreadStop(); - - m_errorCode = QAudio::NoError; - m_stateCode = QAudio::StoppedState; - m_audioBuffer->reset(); - QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, m_stateCode)); - } -} - - -void CoreAudioInput::suspend() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode == QAudio::ActiveState || m_stateCode == QAudio::IdleState) { - audioThreadStop(); - - m_errorCode = QAudio::NoError; - m_stateCode = QAudio::SuspendedState; - QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, m_stateCode)); - } -} - - -void CoreAudioInput::resume() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode == QAudio::SuspendedState) { - audioThreadStart(); - - m_errorCode = QAudio::NoError; - m_stateCode = QAudio::ActiveState; - QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, m_stateCode)); - } -} - - -int CoreAudioInput::bytesReady() const -{ - if (!m_audioBuffer) - return 0; - return m_audioBuffer->used(); -} - - -int CoreAudioInput::periodSize() const -{ - return m_periodSizeBytes; -} - - -void CoreAudioInput::setBufferSize(int value) -{ - m_internalBufferSize = value; -} - - -int CoreAudioInput::bufferSize() const -{ - return m_internalBufferSize; -} - - -void CoreAudioInput::setNotifyInterval(int milliSeconds) -{ - if (m_intervalTimer->interval() == milliSeconds) - return; - - if (milliSeconds <= 0) - milliSeconds = 0; - - m_intervalTimer->setInterval(milliSeconds); -} - - -int CoreAudioInput::notifyInterval() const -{ - return m_intervalTimer->interval(); -} - - -qint64 CoreAudioInput::processedUSecs() const -{ - return m_totalFrames * 1000000 / m_audioFormat.sampleRate(); -} - - -qint64 CoreAudioInput::elapsedUSecs() const -{ - if (m_stateCode == QAudio::StoppedState) - return 0; - - return (CoreAudioUtils::currentTime() - m_startTime) / (m_clockFrequency / 1000); -} - - -QAudio::Error CoreAudioInput::error() const -{ - return m_errorCode; -} - - -QAudio::State CoreAudioInput::state() const -{ - return m_stateCode; -} - - -void CoreAudioInput::setFormat(const QAudioFormat &format) -{ - if (m_stateCode == QAudio::StoppedState) - m_audioFormat = format; -} - - -QAudioFormat CoreAudioInput::format() const -{ - return m_audioFormat; -} - - -void CoreAudioInput::setVolume(qreal volume) -{ - m_volume = volume; - if (m_audioBuffer) - m_audioBuffer->setVolume(m_volume); -} - - -qreal CoreAudioInput::volume() const -{ - return m_volume; -} - -void CoreAudioInput::deviceStoppped() -{ - stopTimers(); - emit stateChanged(m_stateCode); -} - -void CoreAudioInput::audioThreadStart() -{ - startTimers(); - m_audioThreadState.storeRelaxed(Running); - AudioOutputUnitStart(m_audioUnit); -} - -void CoreAudioInput::audioThreadStop() -{ - stopTimers(); - if (m_audioThreadState.testAndSetAcquire(Running, Stopped)) - m_threadFinished.wait(&m_mutex); -} - -void CoreAudioInput::audioDeviceStop() -{ - AudioOutputUnitStop(m_audioUnit); - m_audioThreadState.storeRelaxed(Stopped); - m_threadFinished.wakeOne(); -} - -void CoreAudioInput::audioDeviceActive() -{ - if (m_stateCode == QAudio::IdleState) { - QMutexLocker lock(&m_mutex); - m_stateCode = QAudio::ActiveState; - emit stateChanged(m_stateCode); - } -} - -void CoreAudioInput::audioDeviceFull() -{ - if (m_stateCode == QAudio::ActiveState) { - QMutexLocker lock(&m_mutex); - m_errorCode = QAudio::UnderrunError; - m_stateCode = QAudio::IdleState; - emit stateChanged(m_stateCode); - } -} - -void CoreAudioInput::audioDeviceError() -{ - if (m_stateCode == QAudio::ActiveState) { - QMutexLocker lock(&m_mutex); - audioDeviceStop(); - - m_errorCode = QAudio::IOError; - m_stateCode = QAudio::StoppedState; - QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection); - } -} - -void CoreAudioInput::startTimers() -{ - m_audioBuffer->startFlushTimer(); - if (m_intervalTimer->interval() > 0) - m_intervalTimer->start(); -} - -void CoreAudioInput::stopTimers() -{ - m_audioBuffer->stopFlushTimer(); - m_intervalTimer->stop(); -} - -OSStatus CoreAudioInput::inputCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) -{ - Q_UNUSED(ioData); - - CoreAudioInput* d = static_cast<CoreAudioInput*>(inRefCon); - - const int threadState = d->m_audioThreadState.loadAcquire(); - if (threadState == Stopped) - d->audioDeviceStop(); - else { - qint64 framesWritten; - - framesWritten = d->m_audioBuffer->renderFromDevice(d->m_audioUnit, - ioActionFlags, - inTimeStamp, - inBusNumber, - inNumberFrames); - - if (framesWritten > 0) { - d->m_totalFrames += framesWritten; - d->audioDeviceActive(); - } else if (framesWritten == 0) - d->audioDeviceFull(); - else if (framesWritten < 0) - d->audioDeviceError(); - } - - return noErr; -} - -QT_END_NAMESPACE - -#include "moc_coreaudioinput.cpp" diff --git a/src/plugins/coreaudio/coreaudiooutput.h b/src/plugins/coreaudio/coreaudiooutput.h deleted file mode 100644 index 97b1e0438..000000000 --- a/src/plugins/coreaudio/coreaudiooutput.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IOSAUDIOOUTPUT_H -#define IOSAUDIOOUTPUT_H - -#include <qaudiosystem.h> - -#if defined(Q_OS_OSX) -# include <CoreAudio/CoreAudio.h> -#endif -#include <AudioUnit/AudioUnit.h> -#include <CoreAudio/CoreAudioTypes.h> - -#include <QtCore/QIODevice> -#include <QtCore/QWaitCondition> -#include <QtCore/QMutex> - -QT_BEGIN_NAMESPACE - -class CoreAudioOutputBuffer; -class QTimer; -class CoreAudioDeviceInfo; -class CoreAudioRingBuffer; - -class CoreAudioOutputBuffer : public QObject -{ - Q_OBJECT - -public: - CoreAudioOutputBuffer(int bufferSize, int maxPeriodSize, QAudioFormat const& audioFormat); - ~CoreAudioOutputBuffer(); - - qint64 readFrames(char *data, qint64 maxFrames); - qint64 writeBytes(const char *data, qint64 maxSize); - - int available() const; - void reset(); - - void setPrefetchDevice(QIODevice *device); - - void startFillTimer(); - void stopFillTimer(); - -signals: - void readyRead(); - -private slots: - void fillBuffer(); - -private: - bool m_deviceError; - int m_maxPeriodSize; - int m_bytesPerFrame; - int m_periodTime; - QIODevice *m_device; - QTimer *m_fillTimer; - CoreAudioRingBuffer *m_buffer; -}; - -class CoreAudioOutputDevice : public QIODevice -{ -public: - CoreAudioOutputDevice(CoreAudioOutputBuffer *audioBuffer, QObject *parent); - - qint64 readData(char *data, qint64 len); - qint64 writeData(const char *data, qint64 len); - - bool isSequential() const { return true; } - -private: - CoreAudioOutputBuffer *m_audioBuffer; -}; - - -class CoreAudioOutput : public QAbstractAudioOutput -{ - Q_OBJECT - -public: - CoreAudioOutput(const QByteArray &device); - ~CoreAudioOutput(); - - void start(QIODevice *device); - QIODevice *start(); - void stop(); - void reset(); - void suspend(); - void resume(); - int bytesFree() const; - int periodSize() const; - void setBufferSize(int value); - int bufferSize() const; - void setNotifyInterval(int milliSeconds); - int notifyInterval() const; - qint64 processedUSecs() const; - qint64 elapsedUSecs() const; - QAudio::Error error() const; - QAudio::State state() const; - void setFormat(const QAudioFormat &format); - QAudioFormat format() const; - - void setVolume(qreal volume); - qreal volume() const; - - void setCategory(const QString &category); - QString category() const; - -private slots: - void deviceStopped(); - void inputReady(); - -private: - enum { - Running, - Draining, - Stopped - }; - - static OSStatus renderCallback(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); - - bool open(); - void close(); - void audioThreadStart(); - void audioThreadStop(); - void audioThreadDrain(); - void audioDeviceStop(); - void audioDeviceIdle(); - void audioDeviceError(); - - void startTimers(); - void stopTimers(); - - QByteArray m_device; - - bool m_isOpen; - int m_internalBufferSize; - int m_periodSizeBytes; - qint64 m_totalFrames; - QAudioFormat m_audioFormat; - QIODevice *m_audioIO; -#if defined(Q_OS_OSX) - AudioDeviceID m_audioDeviceId; -#endif - AudioUnit m_audioUnit; - Float64 m_clockFrequency; - UInt64 m_startTime; - AudioStreamBasicDescription m_streamFormat; - CoreAudioOutputBuffer *m_audioBuffer; - QAtomicInt m_audioThreadState; - QWaitCondition m_threadFinished; - QMutex m_mutex; - QTimer *m_intervalTimer; - CoreAudioDeviceInfo *m_audioDeviceInfo; - qreal m_cachedVolume; - qreal m_volume; - bool m_pullMode; - - QAudio::Error m_errorCode; - QAudio::State m_stateCode; -}; - -QT_END_NAMESPACE - -#endif // IOSAUDIOOUTPUT_H diff --git a/src/plugins/coreaudio/coreaudiooutput.mm b/src/plugins/coreaudio/coreaudiooutput.mm deleted file mode 100644 index 1138de3e2..000000000 --- a/src/plugins/coreaudio/coreaudiooutput.mm +++ /dev/null @@ -1,752 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "coreaudiooutput.h" -#include "coreaudiosessionmanager.h" -#include "coreaudiodeviceinfo.h" -#include "coreaudioutils.h" - -#include <QtCore/QDataStream> -#include <QtCore/QTimer> -#include <QtCore/QDebug> - -#include <AudioUnit/AudioUnit.h> -#include <AudioToolbox/AudioToolbox.h> -#if defined(Q_OS_OSX) -# include <AudioUnit/AudioComponent.h> -#endif - -#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) -# include <QtMultimedia/private/qaudiohelpers_p.h> -#endif - -QT_BEGIN_NAMESPACE - -static const int DEFAULT_BUFFER_SIZE = 8 * 1024; - -CoreAudioOutputBuffer::CoreAudioOutputBuffer(int bufferSize, int maxPeriodSize, const QAudioFormat &audioFormat) - : m_deviceError(false) - , m_maxPeriodSize(maxPeriodSize) - , m_device(0) -{ - m_buffer = new CoreAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize))); - m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channelCount(); - m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.sampleRate(); - - m_fillTimer = new QTimer(this); - connect(m_fillTimer, SIGNAL(timeout()), SLOT(fillBuffer())); -} - -CoreAudioOutputBuffer::~CoreAudioOutputBuffer() -{ - delete m_buffer; -} - -qint64 CoreAudioOutputBuffer::readFrames(char *data, qint64 maxFrames) -{ - bool wecan = true; - qint64 framesRead = 0; - - while (wecan && framesRead < maxFrames) { - CoreAudioRingBuffer::Region region = m_buffer->acquireReadRegion((maxFrames - framesRead) * m_bytesPerFrame); - - if (region.second > 0) { - // Ensure that we only read whole frames. - region.second -= region.second % m_bytesPerFrame; - - if (region.second > 0) { - memcpy(data + (framesRead * m_bytesPerFrame), region.first, region.second); - framesRead += region.second / m_bytesPerFrame; - } else - wecan = false; // If there is only a partial frame left we should exit. - } - else - wecan = false; - - m_buffer->releaseReadRegion(region); - } - - if (framesRead == 0 && m_deviceError) - framesRead = -1; - - return framesRead; -} - -qint64 CoreAudioOutputBuffer::writeBytes(const char *data, qint64 maxSize) -{ - bool wecan = true; - qint64 bytesWritten = 0; - - maxSize -= maxSize % m_bytesPerFrame; - while (wecan && bytesWritten < maxSize) { - CoreAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(maxSize - bytesWritten); - - if (region.second > 0) { - memcpy(region.first, data + bytesWritten, region.second); - bytesWritten += region.second; - } - else - wecan = false; - - m_buffer->releaseWriteRegion(region); - } - - if (bytesWritten > 0) - emit readyRead(); - - return bytesWritten; -} - -int CoreAudioOutputBuffer::available() const -{ - return m_buffer->free(); -} - -void CoreAudioOutputBuffer::reset() -{ - m_buffer->reset(); - m_device = 0; - m_deviceError = false; -} - -void CoreAudioOutputBuffer::setPrefetchDevice(QIODevice *device) -{ - if (m_device != device) { - m_device = device; - if (m_device != 0) - fillBuffer(); - } -} - -void CoreAudioOutputBuffer::startFillTimer() -{ - if (m_device != 0) - m_fillTimer->start(m_buffer->size() / 2 / m_maxPeriodSize * m_periodTime); -} - -void CoreAudioOutputBuffer::stopFillTimer() -{ - m_fillTimer->stop(); -} - -void CoreAudioOutputBuffer::fillBuffer() -{ - const int free = m_buffer->free(); - const int writeSize = free - (free % m_maxPeriodSize); - - if (writeSize > 0) { - bool wecan = true; - int filled = 0; - - while (!m_deviceError && wecan && filled < writeSize) { - CoreAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(writeSize - filled); - - if (region.second > 0) { - region.second = m_device->read(region.first, region.second); - if (region.second > 0) - filled += region.second; - else if (region.second == 0) - wecan = false; - else if (region.second < 0) { - m_fillTimer->stop(); - region.second = 0; - m_deviceError = true; - } - } - else - wecan = false; - - m_buffer->releaseWriteRegion(region); - } - - if (filled > 0) - emit readyRead(); - } -} - -CoreAudioOutputDevice::CoreAudioOutputDevice(CoreAudioOutputBuffer *audioBuffer, QObject *parent) - : QIODevice(parent) - , m_audioBuffer(audioBuffer) -{ - open(QIODevice::WriteOnly | QIODevice::Unbuffered); -} - -qint64 CoreAudioOutputDevice::readData(char *data, qint64 len) -{ - Q_UNUSED(data); - Q_UNUSED(len); - - return 0; -} - -qint64 CoreAudioOutputDevice::writeData(const char *data, qint64 len) -{ - return m_audioBuffer->writeBytes(data, len); -} - -CoreAudioOutput::CoreAudioOutput(const QByteArray &device) - : m_isOpen(false) - , m_internalBufferSize(DEFAULT_BUFFER_SIZE) - , m_totalFrames(0) - , m_audioIO(0) - , m_audioUnit(0) - , m_startTime(0) - , m_audioBuffer(0) - , m_cachedVolume(1.0) - , m_volume(1.0) - , m_pullMode(false) - , m_errorCode(QAudio::NoError) - , m_stateCode(QAudio::StoppedState) -{ -#if defined(Q_OS_OSX) - quint32 deviceID; - QDataStream dataStream(device); - dataStream >> deviceID >> m_device; - m_audioDeviceId = AudioDeviceID(deviceID); -#else //iOS - m_device = device; -#endif - - m_clockFrequency = CoreAudioUtils::frequency() / 1000; - m_audioDeviceInfo = new CoreAudioDeviceInfo(device, QAudio::AudioOutput); - m_audioThreadState.storeRelaxed(Stopped); - - m_intervalTimer = new QTimer(this); - m_intervalTimer->setInterval(1000); - connect(m_intervalTimer, SIGNAL(timeout()), this, SIGNAL(notify())); -} - -CoreAudioOutput::~CoreAudioOutput() -{ - close(); - delete m_audioDeviceInfo; -} - -void CoreAudioOutput::start(QIODevice *device) -{ - QIODevice* op = device; - - if (!m_audioDeviceInfo->isFormatSupported(m_audioFormat) || !open()) { - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::OpenError; - return; - } - - reset(); - m_audioBuffer->reset(); - m_audioBuffer->setPrefetchDevice(op); - - if (op == 0) { - op = m_audioIO; - m_stateCode = QAudio::IdleState; - } - else - m_stateCode = QAudio::ActiveState; - - // Start - m_pullMode = true; - m_errorCode = QAudio::NoError; - m_totalFrames = 0; - m_startTime = CoreAudioUtils::currentTime(); - - if (m_stateCode == QAudio::ActiveState) - audioThreadStart(); - - emit stateChanged(m_stateCode); -} - -QIODevice *CoreAudioOutput::start() -{ - if (!m_audioDeviceInfo->isFormatSupported(m_audioFormat) || !open()) { - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::OpenError; - return m_audioIO; - } - - reset(); - m_audioBuffer->reset(); - m_audioBuffer->setPrefetchDevice(0); - - m_stateCode = QAudio::IdleState; - - // Start - m_pullMode = false; - m_errorCode = QAudio::NoError; - m_totalFrames = 0; - m_startTime = CoreAudioUtils::currentTime(); - - emit stateChanged(m_stateCode); - - return m_audioIO; -} - -void CoreAudioOutput::stop() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode != QAudio::StoppedState) { - audioThreadDrain(); - - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - } -} - -void CoreAudioOutput::reset() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode != QAudio::StoppedState) { - audioThreadStop(); - - m_stateCode = QAudio::StoppedState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - } -} - -void CoreAudioOutput::suspend() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode == QAudio::ActiveState || m_stateCode == QAudio::IdleState) { - audioThreadStop(); - - m_stateCode = QAudio::SuspendedState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - } -} - -void CoreAudioOutput::resume() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode == QAudio::SuspendedState) { - audioThreadStart(); - - m_stateCode = m_pullMode ? QAudio::ActiveState : QAudio::IdleState; - m_errorCode = QAudio::NoError; - emit stateChanged(m_stateCode); - } -} - -int CoreAudioOutput::bytesFree() const -{ - return m_audioBuffer->available(); -} - -int CoreAudioOutput::periodSize() const -{ - return m_periodSizeBytes; -} - -void CoreAudioOutput::setBufferSize(int value) -{ - if (m_stateCode == QAudio::StoppedState) - m_internalBufferSize = value; -} - -int CoreAudioOutput::bufferSize() const -{ - return m_internalBufferSize; -} - -void CoreAudioOutput::setNotifyInterval(int milliSeconds) -{ - if (m_intervalTimer->interval() == milliSeconds) - return; - - if (milliSeconds <= 0) - milliSeconds = 0; - - m_intervalTimer->setInterval(milliSeconds); -} - -int CoreAudioOutput::notifyInterval() const -{ - return m_intervalTimer->interval(); -} - -qint64 CoreAudioOutput::processedUSecs() const -{ - return m_totalFrames * 1000000 / m_audioFormat.sampleRate(); -} - -qint64 CoreAudioOutput::elapsedUSecs() const -{ - if (m_stateCode == QAudio::StoppedState) - return 0; - - return (CoreAudioUtils::currentTime() - m_startTime) / (m_clockFrequency / 1000); -} - -QAudio::Error CoreAudioOutput::error() const -{ - return m_errorCode; -} - -QAudio::State CoreAudioOutput::state() const -{ - return m_stateCode; -} - -void CoreAudioOutput::setFormat(const QAudioFormat &format) -{ - if (m_stateCode == QAudio::StoppedState) - m_audioFormat = format; -} - -QAudioFormat CoreAudioOutput::format() const -{ - return m_audioFormat; -} - -void CoreAudioOutput::setVolume(qreal volume) -{ - m_cachedVolume = qBound(qreal(0.0), volume, qreal(1.0)); - if (!m_isOpen) - return; - -#if defined(Q_OS_OSX) - //on OS X the volume can be set directly on the AudioUnit - if (AudioUnitSetParameter(m_audioUnit, - kHALOutputParam_Volume, - kAudioUnitScope_Global, - 0 /* bus */, - m_cachedVolume, - 0) == noErr) - m_volume = m_cachedVolume; -#endif -} - -qreal CoreAudioOutput::volume() const -{ - return m_cachedVolume; -} - -void CoreAudioOutput::setCategory(const QString &category) -{ - Q_UNUSED(category); -} - -QString CoreAudioOutput::category() const -{ - return QString(); -} - -void CoreAudioOutput::deviceStopped() -{ - m_intervalTimer->stop(); - emit stateChanged(m_stateCode); -} - -void CoreAudioOutput::inputReady() -{ - QMutexLocker lock(&m_mutex); - if (m_stateCode == QAudio::IdleState) { - audioThreadStart(); - - m_stateCode = QAudio::ActiveState; - m_errorCode = QAudio::NoError; - - emit stateChanged(m_stateCode); - } -} - -OSStatus CoreAudioOutput::renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) -{ - Q_UNUSED(ioActionFlags); - Q_UNUSED(inTimeStamp); - Q_UNUSED(inBusNumber); - Q_UNUSED(inNumberFrames); - - CoreAudioOutput* d = static_cast<CoreAudioOutput*>(inRefCon); - - const int threadState = d->m_audioThreadState.fetchAndAddAcquire(0); - if (threadState == Stopped) { - ioData->mBuffers[0].mDataByteSize = 0; - d->audioDeviceStop(); - } - else { - const UInt32 bytesPerFrame = d->m_streamFormat.mBytesPerFrame; - qint64 framesRead; - - framesRead = d->m_audioBuffer->readFrames((char*)ioData->mBuffers[0].mData, - ioData->mBuffers[0].mDataByteSize / bytesPerFrame); - - if (framesRead > 0) { - ioData->mBuffers[0].mDataByteSize = framesRead * bytesPerFrame; - d->m_totalFrames += framesRead; - -#if defined(Q_OS_MACOS) - // If playback is already stopped. - if (threadState != Running) { - qreal oldVolume = d->m_cachedVolume; - // Decrease volume smoothly. - d->setVolume(d->m_volume / 2); - d->m_cachedVolume = oldVolume; - } -#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) - // on iOS we have to adjust the sound volume ourselves - if (!qFuzzyCompare(d->m_cachedVolume, qreal(1.0f))) { - QAudioHelperInternal::qMultiplySamples(d->m_cachedVolume, - d->m_audioFormat, - ioData->mBuffers[0].mData, /* input */ - ioData->mBuffers[0].mData, /* output */ - ioData->mBuffers[0].mDataByteSize); - } -#endif - - } - else { - ioData->mBuffers[0].mDataByteSize = 0; - if (framesRead == 0) { - if (threadState == Draining) - d->audioDeviceStop(); - else - d->audioDeviceIdle(); - } - else - d->audioDeviceError(); - } - } - - return noErr; -} - -bool CoreAudioOutput::open() -{ -#if defined(Q_OS_IOS) - // Set default category to Ambient (implies MixWithOthers). This makes sure audio stops playing - // if the screen is locked or if the Silent switch is toggled. - CoreAudioSessionManager::instance().setCategory(CoreAudioSessionManager::Ambient, CoreAudioSessionManager::None); - CoreAudioSessionManager::instance().setActive(true); -#endif - - if (m_errorCode != QAudio::NoError) - return false; - - if (m_isOpen) { - setVolume(m_cachedVolume); - return true; - } - - AudioComponentDescription componentDescription; - componentDescription.componentType = kAudioUnitType_Output; -#if defined(Q_OS_OSX) - componentDescription.componentSubType = kAudioUnitSubType_HALOutput; -#else - componentDescription.componentSubType = kAudioUnitSubType_RemoteIO; -#endif - componentDescription.componentManufacturer = kAudioUnitManufacturer_Apple; - componentDescription.componentFlags = 0; - componentDescription.componentFlagsMask = 0; - - AudioComponent component = AudioComponentFindNext(0, &componentDescription); - if (component == 0) { - qWarning() << "QAudioOutput: Failed to find Output component"; - return false; - } - - if (AudioComponentInstanceNew(component, &m_audioUnit) != noErr) { - qWarning() << "QAudioOutput: Unable to Open Output Component"; - return false; - } - - // register callback - AURenderCallbackStruct callback; - callback.inputProc = renderCallback; - callback.inputProcRefCon = this; - - if (AudioUnitSetProperty(m_audioUnit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Global, - 0, - &callback, - sizeof(callback)) != noErr) { - qWarning() << "QAudioOutput: Failed to set AudioUnit callback"; - return false; - } - -#if defined(Q_OS_OSX) - //Set Audio Device - if (AudioUnitSetProperty(m_audioUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &m_audioDeviceId, - sizeof(m_audioDeviceId)) != noErr) { - qWarning() << "QAudioOutput: Unable to use configured device"; - return false; - } -#endif - - // Set stream format - m_streamFormat = CoreAudioUtils::toAudioStreamBasicDescription(m_audioFormat); - - UInt32 size = sizeof(m_streamFormat); - if (AudioUnitSetProperty(m_audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &m_streamFormat, - size) != noErr) { - qWarning() << "QAudioOutput: Unable to Set Stream information"; - return false; - } - - // Allocate buffer - UInt32 numberOfFrames = 0; -#if defined(Q_OS_OSX) - size = sizeof(UInt32); - if (AudioUnitGetProperty(m_audioUnit, - kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, - 0, - &numberOfFrames, - &size) != noErr) { - qWarning() << "QAudioInput: Failed to get audio period size"; - return false; - } -#else //iOS - Float32 bufferSize = CoreAudioSessionManager::instance().currentIOBufferDuration(); - bufferSize *= m_streamFormat.mSampleRate; - numberOfFrames = bufferSize; -#endif - - m_periodSizeBytes = numberOfFrames * m_streamFormat.mBytesPerFrame; - if (m_internalBufferSize < m_periodSizeBytes * 2) - m_internalBufferSize = m_periodSizeBytes * 2; - else - m_internalBufferSize -= m_internalBufferSize % m_streamFormat.mBytesPerFrame; - - m_audioBuffer = new CoreAudioOutputBuffer(m_internalBufferSize, m_periodSizeBytes, m_audioFormat); - connect(m_audioBuffer, SIGNAL(readyRead()), SLOT(inputReady())); //Pull - - m_audioIO = new CoreAudioOutputDevice(m_audioBuffer, this); - - //Init - if (AudioUnitInitialize(m_audioUnit)) { - qWarning() << "QAudioOutput: Failed to initialize AudioUnit"; - return false; - } - - m_isOpen = true; - - setVolume(m_cachedVolume); - - return true; -} - -void CoreAudioOutput::close() -{ - if (m_audioUnit != 0) { - AudioOutputUnitStop(m_audioUnit); - AudioUnitUninitialize(m_audioUnit); - AudioComponentInstanceDispose(m_audioUnit); - } - - delete m_audioBuffer; -} - -void CoreAudioOutput::audioThreadStart() -{ - startTimers(); - m_audioThreadState.storeRelaxed(Running); - AudioOutputUnitStart(m_audioUnit); -} - -void CoreAudioOutput::audioThreadStop() -{ - stopTimers(); - if (m_audioThreadState.testAndSetAcquire(Running, Stopped)) - m_threadFinished.wait(&m_mutex, 500); -} - -void CoreAudioOutput::audioThreadDrain() -{ - stopTimers(); - if (m_audioThreadState.testAndSetAcquire(Running, Draining)) - m_threadFinished.wait(&m_mutex, 500); -} - -void CoreAudioOutput::audioDeviceStop() -{ - AudioOutputUnitStop(m_audioUnit); - m_audioThreadState.storeRelaxed(Stopped); - m_threadFinished.wakeOne(); -} - -void CoreAudioOutput::audioDeviceIdle() -{ - if (m_stateCode == QAudio::ActiveState) { - QMutexLocker lock(&m_mutex); - audioDeviceStop(); - - m_errorCode = QAudio::UnderrunError; - m_stateCode = QAudio::IdleState; - QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection); - } -} - -void CoreAudioOutput::audioDeviceError() -{ - if (m_stateCode == QAudio::ActiveState) { - QMutexLocker lock(&m_mutex); - audioDeviceStop(); - - m_errorCode = QAudio::IOError; - m_stateCode = QAudio::StoppedState; - QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection); - } -} - -void CoreAudioOutput::startTimers() -{ - m_audioBuffer->startFillTimer(); - if (m_intervalTimer->interval() > 0) - m_intervalTimer->start(); -} - -void CoreAudioOutput::stopTimers() -{ - m_audioBuffer->stopFillTimer(); - m_intervalTimer->stop(); -} - -QT_END_NAMESPACE - -#include "moc_coreaudiooutput.cpp" diff --git a/src/plugins/coreaudio/coreaudioplugin.h b/src/plugins/coreaudio/coreaudioplugin.h deleted file mode 100644 index 5407bdeb9..000000000 --- a/src/plugins/coreaudio/coreaudioplugin.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IOSAUDIOPLUGIN_H -#define IOSAUDIOPLUGIN_H - -#include <QtMultimedia/qaudiosystemplugin.h> -#include <QtMultimedia/private/qaudiosystempluginext_p.h> - -QT_BEGIN_NAMESPACE - -class CoreAudioPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "coreaudio.json") - Q_INTERFACES(QAudioSystemPluginExtension) - -public: - explicit CoreAudioPlugin(QObject *parent = 0); - ~CoreAudioPlugin() {} - - QByteArray defaultDevice(QAudio::Mode mode) const override; - QList<QByteArray> availableDevices(QAudio::Mode mode) const override; - QAbstractAudioInput *createInput(const QByteArray &device) override; - QAbstractAudioOutput *createOutput(const QByteArray &device) override; - QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode) override; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/coreaudio/coreaudioplugin.mm b/src/plugins/coreaudio/coreaudioplugin.mm deleted file mode 100644 index ac51b9cd0..000000000 --- a/src/plugins/coreaudio/coreaudioplugin.mm +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "coreaudioplugin.h" - -#include "coreaudiodeviceinfo.h" -#include "coreaudioinput.h" -#include "coreaudiooutput.h" - -QT_BEGIN_NAMESPACE - -CoreAudioPlugin::CoreAudioPlugin(QObject *parent) - : QAudioSystemPlugin(parent) -{ -} - -QByteArray CoreAudioPlugin::defaultDevice(QAudio::Mode mode) const -{ - return CoreAudioDeviceInfo::defaultDevice(mode); -} - -QList<QByteArray> CoreAudioPlugin::availableDevices(QAudio::Mode mode) const -{ - return CoreAudioDeviceInfo::availableDevices(mode); -} - - -QAbstractAudioInput *CoreAudioPlugin::createInput(const QByteArray &device) -{ - return new CoreAudioInput(device); -} - - -QAbstractAudioOutput *CoreAudioPlugin::createOutput(const QByteArray &device) -{ - return new CoreAudioOutput(device); -} - - -QAbstractAudioDeviceInfo *CoreAudioPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode) -{ - return new CoreAudioDeviceInfo(device, mode); -} - -QT_END_NAMESPACE - -#include "moc_coreaudioplugin.cpp" diff --git a/src/plugins/coreaudio/coreaudiosessionmanager.h b/src/plugins/coreaudio/coreaudiosessionmanager.h deleted file mode 100644 index 73ef9f303..000000000 --- a/src/plugins/coreaudio/coreaudiosessionmanager.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef IOSAUDIOSESSIONMANAGER_H -#define IOSAUDIOSESSIONMANAGER_H - -#include <QObject> -#ifdef QT_DEBUG_COREAUDIO -# include <QtCore/QDebug> -#endif - -@class CoreAudioSessionObserver; - -QT_BEGIN_NAMESPACE - -class CoreAudioSessionManager : public QObject -{ - Q_OBJECT -public: - enum AudioSessionCategorys { - Ambient, - SoloAmbient, - Playback, - Record, - PlayAndRecord, - AudioProcessing, - MultiRoute - }; - enum AudioSessionCategoryOptions { - None = 0, - MixWithOthers = 1, - DuckOthers = 2, - AllowBluetooth = 4, - DefaultToSpeaker = 8 - }; - enum AudioSessionModes { - Default, - VoiceChat, - GameChat, - VideoRecording, - Measurement, - MoviePlayback - }; - - static CoreAudioSessionManager& instance(); - - bool setActive(bool active); - bool setCategory(AudioSessionCategorys category, AudioSessionCategoryOptions options = None); - bool setMode(AudioSessionModes mode); - - AudioSessionCategorys category(); - AudioSessionModes mode(); - - QList<QByteArray> inputDevices(); - QList<QByteArray> outputDevices(); - - float currentIOBufferDuration(); - float preferredSampleRate(); - -signals: - void activeChanged(); - void categoryChanged(); - void modeChanged(); - void routeChanged(); - void inputDevicesAvailableChanged(); - void outputDevicesAvailableChanged(); - -private: - CoreAudioSessionManager(); - ~CoreAudioSessionManager(); - CoreAudioSessionManager(CoreAudioSessionManager const ©); - CoreAudioSessionManager& operator =(CoreAudioSessionManager const ©); - - CoreAudioSessionObserver *m_sessionObserver; -}; - -#ifdef QT_DEBUG_COREAUDIO -QDebug operator <<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategorys category); -QDebug operator <<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategoryOptions option); -QDebug operator <<(QDebug dbg, CoreAudioSessionManager::AudioSessionModes mode); -#endif - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(CoreAudioSessionManager::AudioSessionCategorys) -Q_DECLARE_METATYPE(CoreAudioSessionManager::AudioSessionCategoryOptions) -Q_DECLARE_METATYPE(CoreAudioSessionManager::AudioSessionModes) - -#endif // IOSAUDIOSESSIONMANAGER_H diff --git a/src/plugins/coreaudio/coreaudiosessionmanager.mm b/src/plugins/coreaudio/coreaudiosessionmanager.mm deleted file mode 100644 index 372c49491..000000000 --- a/src/plugins/coreaudio/coreaudiosessionmanager.mm +++ /dev/null @@ -1,472 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "coreaudiosessionmanager.h" -#import <AVFoundation/AVAudioSession.h> -#import <Foundation/Foundation.h> - -QT_BEGIN_NAMESPACE - -@interface CoreAudioSessionObserver : NSObject -{ - CoreAudioSessionManager *m_sessionManager; - AVAudioSession *m_audioSession; -} - -@property (readonly, getter=sessionManager) CoreAudioSessionManager *m_sessionManager; -@property (readonly, getter=audioSession) AVAudioSession *m_audioSession; - --(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager; - --(BOOL)activateAudio; --(BOOL)deactivateAudio; - -//Notification handlers --(void)audioSessionInterruption:(NSNotification *)notification; --(void)audioSessionRouteChange:(NSNotification *)notification; --(void)audioSessionMediaServicesWereReset:(NSNotification *)notification; - -@end //interface CoreAudioSessionObserver - -@implementation CoreAudioSessionObserver - -@synthesize m_sessionManager, m_audioSession; - --(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager -{ - if (!(self = [super init])) - return nil; - - self->m_sessionManager = sessionManager; - self->m_audioSession = [AVAudioSession sharedInstance]; - - //Set up observers - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionInterruption:) - name:AVAudioSessionInterruptionNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionMediaServicesWereReset:) - name:AVAudioSessionMediaServicesWereResetNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionRouteChange:) - name:AVAudioSessionRouteChangeNotification - object:self->m_audioSession]; - - return self; -} - --(void)dealloc -{ -#ifdef QT_DEBUG_COREAUDIO - qDebug() << Q_FUNC_INFO; -#endif - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionInterruptionNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionMediaServicesWereResetNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionRouteChangeNotification - object:self->m_audioSession]; - - [super dealloc]; -} - --(BOOL)activateAudio -{ - NSError *error = nil; - BOOL success = [self->m_audioSession setActive:YES error:&error]; - if (![self->m_audioSession setActive:YES error:&error]) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audio session activation failed: %s", [[error localizedDescription] UTF8String]); - } else { - qDebug("audio session activated"); -#endif - } - - return success; -} - --(BOOL)deactivateAudio -{ - NSError *error = nil; - BOOL success = [m_audioSession setActive:NO error:&error]; -#ifdef QT_DEBUG_COREAUDIO - if (!success) { - qDebug("%s", [[error localizedDescription] UTF8String]); - } -#endif - return success; -} - --(void)audioSessionInterruption:(NSNotification *)notification -{ - NSNumber *type = [[notification userInfo] valueForKey:AVAudioSessionInterruptionTypeKey]; - if ([type intValue] == AVAudioSessionInterruptionTypeBegan) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession Interuption begain"); -#endif - } else if ([type intValue] == AVAudioSessionInterruptionTypeEnded) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession Interuption ended"); -#endif - NSNumber *option = [[notification userInfo] valueForKey:AVAudioSessionInterruptionOptionKey]; - if ([option intValue] == AVAudioSessionInterruptionOptionShouldResume) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession is active and immediately ready to be used."); -#endif - } else { - [self activateAudio]; - } - } -} - --(void)audioSessionMediaServicesWereReset:(NSNotification *)notification -{ - Q_UNUSED(notification); -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession Media Services were reset"); -#endif - //Reactivate audio when this occurs - [self activateAudio]; -} - --(void)audioSessionRouteChange:(NSNotification *)notification -{ - NSNumber *reason = [[notification userInfo] valueForKey:AVAudioSessionRouteChangeReasonKey]; - NSUInteger reasonEnum = [reason intValue]; - - if (reasonEnum == AVAudioSessionRouteChangeReasonUnknown) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: unknown"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonNewDeviceAvailable) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: new device available"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: old device unavailable"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonCategoryChange) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: category changed"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonOverride) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: override"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonWakeFromSleep) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: woken from sleep"); -#endif - } else if (reasonEnum == AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory) { -#ifdef QT_DEBUG_COREAUDIO - qDebug("audioSession route changed. reason: no suitable route for category"); -#endif - } - -} - -@end //implementation CoreAudioSessionObserver - -CoreAudioSessionManager::CoreAudioSessionManager() : - QObject(0) -{ - m_sessionObserver = [[CoreAudioSessionObserver alloc] initWithAudioSessionManager:this]; -} - -CoreAudioSessionManager::~CoreAudioSessionManager() -{ -#ifdef QT_DEBUG_COREAUDIO - qDebug() << Q_FUNC_INFO; -#endif - [m_sessionObserver release]; -} - - -CoreAudioSessionManager &CoreAudioSessionManager::instance() -{ - static CoreAudioSessionManager instance; - return instance; -} - -bool CoreAudioSessionManager::setActive(bool active) -{ - if (active) { - return [m_sessionObserver activateAudio]; - } else { - return [m_sessionObserver deactivateAudio]; - } -} - -bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionCategorys category, CoreAudioSessionManager::AudioSessionCategoryOptions options) -{ - NSString *targetCategory = nil; - - switch (category) { - case CoreAudioSessionManager::Ambient: - targetCategory = AVAudioSessionCategoryAmbient; - break; - case CoreAudioSessionManager::SoloAmbient: - targetCategory = AVAudioSessionCategorySoloAmbient; - break; - case CoreAudioSessionManager::Playback: - targetCategory = AVAudioSessionCategoryPlayback; - break; - case CoreAudioSessionManager::Record: - targetCategory = AVAudioSessionCategoryRecord; - break; - case CoreAudioSessionManager::PlayAndRecord: - targetCategory = AVAudioSessionCategoryPlayAndRecord; - break; - case CoreAudioSessionManager::AudioProcessing: -#ifndef Q_OS_TVOS - targetCategory = AVAudioSessionCategoryAudioProcessing; -#endif - break; - case CoreAudioSessionManager::MultiRoute: - targetCategory = AVAudioSessionCategoryMultiRoute; - break; - } - - if (targetCategory == nil) - return false; - - return [[m_sessionObserver audioSession] setCategory:targetCategory - withOptions:(AVAudioSessionCategoryOptions)options - error:nil]; -} - -bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes mode) -{ - NSString *targetMode = nil; - switch (mode) { - case CoreAudioSessionManager::Default: - targetMode = AVAudioSessionModeDefault; - break; - case CoreAudioSessionManager::VoiceChat: - targetMode = AVAudioSessionModeVoiceChat; - break; - case CoreAudioSessionManager::GameChat: - targetMode = AVAudioSessionModeGameChat; - break; - case CoreAudioSessionManager::VideoRecording: - targetMode = AVAudioSessionModeVideoRecording; - break; - case CoreAudioSessionManager::Measurement: - targetMode = AVAudioSessionModeMeasurement; - break; - case CoreAudioSessionManager::MoviePlayback: - targetMode = AVAudioSessionModeMoviePlayback; - break; - } - - if (targetMode == nil) - return false; - - return [[m_sessionObserver audioSession] setMode:targetMode error:nil]; - -} - -CoreAudioSessionManager::AudioSessionCategorys CoreAudioSessionManager::category() -{ - NSString *category = [[m_sessionObserver audioSession] category]; - AudioSessionCategorys localCategory = Ambient; - - if (category == AVAudioSessionCategoryAmbient) { - localCategory = Ambient; - } else if (category == AVAudioSessionCategorySoloAmbient) { - localCategory = SoloAmbient; - } else if (category == AVAudioSessionCategoryPlayback) { - localCategory = Playback; - } else if (category == AVAudioSessionCategoryRecord) { - localCategory = Record; - } else if (category == AVAudioSessionCategoryPlayAndRecord) { - localCategory = PlayAndRecord; -#ifndef Q_OS_TVOS - } else if (category == AVAudioSessionCategoryAudioProcessing) { - localCategory = AudioProcessing; -#endif - } else if (category == AVAudioSessionCategoryMultiRoute) { - localCategory = MultiRoute; - } - - return localCategory; -} - -CoreAudioSessionManager::AudioSessionModes CoreAudioSessionManager::mode() -{ - NSString *mode = [[m_sessionObserver audioSession] mode]; - AudioSessionModes localMode = Default; - - if (mode == AVAudioSessionModeDefault) { - localMode = Default; - } else if (mode == AVAudioSessionModeVoiceChat) { - localMode = VoiceChat; - } else if (mode == AVAudioSessionModeGameChat) { - localMode = GameChat; - } else if (mode == AVAudioSessionModeVideoRecording) { - localMode = VideoRecording; - } else if (mode == AVAudioSessionModeMeasurement) { - localMode = Measurement; - } else if (mode == AVAudioSessionModeMoviePlayback) { - localMode = MoviePlayback; - } - - return localMode; -} - -QList<QByteArray> CoreAudioSessionManager::inputDevices() -{ - //TODO: Add support for USB input devices - //Right now the default behavior on iOS is to have only one input route - //at a time. - QList<QByteArray> inputDevices; - inputDevices << "default"; - return inputDevices; -} - -QList<QByteArray> CoreAudioSessionManager::outputDevices() -{ - //TODO: Add support for USB output devices - //Right now the default behavior on iOS is to have only one output route - //at a time. - QList<QByteArray> outputDevices; - outputDevices << "default"; - return outputDevices; -} - -float CoreAudioSessionManager::currentIOBufferDuration() -{ - return [[m_sessionObserver audioSession] IOBufferDuration]; -} - -float CoreAudioSessionManager::preferredSampleRate() -{ - return [[m_sessionObserver audioSession] preferredSampleRate]; -} - -#ifdef QT_DEBUG_COREAUDIO -QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategorys category) -{ - QDebug output = dbg.nospace(); - switch (category) { - case CoreAudioSessionManager::Ambient: - output << "AudioSessionCategoryAmbient"; - break; - case CoreAudioSessionManager::SoloAmbient: - output << "AudioSessionCategorySoloAmbient"; - break; - case CoreAudioSessionManager::Playback: - output << "AudioSessionCategoryPlayback"; - break; - case CoreAudioSessionManager::Record: - output << "AudioSessionCategoryRecord"; - break; - case CoreAudioSessionManager::PlayAndRecord: - output << "AudioSessionCategoryPlayAndRecord"; - break; - case CoreAudioSessionManager::AudioProcessing: - output << "AudioSessionCategoryAudioProcessing"; - break; - case CoreAudioSessionManager::MultiRoute: - output << "AudioSessionCategoryMultiRoute"; - break; - } - return output; -} - -QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategoryOptions option) -{ - QDebug output = dbg.nospace(); - switch (option) { - case CoreAudioSessionManager::None: - output << "AudioSessionCategoryOptionNone"; - break; - case CoreAudioSessionManager::MixWithOthers: - output << "AudioSessionCategoryOptionMixWithOthers"; - break; - case CoreAudioSessionManager::DuckOthers: - output << "AudioSessionCategoryOptionDuckOthers"; - break; - case CoreAudioSessionManager::AllowBluetooth: - output << "AudioSessionCategoryOptionAllowBluetooth"; - break; - case CoreAudioSessionManager::DefaultToSpeaker: - output << "AudioSessionCategoryOptionDefaultToSpeaker"; - break; - } - return output; -} - -QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionModes mode) -{ - QDebug output = dbg.nospace(); - switch (mode) { - case CoreAudioSessionManager::Default: - output << "AudioSessionModeDefault"; - break; - case CoreAudioSessionManager::VoiceChat: - output << "AudioSessionModeVoiceChat"; - break; - case CoreAudioSessionManager::GameChat: - output << "AudioSessionModeGameChat"; - break; - case CoreAudioSessionManager::VideoRecording: - output << "AudioSessionModeVideoRecording"; - break; - case CoreAudioSessionManager::Measurement: - output << "AudioSessionModeMeasurement"; - break; - case CoreAudioSessionManager::MoviePlayback: - output << "AudioSessionModeMoviePlayback"; - break; - } - return output; -} -#endif - -QT_END_NAMESPACE - -#include "moc_coreaudiosessionmanager.cpp" diff --git a/src/plugins/coreaudio/coreaudioutils.h b/src/plugins/coreaudio/coreaudioutils.h deleted file mode 100644 index 7b67f9e41..000000000 --- a/src/plugins/coreaudio/coreaudioutils.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef IOSAUDIOUTILS_H -#define IOSAUDIOUTILS_H - -#include <CoreAudio/CoreAudioTypes.h> - -#include <QtMultimedia/QAudioFormat> -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class CoreAudioUtils -{ -public: - static quint64 currentTime(); - static double frequency(); - static QAudioFormat toQAudioFormat(const AudioStreamBasicDescription& streamFormat); - static AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat); - -private: - static void initialize(); - static double sFrequency; - static bool sIsInitialized; -}; - -class CoreAudioRingBuffer -{ -public: - typedef QPair<char*, int> Region; - - CoreAudioRingBuffer(int bufferSize); - ~CoreAudioRingBuffer(); - - Region acquireReadRegion(int size); - void releaseReadRegion(Region const& region); - Region acquireWriteRegion(int size); - void releaseWriteRegion(Region const& region); - - int used() const; - int free() const; - int size() const; - - void reset(); - -private: - int m_bufferSize; - int m_readPos; - int m_writePos; - char* m_buffer; - QAtomicInt m_bufferUsed; -}; - -QT_END_NAMESPACE - -#endif // IOSAUDIOUTILS_H diff --git a/src/plugins/coreaudio/coreaudioutils.mm b/src/plugins/coreaudio/coreaudioutils.mm deleted file mode 100644 index 1f9b9866c..000000000 --- a/src/plugins/coreaudio/coreaudioutils.mm +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "coreaudioutils.h" -#include <mach/mach_time.h> - -QT_BEGIN_NAMESPACE - -double CoreAudioUtils::sFrequency = 0.0; -bool CoreAudioUtils::sIsInitialized = false; - -void CoreAudioUtils::initialize() -{ - struct mach_timebase_info timeBaseInfo; - mach_timebase_info(&timeBaseInfo); - sFrequency = static_cast<double>(timeBaseInfo.denom) / static_cast<double>(timeBaseInfo.numer); - sFrequency *= 1000000000.0; - - sIsInitialized = true; -} - - -quint64 CoreAudioUtils::currentTime() -{ - return mach_absolute_time(); -} - -double CoreAudioUtils::frequency() -{ - if (!sIsInitialized) - initialize(); - return sFrequency; -} - -QAudioFormat CoreAudioUtils::toQAudioFormat(AudioStreamBasicDescription const& sf) -{ - QAudioFormat audioFormat; - - audioFormat.setSampleRate(sf.mSampleRate); - audioFormat.setChannelCount(sf.mChannelsPerFrame); - audioFormat.setSampleSize(sf.mBitsPerChannel); - audioFormat.setCodec(QString::fromLatin1("audio/pcm")); - audioFormat.setByteOrder((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian); - QAudioFormat::SampleType type = QAudioFormat::UnSignedInt; - if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) - type = QAudioFormat::SignedInt; - else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0) - type = QAudioFormat::Float; - audioFormat.setSampleType(type); - - return audioFormat; -} - -AudioStreamBasicDescription CoreAudioUtils::toAudioStreamBasicDescription(QAudioFormat const& audioFormat) -{ - AudioStreamBasicDescription sf; - - sf.mFormatFlags = kAudioFormatFlagIsPacked; - sf.mSampleRate = audioFormat.sampleRate(); - sf.mFramesPerPacket = 1; - sf.mChannelsPerFrame = audioFormat.channelCount(); - sf.mBitsPerChannel = audioFormat.sampleSize(); - sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8); - sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame; - sf.mFormatID = kAudioFormatLinearPCM; - - switch (audioFormat.sampleType()) { - case QAudioFormat::SignedInt: sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; break; - case QAudioFormat::UnSignedInt: /* default */ break; - case QAudioFormat::Float: sf.mFormatFlags |= kAudioFormatFlagIsFloat; break; - case QAudioFormat::Unknown: default: break; - } - - if (audioFormat.byteOrder() == QAudioFormat::BigEndian) - sf.mFormatFlags |= kAudioFormatFlagIsBigEndian; - - return sf; -} - -// QAudioRingBuffer -CoreAudioRingBuffer::CoreAudioRingBuffer(int bufferSize): - m_bufferSize(bufferSize) -{ - m_buffer = new char[m_bufferSize]; - reset(); -} - -CoreAudioRingBuffer::~CoreAudioRingBuffer() -{ - delete[] m_buffer; -} - -CoreAudioRingBuffer::Region CoreAudioRingBuffer::acquireReadRegion(int size) -{ - const int used = m_bufferUsed.fetchAndAddAcquire(0); - - if (used > 0) { - const int readSize = qMin(size, qMin(m_bufferSize - m_readPos, used)); - - return readSize > 0 ? Region(m_buffer + m_readPos, readSize) : Region(0, 0); - } - - return Region(0, 0); -} - -void CoreAudioRingBuffer::releaseReadRegion(const CoreAudioRingBuffer::Region ®ion) -{ - m_readPos = (m_readPos + region.second) % m_bufferSize; - - m_bufferUsed.fetchAndAddRelease(-region.second); -} - -CoreAudioRingBuffer::Region CoreAudioRingBuffer::acquireWriteRegion(int size) -{ - const int free = m_bufferSize - m_bufferUsed.fetchAndAddAcquire(0); - - Region output; - - if (free > 0) { - const int writeSize = qMin(size, qMin(m_bufferSize - m_writePos, free)); - output = writeSize > 0 ? Region(m_buffer + m_writePos, writeSize) : Region(0, 0); - } else { - output = Region(0, 0); - } -#ifdef QT_DEBUG_COREAUDIO - qDebug("acquireWriteRegion(%d) free: %d returning Region(%p, %d)", size, free, output.first, output.second); -#endif - return output; -} -void CoreAudioRingBuffer::releaseWriteRegion(const CoreAudioRingBuffer::Region ®ion) -{ - m_writePos = (m_writePos + region.second) % m_bufferSize; - - m_bufferUsed.fetchAndAddRelease(region.second); -#ifdef QT_DEBUG_COREAUDIO - qDebug("releaseWriteRegion(%p,%d): m_writePos:%d", region.first, region.second, m_writePos); -#endif -} - -int CoreAudioRingBuffer::used() const -{ - return m_bufferUsed.loadRelaxed(); -} - -int CoreAudioRingBuffer::free() const -{ - return m_bufferSize - m_bufferUsed.loadRelaxed(); -} - -int CoreAudioRingBuffer::size() const -{ - return m_bufferSize; -} - -void CoreAudioRingBuffer::reset() -{ - m_readPos = 0; - m_writePos = 0; - m_bufferUsed.storeRelaxed(0); -} - -QT_END_NAMESPACE |