diff --git a/dde_oss/src/drivers/oss/main.cc b/dde_oss/src/drivers/oss/main.cc
index f0d624467..8be1fc013 100644
--- a/dde_oss/src/drivers/oss/main.cc
+++ b/dde_oss/src/drivers/oss/main.cc
@@ -19,7 +19,7 @@ extern "C" {
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/libports/src/lib/sdl/audio/SDL_genodeaudio.cc b/libports/src/lib/sdl/audio/SDL_genodeaudio.cc
index fbbad5022..5cff4c528 100644
--- a/libports/src/lib/sdl/audio/SDL_genodeaudio.cc
+++ b/libports/src/lib/sdl/audio/SDL_genodeaudio.cc
@@ -17,7 +17,7 @@
#include
#include
#include
-#include
+#include
#include
diff --git a/os/include/audio_out_session/audio_out_session.h b/os/include/audio_out_session/audio_out_session.h
index 0bce70d0a..d5d1ecca8 100644
--- a/os/include/audio_out_session/audio_out_session.h
+++ b/os/include/audio_out_session/audio_out_session.h
@@ -1,31 +1,33 @@
/*
- * \brief Audio-out session interface
- * \author Norman Feske
+ * \brief Audio_out session interface
* \author Sebastian Sumpf
- * \author Christian Helmuth
- * \author Stefan Kalkowski
- * \date 2009-12-02
+ * \date 2012-12-20
*
- * A audio-out session corresponds to one output channel, which can be used to
- * transmit audio frames. Payload is communicated over the packet-stream
- * interface set up between 'Session_client' and 'Session_server'. The term
- * _channel_ means literally one audio channel, e.g. front left or rear center.
- * Therefore, a standard two-channel stereo track needs two audio-out sessions
- * - one for "front left" and one for "front right". The channel format is
- * FLOAT_LE currently.
+ * An audio session corresponds to one output channel, which can be used to
+ * send audio frames. Each session consists of an 'Audio_out::Stream' object
+ * that resides in shared memory between the client and the server. The
+ * 'Audio_out::Stream' in turn consists of 'Audio_out::Packet's that contain
+ * the actual frames. Each packet within a stream is freely accessible or may
+ * be allocated successively. Also there is a current position pointer for each
+ * stream that is updated by the server. This way, it is possible to send
+ * sporadic events that need immediate processing as well as streams that rely
+ * on buffering.
*
- * Audio channel identifiers (loosly related to WAV channels) are:
+ * Audio_out channel identifiers (loosely related to WAV channels) are:
*
- * * Front left, right, center
- * * LFE (low frequency effets, subwoofer)
- * * Rear left, right, center
+ * * front left (or left), front right (or right), front center
+ * * lfe (low frequency effects, subwoofer)
+ * * rear left, rear right, rear center
*
* For example, consumer-oriented 6-channel (5.1) audio uses front
- * left/right/center, rear left/right and LFE.
+ * left/right/center, rear left/right and lfe.
+ *
+ * Note: That most components right now only support: "(front) left" and
+ * "(front) right".
*/
/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@@ -34,65 +36,295 @@
#ifndef _INCLUDE__AUDIO_OUT_SESSION__AUDIO_OUT_SESSION_H_
#define _INCLUDE__AUDIO_OUT_SESSION__AUDIO_OUT_SESSION_H_
-#include
-#include
+#include
#include
-#include
-#include
+#include
#include
+
namespace Audio_out {
+ class Packet;
+ class Stream;
+ class Session;
enum {
- QUEUE_SIZE = 16, /* buffer queue size */
- FRAME_SIZE = 4, /* frame size in bytes */
- PERIOD = 1024 /* frames per period */
- };
-
- struct Session : Genode::Session
- {
- typedef Packet_stream_policy Policy;
-
- typedef Packet_stream_tx::Channel Channel;
-
- static const char *service_name() { return "Audio_out"; }
-
- virtual ~Session() { }
-
- /**
- * Request client-side packet-stream interface of channel
- */
- virtual Channel::Source *stream() { return 0; }
-
- /**
- * Flush the audio buffer
- */
- virtual void flush(void) = 0;
-
- /**
- * Set synchronization session
- *
- * \param audio_out_session synchronization session
- *
- * Session can be kept in sync (or bundled) using this function, for
- * example, the left and right stero channels. A session has exactly
- * one synchronization session.
- */
- virtual void sync_session(Session_capability audio_out_session) = 0;
-
-
- /*******************
- ** RPC interface **
- *******************/
-
- GENODE_RPC(Rpc_flush, void, flush);
- GENODE_RPC(Rpc_sync_session, void, sync_session, Session_capability);
- GENODE_RPC(Rpc_channel_cap, Genode::Capability, channel_cap);
-
- GENODE_RPC_INTERFACE(Rpc_flush, Rpc_sync_session, Rpc_channel_cap);
+ QUEUE_SIZE = 16, /* buffer queue size */
+ PERIOD = 2048, /* samples per period */
+ SAMPLE_RATE = 44100,
+ SAMPLE_SIZE = sizeof(float),
};
}
+
+/**
+ * Audio_out packet containing frames
+ */
+class Audio_out::Packet
+{
+ private:
+
+ friend class Session_client;
+ friend class Stream;
+
+ bool _valid;
+ bool _wait_for_play;
+ float _data[PERIOD];
+
+ void _submit() { _valid = true; _wait_for_play = true; }
+ void _alloc() { _wait_for_play = false; _valid = false; }
+
+ public:
+
+ Packet() : _valid(false), _wait_for_play(false) { }
+
+ /**
+ * Copy data into packet, if there are less frames given than 'PERIOD',
+ * the remainder is filled with zeros
+ *
+ * \param data frames to copy in
+ * \param size number of frames to copy
+ */
+ void content(float *data, Genode::size_t samples)
+ {
+ Genode::memcpy(_data, data, (samples > PERIOD ? PERIOD : samples) * SAMPLE_SIZE);
+
+ if (samples < PERIOD)
+ Genode::memset(data + samples, 0, (PERIOD - samples) * SAMPLE_SIZE);
+ }
+
+ /**
+ * Get content
+ *
+ * \return pointer to frame data
+ */
+ float *content() { return _data; }
+
+ /**
+ * Play state
+ *
+ * \return true if the packet has been played back; false otherwise
+ */
+ bool played() const { return !_wait_for_play; }
+
+ /**
+ * Valid state
+ *
+ * The valid state of a packet describes that the packet has been
+ * processed by the server even though it may not have been played back
+ * if the packet is invalid. For example, if a server is a filter, the
+ * audio may not have been processed by the output driver.
+ *
+ * \return true if packet has *not* been processed yet; false otherwise
+ */
+ bool valid() const { return _valid; }
+
+ Genode::size_t size() const { return sizeof(_data); }
+
+
+ /**********************************************
+ ** Intended to be called by the server side **
+ **********************************************/
+
+ /**
+ * Invalidate packet, thus marking it as processed
+ */
+ void invalidate() { _valid = false; }
+
+ /**
+ * Mark a packet as played
+ */
+ void mark_as_played() { _wait_for_play = false; }
+};
+
+
+/**
+ * The audio-stream object containing packets
+ *
+ * The stream object is created upon session creation. The server will allocate
+ * a dataspace on the client's account. The client session will then request
+ * this dataspace and both client and server will attach it in their respective
+ * protection domain. After that, the stream pointer within a session will be
+ * pointed to the attached dataspace on both sides. Because the 'Stream' object
+ * is backed by shared memory, its constructor is never supposed to be called.
+ */
+class Audio_out::Stream
+{
+ private:
+
+ unsigned _pos; /* current playback position */
+ unsigned _tail; /* tail pointer used for allocations */
+ Packet _buf[QUEUE_SIZE]; /* packet queue */
+
+ public:
+
+ /**
+ * Exceptions
+ */
+ class Alloc_failed { };
+
+ /**
+ * Current audio playback position
+ *
+ * \return position
+ */
+ unsigned pos() const { return _pos; }
+
+ /**
+ * Retrieve next packet for given packet
+ *
+ * \param packet preceding packet
+ *
+ * \return Successor of packet or successor of current position if
+ * 'packet' is zero
+ */
+ Packet *next(Packet *packet = 0)
+ {
+ return packet ? get(packet_position(packet) + 1) : get(pos() + 1);
+ }
+
+ /**
+ * Retrieves the position of a given packet in the stream queue
+ *
+ * \param packet a packet
+ *
+ * \return position in stream queue
+ */
+ unsigned packet_position(Packet *packet) { return packet - &_buf[0]; }
+
+ /**
+ * Check if stream queue is full/empty
+ */
+ bool empty() const
+ {
+ bool valid = false;
+ for (int i = 0; i < QUEUE_SIZE; i++)
+ valid |= _buf[i].valid();
+
+ return !valid;
+ }
+
+ bool full() const { return (_tail + 1) % QUEUE_SIZE == _pos; }
+
+ /**
+ * Retrieve an audio at given position
+ *
+ * \param pos position in stream
+ *
+ * \return Audio_out packet
+ */
+ Packet *get(unsigned pos) { return &_buf[pos % QUEUE_SIZE]; }
+
+
+ /**
+ * Allocate a packet in stream
+ *
+ * \return Packet
+ * \throw Alloc_failed when stream queue is full
+ */
+ Packet *alloc()
+ {
+ if (full())
+ throw Alloc_failed();
+
+ unsigned pos = _tail;
+ _tail = (_tail + 1) % QUEUE_SIZE;
+
+ Packet *p = get(pos);
+ p->_alloc();
+
+ return p;
+ }
+
+ /**
+ * Reset stream queue
+ *
+ * This means that allocation will start at current queue position.
+ */
+ void reset() { _tail = _pos; }
+
+
+ /**********************************************
+ ** Intended to be called by the server side **
+ ***********************************************/
+
+ /**
+ * Set current stream position
+ *
+ * \param pos current position
+ */
+ void pos(unsigned p) { _pos = p; }
+
+ /**
+ * Increment current stream position by one
+ */
+ void increment_position() { _pos = (_pos + 1) % QUEUE_SIZE; }
+};
+
+
+/**
+ * Audio_out session base
+ */
+class Audio_out::Session : public Genode::Session
+{
+ protected:
+
+ Stream *_stream;
+
+ public:
+
+ static const char *service_name() { return "Audio_out"; }
+
+ /**
+ * Return stream of this session, see 'Stream' above
+ */
+ Stream *stream() const { return _stream; }
+
+ /**
+ * Start playback (alloc and submit packets after calling 'start')
+ */
+ virtual void start() = 0;
+
+ /**
+ * Stop playback
+ */
+ virtual void stop() = 0;
+
+
+ /*************
+ ** Signals **
+ *************/
+
+ /**
+ * The 'progress' signal is sent from the server to the client if a
+ * packet has been played.
+ *
+ * See: client.h, connection.h
+ */
+ virtual void progress_sigh(Genode::Signal_context_capability sigh) = 0;
+
+ /**
+ * The 'alloc' signal is sent from the server to the client when the
+ * stream queue leaves the 'full' state.
+ *
+ * See: client.h, connection.h
+ */
+ virtual void alloc_sigh(Genode::Signal_context_capability sigh) = 0;
+
+ /**
+ * The 'data_avail' signal is sent from the client to the server if the
+ * stream queue leaves the 'empty' state.
+ */
+ virtual Genode::Signal_context_capability data_avail_sigh() = 0;
+
+ GENODE_RPC(Rpc_start, void, start);
+ GENODE_RPC(Rpc_stop, void, stop);
+ GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace);
+ GENODE_RPC(Rpc_progress_sigh, void, progress_sigh, Genode::Signal_context_capability);
+ GENODE_RPC(Rpc_alloc_sigh, void, alloc_sigh, Genode::Signal_context_capability);
+ GENODE_RPC(Rpc_data_avail_sigh, Genode::Signal_context_capability, data_avail_sigh);
+
+ GENODE_RPC_INTERFACE(Rpc_start, Rpc_stop, Rpc_dataspace, Rpc_progress_sigh,
+ Rpc_alloc_sigh, Rpc_data_avail_sigh);
+};
+
#endif /* _INCLUDE__AUDIO_OUT_SESSION__AUDIO_OUT_SESSION_H_ */
diff --git a/os/include/audio_out_session/capability.h b/os/include/audio_out_session/capability.h
index 3f70b605f..5633ee437 100644
--- a/os/include/audio_out_session/capability.h
+++ b/os/include/audio_out_session/capability.h
@@ -25,6 +25,7 @@ namespace Audio_out {
* because this file relies on the 'Audio_out::Session_capability' type.
*/
class Session;
- typedef Genode::Capability Session_capability; }
+ typedef Genode::Capability Session_capability;
+}
#endif /* _INCLUDE__AUDIO_OUT_SESSION__CAPABILITY_H_ */
diff --git a/os/include/audio_out_session/client.h b/os/include/audio_out_session/client.h
index 6ecb02b07..90bcea069 100644
--- a/os/include/audio_out_session/client.h
+++ b/os/include/audio_out_session/client.h
@@ -1,14 +1,11 @@
/*
- * \brief Client-side audio-out session interface
- * \author Norman Feske
+ * \brief Client-side Audio_out-session
* \author Sebastian Sumpf
- * \author Christian Helmuth
- * \author Stefan Kalkowski
- * \date 2009-12-02
+ * \date 2012-12-20
*/
/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@@ -17,58 +14,138 @@
#ifndef _INCLUDE__AUDIO_OUT_SESSION__CLIENT_H_
#define _INCLUDE__AUDIO_OUT_SESSION__CLIENT_H_
+#include
#include
#include
-#include
namespace Audio_out {
-
- class Session_client : public Genode::Rpc_client
- {
- private:
-
- Packet_stream_tx::Client _channel;
-
- Session_capability _cap;
-
- public:
-
- /**
- * Constructor
- *
- * \param session Audio-out session capability
- * \param buffer_alloc allocator used for managing the
- * transmission buffer
- */
- Session_client(Genode::Capability session,
- Genode::Range_allocator *buffer_alloc)
- :
- Genode::Rpc_client(session),
- _channel(call(), buffer_alloc),
- _cap(session)
- { }
-
- /**
- * Return session capability of this session
- *
- * This function is meant to be used to obtain the argument for the
- * 'sync_session' function called for another 'Audio_out' session.
- */
- Session_capability session_capability() { return _cap; }
-
- Session::Channel *channel() { return &_channel; }
-
- /*********************************
- ** Audio-out session interface **
- *********************************/
-
- Session::Channel::Source *stream() { return _channel.source(); }
-
- void flush(void) { call(); }
-
- void sync_session(Session_capability audio_out_session) {
- call(audio_out_session); }
- };
+ struct Signal;
+ struct Session_client;
}
+
+struct Audio_out::Signal
+{
+ Genode::Signal_receiver recv;
+ Genode::Signal_context context;
+ Genode::Signal_context_capability cap;
+
+ Signal() : cap(recv.manage(&context)) { }
+
+ void wait() { recv.wait_for_signal(); }
+};
+
+
+class Audio_out::Session_client : public Genode::Rpc_client
+{
+ private:
+
+ Signal _progress;
+ Signal _alloc;
+
+ Genode::Signal_transmitter _data_avail;
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param session session capability
+ * \param alloc_signal true, install 'alloc_signal' receiver
+ * \param progress_signal true, install 'progress_signal' receiver
+ */
+ Session_client(Genode::Capability session, bool alloc_signal,
+ bool progress_signal)
+ :
+ Genode::Rpc_client(session),
+ _data_avail(call())
+ {
+ /* ask server for stream data space and attach it */
+ _stream = static_cast(Genode::env()->rm_session()->attach(call()));
+
+ if (progress_signal)
+ progress_sigh(_progress.cap);
+
+ if (alloc_signal)
+ alloc_sigh(_alloc.cap);
+ }
+
+
+ /*************
+ ** Signals **
+ *************/
+
+ void progress_sigh(Genode::Signal_context_capability sigh) {
+ call(sigh); }
+
+ void alloc_sigh(Genode::Signal_context_capability sigh) {
+ call(sigh); }
+
+ Genode::Signal_context_capability data_avail_sigh() {
+ return Genode::Signal_context_capability(); }
+
+
+ /***********************
+ ** Session interface **
+ ***********************/
+
+ void start()
+ {
+ call();
+
+ /* reset tail pointer */
+ stream()->reset();
+ }
+
+ void stop() { call(); }
+
+
+ /**********************************
+ ** Session interface extensions **
+ **********************************/
+
+ /**
+ * Wait for progress signal
+ */
+ void wait_for_progress()
+ {
+ if (!_progress.cap.valid()) {
+ PWRN("Progress signal is not installed, will not block "
+ "(enable in 'Audio_out::Connection')");
+ return;
+ }
+
+ _progress.wait();
+ }
+
+ /**
+ * Wait for allocation signal
+ *
+ * This can be used when the 'Stream' is full and the application wants
+ * to block until the stream has free elements again.
+ */
+ void wait_for_alloc()
+ {
+ if (!_alloc.cap.valid()) {
+ PWRN("Alloc signal is not installed, will not block "
+ "(enable in 'Audio_out::Connection')");
+ return;
+ }
+
+ _alloc.wait();
+ }
+
+ /**
+ * Submit a packet
+ */
+ void submit(Packet *packet)
+ {
+ bool empty = stream()->empty();
+
+ packet->_submit();
+ if (empty)
+ _data_avail.submit();
+ }
+};
+
#endif /* _INCLUDE__AUDIO_OUT_SESSION__CLIENT_H_ */
diff --git a/os/include/audio_out_session/connection.h b/os/include/audio_out_session/connection.h
index f4f3b40d9..b320f0712 100644
--- a/os/include/audio_out_session/connection.h
+++ b/os/include/audio_out_session/connection.h
@@ -1,13 +1,11 @@
/*
- * \brief Connection to audio-out service
- * \author Norman Feske
+ * \brief Connection to audio service
* \author Sebastian Sumpf
- * \author Christian Helmuth
- * \date 2009-12-01
+ * \date 2012-12-20
*/
/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@@ -20,30 +18,33 @@
#include
#include
-namespace Audio_out {
- struct Connection : Genode::Connection, Session_client
- {
- /**
- * Constructor
- *
- * \param channel channel identifier (e.g., "front left")
- * \param buffer_alloc allocator used for managing the
- * transmission buffer
- * \param buffer_size size of transmission buffer in bytes
- * (defaults to all packets of the queue plus
- * some space for metadata)
- */
- Connection(const char *channel,
- Genode::Range_allocator *buffer_alloc,
- Genode::size_t buffer_size = QUEUE_SIZE * FRAME_SIZE * PERIOD + 0x400)
- :
- Genode::Connection(
- session("ram_quota=%zd, channel=\"%s\", buffer_size=%zd",
- 3*4096 + buffer_size, channel, buffer_size)),
- Session_client(cap(), buffer_alloc)
- { }
- };
+namespace Audio_out {
+ struct Connection;
}
+
+struct Audio_out::Connection : Genode::Connection, Audio_out::Session_client
+{
+ /**
+ * Constructor
+ *
+ * \param channel channel identifier (e.g., "front left")
+ * \param alloc_signal install 'alloc_signal', the client may then use
+ * 'wait_for_alloc' when the stream is full
+ * \param progress_signal install progress signal, the client may then
+ * call 'wait_for_progress', which is sent when the
+ * server processed one or more packets
+ */
+ Connection(const char *channel,
+ bool alloc_signal = true,
+ bool progress_signal = false)
+ :
+ Genode::Connection(
+ session("ram_quota=%zd, channel=\"%s\"",
+ 2*4096 + sizeof(Stream), channel)),
+ Session_client(cap(), alloc_signal, progress_signal)
+ { }
+};
+
#endif /* _INCLUDE__AUDIO_OUT_SESSION__CONNECTION_H_ */
diff --git a/os/include/audio_out_session/rpc_object.h b/os/include/audio_out_session/rpc_object.h
index a78740ac4..7c61651be 100644
--- a/os/include/audio_out_session/rpc_object.h
+++ b/os/include/audio_out_session/rpc_object.h
@@ -1,14 +1,11 @@
/*
- * \brief Server-side audio-out session interface
- * \author Norman Feske
+ * \brief Server-side audio-session interface
* \author Sebastian Sumpf
- * \author Christian Helmuth
- * \author Stefan Kalkowski
- * \date 2009-12-02
+ * \date 2012-12-10
*/
/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@@ -17,41 +14,112 @@
#ifndef _INCLUDE__AUDIO_OUT_SESSION__RPC_OBJECT_H_
#define _INCLUDE__AUDIO_OUT_SESSION__RPC_OBJECT_H_
+#include
#include
#include
-#include
+
namespace Audio_out {
-
- class Session_rpc_object : public Genode::Rpc_object
- {
- protected:
-
- Packet_stream_tx::Rpc_object _channel;
-
- public:
-
- /**
- * Constructor
- *
- * \param ds dataspace used as communication buffer
- * for the packet stream
- * \param ep entry point used for packet-stream channel
- */
- Session_rpc_object(Genode::Dataspace_capability ds,
- Genode::Rpc_entrypoint &ep)
- : _channel(ds, ep) { }
-
- /**
- * Return capability to packet-stream channel
- *
- * This function is called by the client via an RPC call at session
- * construction time.
- */
- Genode::Capability channel_cap() { return _channel.cap(); }
-
- Channel::Sink *channel() { return _channel.sink(); }
- };
+ class Session_rpc_object;
}
+
+class Audio_out::Session_rpc_object : public Genode::Rpc_object
+{
+ protected:
+
+ bool _stopped; /* state */
+ Genode::Ram_dataspace_capability _ds; /* contains Audio_out_stream */
+ Genode::Signal_transmitter _progress;
+ Genode::Signal_transmitter _alloc;
+
+ Genode::Signal_context_capability _data_cap;
+
+ bool _progress_sigh; /* progress signal on/off */
+ bool _alloc_sigh; /* alloc signal on/off */
+
+ public:
+
+ Session_rpc_object(Genode::Signal_context_capability data_cap)
+ :
+ _stopped(true), _data_cap(data_cap),
+ _progress_sigh(false), _alloc_sigh(false)
+ {
+ _ds = Genode::env()->ram_session()->alloc(sizeof(Stream));
+ _stream = static_cast(Genode::env()->rm_session()->attach(_ds));
+ }
+
+ virtual ~Session_rpc_object()
+ {
+ if (_ds.valid()) {
+ Genode::env()->rm_session()->detach(_stream);
+ Genode::env()->ram_session()->free(_ds);
+ }
+ }
+
+
+ /**************
+ ** Signals **
+ **************/
+
+ void progress_sigh(Genode::Signal_context_capability sigh)
+ {
+ _progress.context(sigh);
+ _progress_sigh = true;
+ }
+
+ Genode::Signal_context_capability data_avail_sigh() {
+ return _data_cap; }
+
+ void alloc_sigh(Genode::Signal_context_capability sigh)
+ {
+ _alloc.context(sigh);
+ _alloc_sigh = true;
+ }
+
+
+ /***********************
+ ** Session interface **
+ ***********************/
+
+ void start() { _stopped = false; }
+ void stop() { _stopped = true; }
+
+ Genode::Dataspace_capability dataspace() { return _ds; }
+
+
+ /**********************************
+ ** Session interface extensions **
+ **********************************/
+
+ /**
+ * Send 'progress' signal
+ */
+ void progress_submit()
+ {
+ if (_progress_sigh)
+ _progress.submit();
+ }
+
+ /**
+ * Send 'alloc' signal
+ */
+ void alloc_submit()
+ {
+ if (_alloc_sigh)
+ _alloc.submit();
+ }
+
+ /**
+ * Return true if client state is stopped
+ */
+ bool stopped() const { return _stopped; }
+
+ /**
+ * Return true if client session is active
+ */
+ bool active() const { return !_stopped; }
+};
+
#endif /* _INCLUDE__AUDIO_OUT_SESSION__RPC_OBJECT_H_ */
diff --git a/os/include/audio_session/audio_session.h b/os/include/audio_session/audio_session.h
deleted file mode 100644
index 0f6675a20..000000000
--- a/os/include/audio_session/audio_session.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * \brief Audio_out session interface
- * \author Sebastian Sumpf
- * \date 2012-12-20
- *
- * An audio session corresponds to one output channel, which can be used to send
- * audio frames. Each session consists of an 'Audio_out::Stream' object that resides
- * in shared memory between the client and the server. The 'Audio_out::Stream' in
- * turn consists of 'Audio_out::Packet's that contain the actual frames. Each packet
- * within a stream is freely accessible or may be allocated successively. Also
- * there is a current position pointer for each stream that is updated by the
- * server. This way it is possible to send one time events that need immediate
- * processing as well as streams that rely on buffering.
- *
- * Audio_out channel identifiers (loosely related to WAV channels) are:
- *
- * * front left (or left), front right (or right), front center
- * * lfe (low frequency effects, subwoofer)
- * * rear left, rear right, rear center
- *
- * For example, consumer-oriented 6-channel (5.1) audio uses front
- * left/right/center, rear left/right and lfe.
- *
- * Note: That most components right now only support: "(front) left" and
- * "(front) right".
- *
- */
-
-/*
- * Copyright (C) 2012 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__AUDIO_SESSION__AUDIO_SESSION_H_
-#define _INCLUDE__AUDIO_SESSION__AUDIO_SESSION_H_
-
-#include
-#include
-#include
-#include
-
-namespace Audio_out {
- class Packet;
- class Stream;
- class Session;
-
- enum {
- QUEUE_SIZE = 16, /* buffer queue size */
- PERIOD = 2048, /* samples per period */
- SAMPLE_RATE = 44100,
- SAMPLE_SIZE = sizeof(float),
- };
-}
-
-/**
- * Audio_out packet containing frames
- */
-class Audio_out::Packet
-{
- private:
-
- friend class Session_client;
- friend class Stream;
-
- bool _valid;
- bool _wait_for_play;
- float _data[PERIOD];
-
- void _submit() { _valid = true; _wait_for_play = true; }
- void _alloc() { _wait_for_play = false; _valid = false; }
-
- public:
-
- Packet() : _valid(false), _wait_for_play(false) { }
-
- /**
- * Copy data into packet, if there are less frames given than 'PERIOD',
- * then the remainder is filled with zeros
- *
- * \param data frames to copy in
- * \param size number of frames to copy
- */
- void content(float *data, Genode::size_t samples)
- {
- Genode::memcpy(_data, data, (samples > PERIOD ? PERIOD : samples) * SAMPLE_SIZE);
-
- if (samples < PERIOD)
- Genode::memset(data + samples, 0, (PERIOD - samples) * SAMPLE_SIZE);
- }
-
- /**
- * Get content
- *
- * \return pointer to frame data
- */
- float *content() { return _data; }
-
- /**
- * Play state
- *
- * \return true if the packet has been played back; false otherwise
- */
- bool played() const { return !_wait_for_play; }
-
- /**
- * Valid state
- *
- * The valid state of a packet describes that the packet has been
- * processed by the server, it may not have been played back if the packet
- * is invalid. For example if a server is some filter, the audio may not
- * have been processed by the audio output driver.
- *
- * \return true packet has *not* been processed yet; false otherwise
- */
- bool valid() const { return _valid; }
- Genode::size_t size() const { return sizeof(_data); }
-
-
- /**********************************************
- ** Intended to be called by the server side **
- **********************************************/
-
- /**
- * Invalidate packet thus marking it as processed
- */
- void invalidate() { _valid = false; }
-
- /**
- * Mark a packet as played
- */
- void mark_as_played() { _wait_for_play = false; }
-};
-
-
-/**
- * The audio stream object containing packets
- *
- * The stream object is created upon session creation. The server will
- * allocate a dataspace on the clients account, the client session will then request this
- * dataspace as well and both will attach it in there protection domains.
- * After that the stream pointer within a session will be pointed to the
- * attached dataspace on both sides. Therefore the constructor of the 'Stream'
- * object will never be called.
- */
-class Audio_out::Stream
-{
- private:
-
- unsigned _pos; /* current playback position */
- unsigned _tail; /* tail pointer used for allocations */
- Packet _buf[QUEUE_SIZE]; /* packet queue */
-
- public:
-
- /**
- * Exceptions
- */
- class Alloc_failed { };
-
- /**
- * Current audio playback position
- *
- * \return position
- */
- unsigned pos() const { return _pos; }
-
-
- /**
- * Retrieve next packet for given packet
- *
- * \param packet preceding packet
- *
- * \return Successor of packet or successor of current position if
- * 'packet' is zero
- */
- Packet *next(Packet *packet = 0)
- {
- return packet ? get(packet_position(packet) + 1) : get(pos() + 1);
- }
-
- /**
- * Retrieves the position of a given packet in the stream queue
- *
- * \param packet a packet
- *
- * \return position in stream queue
- */
- unsigned packet_position(Packet *packet) { return packet - &_buf[0]; }
-
-
- /**
- * Check if stream queue is full/empty
- */
- bool empty() const
- {
- bool valid = false;
- for (int i = 0; i < QUEUE_SIZE; i++)
- valid |= _buf[i].valid();
-
- return !valid;
- }
-
- bool full() const { return (_tail + 1) % QUEUE_SIZE == _pos; }
-
-
- /**
- * Retrieve an audio at given position
- *
- * \param pos position in stream
- *
- * \retun Audio_out packet
- */
- Packet *get(unsigned pos) { return &_buf[pos % QUEUE_SIZE]; }
-
-
- /**
- * Allocate a packet in stream
- *
- * \return Packet
- * \throw Alloc_failed when stream queue is full
- */
- Packet *alloc()
- {
- if (full())
- throw Alloc_failed();
-
- unsigned pos = _tail;
- _tail = (_tail + 1) % QUEUE_SIZE;
-
- Packet *p = get(pos);
- p->_alloc();
-
- return p;
- }
-
- /**
- * Reset stream queue, this means that allocation will start at current
- * queue position
- */
- void reset() { _tail = _pos; }
-
-
- /**********************************************
- ** Intended to be called by the server side **
- ***********************************************/
-
- /**
- * Set current stream position
- *
- * \param pos current position
- */
- void pos(unsigned p) { _pos = p; }
-
- /**
- * Increment current stream position by one
- */
- void increment_position() { _pos = (_pos + 1) % QUEUE_SIZE; }
-};
-
-
-/**
- * Audio_out session base
- */
-class Audio_out::Session : public Genode::Session
-{
- protected:
-
- Stream *_stream;
-
- public:
-
- static const char *service_name() { return "Audio_out"; }
-
- /**
- * Return stream of this session, see 'Stream' above
- */
- Stream *stream() const { return _stream; }
-
- /**
- * Start playback (alloc and submit packets after calling 'start')
- */
- virtual void start() = 0;
-
- /**
- * Stop playback
- */
- virtual void stop() = 0;
-
-
- /*************
- ** Signals **
- *************/
-
-
- /**
- * The 'progress' signal may be sent from the server to the client if a
- * packet has been played.
- *
- * See: client.h, connection.h
- */
- virtual void progress_sigh(Genode::Signal_context_capability sigh) = 0;
-
- /**
- * The 'alloc' signal may be sent from the server to the client when the
- * stream queue leaves the 'full' state.
- *
- * See: client.h, connection.h
- */
- virtual void alloc_sigh(Genode::Signal_context_capability sigh) = 0;
-
- /**
- * The 'data_avail' signal is sent from the client to the surfer the
- * stream queue leaves the 'empty' state.
- */
- virtual Genode::Signal_context_capability data_avail_sigh() = 0;
-
- GENODE_RPC(Rpc_start, void, start);
- GENODE_RPC(Rpc_stop, void, stop);
- GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace);
- GENODE_RPC(Rpc_progress_sigh, void, progress_sigh, Genode::Signal_context_capability);
- GENODE_RPC(Rpc_alloc_sigh, void, alloc_sigh, Genode::Signal_context_capability);
- GENODE_RPC(Rpc_data_avail_sigh, Genode::Signal_context_capability, data_avail_sigh);
-
- GENODE_RPC_INTERFACE(Rpc_start, Rpc_stop, Rpc_dataspace, Rpc_progress_sigh,
- Rpc_alloc_sigh, Rpc_data_avail_sigh);
-};
-
-#endif /* _INCLUDE__AUDIO_SESSION__AUDIO_SESSION_H_ */
diff --git a/os/include/audio_session/client.h b/os/include/audio_session/client.h
deleted file mode 100644
index 1e5280f1e..000000000
--- a/os/include/audio_session/client.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * \brief Audio_out-session-client side
- * \author Sebastian Sumpf
- * \date 2012-12-20
- */
-
-/*
- * Copyright (C) 2012 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__AUDIO_SESSEN__CLIENT_H_
-#define _INCLUDE__AUDIO_SESSEN__CLIENT_H_
-
-#include
-#include
-#include
-
-namespace Audio_out {
- struct Signal;
- struct Session_client;
-}
-
-
-struct Audio_out::Signal
-{
- Genode::Signal_receiver recv;
- Genode::Signal_context context;
- Genode::Signal_context_capability cap;
-
- Signal() : cap(recv.manage(&context)) { }
-
- void wait() { recv.wait_for_signal(); }
-};
-
-
-class Audio_out::Session_client : public Genode::Rpc_client
-{
- private:
-
- Signal _progress;
- Signal _alloc;
-
- Genode::Signal_transmitter _data_avail;
-
- public:
-
- /**
- * Constructor
- *
- * \param session session capability
- * \param alloc_signal true, install 'alloc_signal' receiver
- * \param progress_signal true, install 'progress_signal' receiver
- */
- Session_client(Genode::Capability session, bool alloc_signal, bool progress_signal)
- :
- Genode::Rpc_client(session),
- _data_avail(call())
- {
- /* ask server for stream data space and attach it */
- _stream = static_cast(Genode::env()->rm_session()->attach(call()));
-
- if (progress_signal)
- progress_sigh(_progress.cap);
-
- if (alloc_signal)
- alloc_sigh(_alloc.cap);
-
- }
-
-
- /*************
- ** Signals **
- *************/
-
- void progress_sigh(Genode::Signal_context_capability sigh) { call(sigh); }
- void alloc_sigh(Genode::Signal_context_capability sigh) { call(sigh); }
-
- Genode::Signal_context_capability data_avail_sigh() {
- return Genode::Signal_context_capability(); }
-
-
- /***********************
- ** Session interface **
- ***********************/
-
- void start()
- {
- call();
-
- /* reset tail pointer */
- stream()->reset();
- }
-
- void stop() { call(); }
-
-
- /**********************************
- ** Session interface extensions **
- **********************************/
-
- /**
- * Wait for progress signal
- */
- void wait_for_progress()
- {
- if (!_progress.cap.valid()) {
- PWRN("Progress signal is not installed, will not block "
- "(enable in 'Audio_out::Connection')");
- return;
- }
-
- _progress.wait();
- }
-
- /**
- * Wait for allocation signal. This can be used when the 'Stream' is full
- * and the applications want for block until the stream has free elements
- * again.
- */
- void wait_for_alloc()
- {
- if (!_alloc.cap.valid()) {
- PWRN("Alloc signal is not installed, will not block "
- "(enable in 'Audio_out::Connection')");
- return;
- }
-
- _alloc.wait();
- }
-
- /**
- * Submit a packet
- */
- void submit(Packet *packet)
- {
- bool empty = stream()->empty();
-
- packet->_submit();
- if (empty)
- _data_avail.submit();
- }
-};
-
-#endif /* _INCLUDE__AUDIO_SESSEN__CLIENT_H_ */
diff --git a/os/include/audio_session/connection.h b/os/include/audio_session/connection.h
deleted file mode 100644
index cde360eaf..000000000
--- a/os/include/audio_session/connection.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * \brief Connection to audio service
- * \author Sebastian Sumpf
- * \date 2012-12-20
- */
-
-/*
- * Copyright (C) 2012 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__AUDIO_SESSION__CONNECTION_H_
-#define _INCLUDE__AUDIO_SESSION__CONNECTION_H_
-
-#include
-#include
-#include
-
-
-namespace Audio_out {
- struct Connection;
-}
-
-
-struct Audio_out::Connection : Genode::Connection, Audio_out::Session_client
-{
- /**
- * Constructor
- *
- * \param channel channel identifier (e.g., "front left")
- * \param alloc_signal install 'alloc_signal', the client may thean use
- * 'wait_for_alloc' when the stream is full
- * \param progress_signal install progress signal, the client may then call
- * 'wait_for_progress' which is send when the server
- * processed one or more packets
- */
- Connection(const char *channel,
- bool alloc_signal = true,
- bool progress_signal = false)
- :
- Genode::Connection(
- session("ram_quota=%zd, channel=\"%s\"",
- 2*4096 + sizeof(Stream), channel)),
- Session_client(cap(), alloc_signal, progress_signal)
- { }
-};
-
-
-#endif /* _INCLUDE__AUDIO_SESSION__CONNECTION_H_ */
diff --git a/os/include/audio_session/rpc_object.h b/os/include/audio_session/rpc_object.h
deleted file mode 100644
index 722a57402..000000000
--- a/os/include/audio_session/rpc_object.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * \brief Server side audio-session interface
- * \author Sebastian Sumpf
- * \date 2012-12-10
- */
-
-/*
- * Copyright (C) 2012 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__AUDIO_SESSION__RPC_OBJECT_H_
-#define _INCLUDE__AUDIO_SESSION__RPC_OBJECT_H_
-
-#include
-#include
-#include
-
-
-namespace Audio_out {
- class Session_rpc_object;
-}
-
-
-class Audio_out::Session_rpc_object : public Genode::Rpc_object
-{
- protected:
-
- bool _stopped; /* state */
- Genode::Ram_dataspace_capability _ds; /* contains Audio_out_stream */
- Genode::Signal_transmitter _progress;
- Genode::Signal_transmitter _alloc;
-
- Genode::Signal_context_capability _data_cap;
-
- bool _progress_sigh; /* progress signal on/off */
- bool _alloc_sigh; /* alloc signal on/off */
-
- public:
-
- Session_rpc_object(Genode::Signal_context_capability data_cap)
- :
- _stopped(true), _data_cap(data_cap),
- _progress_sigh(false), _alloc_sigh(false)
- {
- _ds = Genode::env()->ram_session()->alloc(sizeof(Stream));
- _stream = static_cast(Genode::env()->rm_session()->attach(_ds));
- }
-
- virtual ~Session_rpc_object()
- {
- if (_ds.valid()) {
- Genode::env()->rm_session()->detach(_stream);
- Genode::env()->ram_session()->free(_ds);
- }
- }
-
- /**************
- ** Signals **
- **************/
-
- void progress_sigh(Genode::Signal_context_capability sigh)
- {
- _progress.context(sigh);
- _progress_sigh = true;
- }
-
- Genode::Signal_context_capability data_avail_sigh() {
- return _data_cap; }
-
- void alloc_sigh(Genode::Signal_context_capability sigh)
- {
- _alloc.context(sigh);
- _alloc_sigh = true;
- }
-
-
- /***********************
- ** Session interface **
- ***********************/
-
- void start() { _stopped = false; }
- void stop() { _stopped = true; }
-
- Genode::Dataspace_capability dataspace() { return _ds; }
-
-
- /**********************************
- ** Session interface extensions **
- **********************************/
-
- /**
- * Send 'progress' signal
- */
- void progress_submit()
- {
- if (_progress_sigh)
- _progress.submit();
- }
-
- /**
- * Send 'alloc' signal
- */
- void alloc_submit()
- {
- if (_alloc_sigh)
- _alloc.submit();
- }
-
- /**
- * Return true if client state is stopped
- */
- bool stopped() const { return _stopped; }
-
- /**
- * Return true if client session is active
- */
- bool active() const { return !_stopped; }
-};
-
-#endif /* _INCLUDE__AUDIO_SESSION__RPC_OBJECT_H_ */
diff --git a/os/src/drivers/audio_out/linux/main.cc b/os/src/drivers/audio_out/linux/main.cc
index 2d98162de..15bac4fbf 100644
--- a/os/src/drivers/audio_out/linux/main.cc
+++ b/os/src/drivers/audio_out/linux/main.cc
@@ -20,7 +20,7 @@
#include
#include
#include
-#include
+#include
#include
#include "alsa.h"
diff --git a/os/src/server/mixer/mixer.cc b/os/src/server/mixer/mixer.cc
index 9df8df353..b615424ff 100644
--- a/os/src/server/mixer/mixer.cc
+++ b/os/src/server/mixer/mixer.cc
@@ -19,8 +19,8 @@
#include
#include
-#include
-#include
+#include
+#include
#include
#include
#include
diff --git a/os/src/test/audio_out/main.cc b/os/src/test/audio_out/main.cc
index 090081825..c1cf639e1 100644
--- a/os/src/test/audio_out/main.cc
+++ b/os/src/test/audio_out/main.cc
@@ -15,7 +15,7 @@
* under the terms of the GNU General Public License version 2.
*/
-#include
+#include
#include
#include
#include