2 * Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "anbox/platform/sdl/audio_sink.h"
19 #include "anbox/logger.h"
23 #include <boost/throw_exception.hpp>
26 const constexpr size_t max_queue_size{16};
32 AudioSink::AudioSink() :
34 queue_(max_queue_size) {
37 AudioSink::~AudioSink() {}
39 void AudioSink::on_data_requested(void *user_data, std::uint8_t *buffer, int size) {
40 auto thiz = static_cast<AudioSink*>(user_data);
41 thiz->read_data(buffer, size);
44 bool AudioSink::connect_audio() {
48 SDL_memset(&spec_, 0, sizeof(spec_));
50 spec_.format = AUDIO_S16;
53 spec_.callback = &AudioSink::on_data_requested;
54 spec_.userdata = this;
56 device_id_ = SDL_OpenAudioDevice(nullptr, 0, &spec_, nullptr, 0);
60 SDL_PauseAudioDevice(device_id_, 0);
65 void AudioSink::disconnect_audio() {
69 SDL_CloseAudioDevice(device_id_);
73 void AudioSink::read_data(std::uint8_t *buffer, int size) {
74 std::unique_lock<std::mutex> l(lock_);
75 const auto wanted = size;
79 while (count < wanted) {
80 if (read_buffer_left_ > 0) {
81 size_t avail = std::min<size_t>(wanted - count, read_buffer_left_);
83 read_buffer_.data() + (read_buffer_.size() - read_buffer_left_),
86 read_buffer_left_ -= avail;
90 bool blocking = (count == 0);
93 result = queue_.pop_locked(&read_buffer_, l);
95 result = queue_.try_pop_locked(&read_buffer_);
98 read_buffer_left_ = read_buffer_.size();
102 if (count > 0) break;
108 void AudioSink::write_data(const std::vector<std::uint8_t> &data) {
109 std::unique_lock<std::mutex> l(lock_);
110 if (!connect_audio()) {
111 WARNING("Audio server not connected, skipping %d bytes", data.size());
114 graphics::Buffer buffer{data.data(), data.data() + data.size()};
115 queue_.push_locked(std::move(buffer), l);
118 } // namespace platform