Serenity Operating System
at portability 161 lines 6.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "ASClientConnection.h" 28#include "ASMixer.h" 29#include "AudioClientEndpoint.h" 30#include <AK/SharedBuffer.h> 31#include <LibAudio/Buffer.h> 32#include <LibCore/EventLoop.h> 33#include <errno.h> 34#include <stdio.h> 35#include <sys/socket.h> 36#include <sys/types.h> 37#include <sys/uio.h> 38#include <unistd.h> 39 40static HashMap<int, RefPtr<ASClientConnection>> s_connections; 41 42void ASClientConnection::for_each(Function<void(ASClientConnection&)> callback) 43{ 44 NonnullRefPtrVector<ASClientConnection> connections; 45 for (auto& it : s_connections) 46 connections.append(*it.value); 47 for (auto& connection : connections) 48 callback(connection); 49} 50 51ASClientConnection::ASClientConnection(Core::LocalSocket& client_socket, int client_id, ASMixer& mixer) 52 : IPC::ClientConnection<AudioServerEndpoint>(*this, client_socket, client_id) 53 , m_mixer(mixer) 54{ 55 s_connections.set(client_id, *this); 56} 57 58ASClientConnection::~ASClientConnection() 59{ 60} 61 62void ASClientConnection::die() 63{ 64 s_connections.remove(client_id()); 65} 66 67void ASClientConnection::did_finish_playing_buffer(Badge<ASBufferQueue>, int buffer_id) 68{ 69 post_message(Messages::AudioClient::FinishedPlayingBuffer(buffer_id)); 70} 71 72void ASClientConnection::did_change_muted_state(Badge<ASMixer>, bool muted) 73{ 74 post_message(Messages::AudioClient::MutedStateChanged(muted)); 75} 76 77OwnPtr<Messages::AudioServer::GreetResponse> ASClientConnection::handle(const Messages::AudioServer::Greet&) 78{ 79 return make<Messages::AudioServer::GreetResponse>(client_id()); 80} 81 82OwnPtr<Messages::AudioServer::GetMainMixVolumeResponse> ASClientConnection::handle(const Messages::AudioServer::GetMainMixVolume&) 83{ 84 return make<Messages::AudioServer::GetMainMixVolumeResponse>(m_mixer.main_volume()); 85} 86 87OwnPtr<Messages::AudioServer::SetMainMixVolumeResponse> ASClientConnection::handle(const Messages::AudioServer::SetMainMixVolume& message) 88{ 89 m_mixer.set_main_volume(message.volume()); 90 return make<Messages::AudioServer::SetMainMixVolumeResponse>(); 91} 92 93OwnPtr<Messages::AudioServer::EnqueueBufferResponse> ASClientConnection::handle(const Messages::AudioServer::EnqueueBuffer& message) 94{ 95 auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(message.buffer_id()); 96 if (!shared_buffer) { 97 // FIXME: The shared buffer should have been retrieved for us already. 98 // We don't want to do IPC error checking at this layer. 99 ASSERT_NOT_REACHED(); 100 } 101 102 if (!m_queue) 103 m_queue = m_mixer.create_queue(*this); 104 105 if (m_queue->is_full()) 106 return make<Messages::AudioServer::EnqueueBufferResponse>(false); 107 108 m_queue->enqueue(Audio::Buffer::create_with_shared_buffer(*shared_buffer, message.sample_count())); 109 return make<Messages::AudioServer::EnqueueBufferResponse>(true); 110} 111 112OwnPtr<Messages::AudioServer::GetRemainingSamplesResponse> ASClientConnection::handle(const Messages::AudioServer::GetRemainingSamples&) 113{ 114 int remaining = 0; 115 if (m_queue) 116 remaining = m_queue->get_remaining_samples(); 117 118 return make<Messages::AudioServer::GetRemainingSamplesResponse>(remaining); 119} 120 121OwnPtr<Messages::AudioServer::GetPlayedSamplesResponse> ASClientConnection::handle(const Messages::AudioServer::GetPlayedSamples&) 122{ 123 int played = 0; 124 if (m_queue) 125 played = m_queue->get_played_samples(); 126 127 return make<Messages::AudioServer::GetPlayedSamplesResponse>(played); 128} 129 130OwnPtr<Messages::AudioServer::SetPausedResponse> ASClientConnection::handle(const Messages::AudioServer::SetPaused& message) 131{ 132 if (m_queue) 133 m_queue->set_paused(message.paused()); 134 return make<Messages::AudioServer::SetPausedResponse>(); 135} 136 137OwnPtr<Messages::AudioServer::ClearBufferResponse> ASClientConnection::handle(const Messages::AudioServer::ClearBuffer& message) 138{ 139 if (m_queue) 140 m_queue->clear(message.paused()); 141 return make<Messages::AudioServer::ClearBufferResponse>(); 142} 143 144OwnPtr<Messages::AudioServer::GetPlayingBufferResponse> ASClientConnection::handle(const Messages::AudioServer::GetPlayingBuffer&) 145{ 146 int id = -1; 147 if (m_queue) 148 id = m_queue->get_playing_buffer(); 149 return make<Messages::AudioServer::GetPlayingBufferResponse>(id); 150} 151 152OwnPtr<Messages::AudioServer::GetMutedResponse> ASClientConnection::handle(const Messages::AudioServer::GetMuted&) 153{ 154 return make<Messages::AudioServer::GetMutedResponse>(m_mixer.is_muted()); 155} 156 157OwnPtr<Messages::AudioServer::SetMutedResponse> ASClientConnection::handle(const Messages::AudioServer::SetMuted& message) 158{ 159 m_mixer.set_muted(message.muted()); 160 return make<Messages::AudioServer::SetMutedResponse>(); 161}