genode-ehmry/repos/os/include/audio/sink.h
Emery Hemingway 5e8bc9ef51 WiP! Audio session redesign
Define a unified packet-buffer format for both Audio_out and Audio_in
sessions. This allows an Audio_out and an Audio_in client to exchange
packets with a common buffer and lexicon.

The sessions have also been stripped down to a minimum. The
'progress' and 'data_avail' signal handlers have been replaced with a
single 'progress' signal sent by Audio_in and received by Audio_in.

The Audio_in session has a reset signal delivered to the client to
indicate that the progress signal handler has been replaced (dubious).

These changes reflect a different relationship between the two sessions.
Drivers that play audio are now Audio_in clients and drive the rate that
packets can be consumed by sending progress signals.

Ref #2858
2019-06-28 16:17:03 +02:00

94 lines
1.8 KiB
C++

/*
* \brief Audio session consumer class
* \author Emery Hemingway
* \date 2019-06-13
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <audio_in_session/connection.h>
namespace Audio
{
struct Sink;
class Stereo_in;
};
struct Audio::Sink
{
virtual ~Sink() { }
virtual bool drain(float const *left, float const *right, Genode::size_t samples) = 0;
};
class Audio::Stereo_in
{
private:
Audio::Sink &_sink;
Audio_in::Connection _left, _right;
Genode::Signal_handler<Stereo_in> _reset_handler;
Genode::Signal_context_capability _progress_sigh { };
void _handle_reset()
{
_progress_sigh = _left.progress_sigh();
if (_progress_sigh.valid())
Genode::Signal_transmitter(_progress_sigh).submit();
}
public:
Stereo_in(Genode::Env &env, Sink &sink)
: _sink(sink), _left (env, "left"), _right(env, "right"),
_reset_handler(env.ep(), *this, &Stereo_in::_handle_reset)
{
_left.reset_sigh(_reset_handler);
_handle_reset();
}
/**
* Drain incoming audio from packet stream and
* transmit a progress signal to the source.
*/
bool progress()
{
using namespace Audio_in;
bool res = false;
while (!_left.stream().empty()) {
unsigned pos = _left.stream().play_pos();
Packet *left = _left.stream().get(pos);
Packet *right = _right.stream().get(pos);
if (!_sink.drain(left->content(), right->content(), PERIOD))
break;
left->played();
right->played();
_left.stream().increment_position();
_right.stream().increment_position();
res = true;
}
{
if (_progress_sigh.valid())
Genode::Signal_transmitter(_progress_sigh).submit();
}
return res;
}
};