51 lines
2.1 KiB
C++
51 lines
2.1 KiB
C++
#pragma once
|
|
#include <QString>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <atomic>
|
|
#include <thread>
|
|
|
|
/* GUI владеет подпиской, сессия — устройством. Одинаковый выбранный вход открывается один раз.
|
|
* Профиль трансляции имеет приоритет и сохраняется для рации после её остановки.
|
|
* Callback только копирует PCM; ready/stopped вызываются в GUI вне аппаратного callback.
|
|
* close() ждёт завершения своего callback, не останавливая устройство другого потребителя. */
|
|
class AudioCapture {
|
|
public:
|
|
enum class Role { Stream, Radio };
|
|
struct Frame {
|
|
const int16_t* pcm;
|
|
unsigned frames;
|
|
int channels;
|
|
int64_t timeUs;
|
|
uint64_t route;
|
|
bool measured, missing;
|
|
};
|
|
using Ready = std::function<bool(int channels, int nativeChannels)>;
|
|
using Callback = std::function<void(const Frame&)>;
|
|
AudioCapture() = default;
|
|
~AudioCapture();
|
|
AudioCapture(const AudioCapture&) = delete;
|
|
AudioCapture& operator=(const AudioCapture&) = delete;
|
|
bool open(const QString& input, Role role, int channels, uint64_t tag, Ready ready,
|
|
std::function<void()> stopped, Callback callback);
|
|
void close();
|
|
void closeAsync(); // GUI отсоединяет подписчика; последний backend закрывается в worker.
|
|
bool closing() const; // Включает переоткрытие общего backend для подстройки буфера.
|
|
void recover();
|
|
bool subscribed() const { return bool(m_session); }
|
|
bool running() const;
|
|
bool captureTimedOut() const;
|
|
private:
|
|
struct Session;
|
|
std::shared_ptr<Session> detach();
|
|
std::shared_ptr<Session> m_session;
|
|
std::thread m_closeThread;
|
|
std::atomic<bool> m_closeDone{true};
|
|
Ready m_ready;
|
|
std::function<void()> m_stopped;
|
|
Callback m_callback;
|
|
Role m_role = Role::Radio;
|
|
bool m_prepared = false;
|
|
};
|