linux/audio: transition to the new base API

Issue #1987
This commit is contained in:
Josef Söntgen 2016-05-29 10:08:33 +02:00 committed by Christian Helmuth
parent 0d8d8de42c
commit d9f33f7577
2 changed files with 50 additions and 48 deletions

View File

@ -16,23 +16,21 @@
*/ */
/* Genode includes */ /* Genode includes */
#include <base/env.h> #include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/log.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <root/component.h> #include <root/component.h>
#include <cap_session/connection.h>
#include <audio_out_session/rpc_object.h> #include <audio_out_session/rpc_object.h>
#include <util/misc_math.h> #include <util/misc_math.h>
#include <os/config.h>
#include <os/server.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
/* local includes */ /* local includes */
#include "alsa.h" #include <alsa.h>
using namespace Genode; using namespace Genode;
static const bool verbose = false;
enum Channel_number { LEFT, RIGHT, MAX_CHANNELS, INVALID = MAX_CHANNELS }; enum Channel_number { LEFT, RIGHT, MAX_CHANNELS, INVALID = MAX_CHANNELS };
@ -42,6 +40,8 @@ namespace Audio_out
class Out; class Out;
class Root; class Root;
struct Root_policy; struct Root_policy;
struct Main;
static Session_component *channel_acquired[MAX_CHANNELS]; static Session_component *channel_acquired[MAX_CHANNELS];
}; };
@ -50,7 +50,7 @@ class Audio_out::Session_component : public Audio_out::Session_rpc_object
{ {
private: private:
Channel_number _channel; Channel_number _channel;
public: public:
@ -98,11 +98,11 @@ class Audio_out::Out
{ {
private: private:
Server::Entrypoint &_ep; Genode::Env &_env;
Genode::Signal_rpc_member<Audio_out::Out> _data_avail_dispatcher; Genode::Signal_handler<Audio_out::Out> _data_avail_dispatcher;
Genode::Signal_rpc_member<Audio_out::Out> _timer_dispatcher; Genode::Signal_handler<Audio_out::Out> _timer_dispatcher;
Timer::Connection _timer; Timer::Connection _timer { _env };
bool _active() { bool _active() {
return channel_acquired[LEFT] && channel_acquired[RIGHT] && return channel_acquired[LEFT] && channel_acquired[RIGHT] &&
@ -154,15 +154,12 @@ class Audio_out::Out
p_left->invalidate(); p_left->invalidate();
p_right->invalidate(); p_right->invalidate();
if (verbose)
PDBG("play packet");
/* blocking-write packet to ALSA */ /* blocking-write packet to ALSA */
while (int err = audio_drv_play(data, PERIOD)) { while (audio_drv_play(data, PERIOD)) {
if (verbose) PERR("Error %d during playback", err); /* try to restart the driver silently */
audio_drv_stop(); audio_drv_stop();
audio_drv_start(); audio_drv_start();
} }
p_left->mark_as_played(); p_left->mark_as_played();
p_right->mark_as_played(); p_right->mark_as_played();
@ -173,20 +170,20 @@ class Audio_out::Out
return true; return true;
} }
void _handle_data_avail(unsigned num) { } void _handle_data_avail() { }
void _handle_timer(unsigned) void _handle_timer()
{ {
if (_active()) _play_packet(); if (_active()) _play_packet();
} }
public: public:
Out(Server::Entrypoint &ep) Out(Genode::Env &env)
: :
_ep(ep), _env(env),
_data_avail_dispatcher(ep, *this, &Audio_out::Out::_handle_data_avail), _data_avail_dispatcher(env.ep(), *this, &Audio_out::Out::_handle_data_avail),
_timer_dispatcher(ep, *this, &Audio_out::Out::_handle_timer) _timer_dispatcher(env.ep(), *this, &Audio_out::Out::_handle_timer)
{ {
_timer.sigh(_timer_dispatcher); _timer.sigh(_timer_dispatcher);
@ -212,8 +209,8 @@ struct Audio_out::Root_policy
if ((ram_quota < session_size) || if ((ram_quota < session_size) ||
(sizeof(Stream) > ram_quota - session_size)) { (sizeof(Stream) > ram_quota - session_size)) {
PERR("insufficient 'ram_quota', got %zd, need %zd", Genode::error("insufficient 'ram_quota', got ", ram_quota,
ram_quota, sizeof(Stream) + session_size); " need ", sizeof(Stream) + session_size);
throw ::Root::Quota_exceeded(); throw ::Root::Quota_exceeded();
} }
@ -260,50 +257,54 @@ class Audio_out::Root : public Audio_out::Root_component
public: public:
Root(Server::Entrypoint &ep, Allocator *md_alloc, Root(Genode::Entrypoint &ep, Allocator *md_alloc,
Signal_context_capability data_cap) Signal_context_capability data_cap)
: Root_component(&ep.rpc_ep(), md_alloc), _data_cap(data_cap) : Root_component(&ep.rpc_ep(), md_alloc), _data_cap(data_cap)
{ } { }
}; };
struct Main struct Audio_out::Main
{ {
Server::Entrypoint &ep; Genode::Env &env;
Genode::Heap heap { env.ram(), env.rm() };
Main(Server::Entrypoint &ep) : ep(ep) Genode::Attached_rom_dataspace config { env, "config" };
Main(Genode::Env &env) : env(env)
{ {
char dev[32] = { 'h', 'w', 0 }; char dev[32] = { 'h', 'w', 0 };
try { try {
Genode::Xml_node config = Genode::config()->xml_node(); config.xml().attribute("alsa_device").value(dev, sizeof(dev));
config.attribute("alsa_device").value(dev, sizeof(dev));
} catch (...) { } } catch (...) { }
/* init ALSA */ /* init ALSA */
int err = audio_drv_init(dev); int err = audio_drv_init(dev);
if (err) { if (err) {
if (err == -1) PERR("Could not open ALSA device '%s'.", dev); if (err == -1) {
else PERR("Could not initialize driver, error: %d", err); Genode::error("could not open ALSA device ", dev);
} else {
Genode::error("could not initialize driver error ", err);
}
throw -1; throw -1;
} }
audio_drv_start(); audio_drv_start();
static Audio_out::Out out(ep); static Audio_out::Out out(env);
static Audio_out::Root root(ep, Genode::env()->heap(), static Audio_out::Root root(env.ep(), &heap,
out.data_avail_sigh()); out.data_avail_sigh());
env()->parent()->announce(ep.manage(root)); env.parent().announce(env.ep().manage(root));
PINF("--- start Audio_out ALSA driver ---"); Genode::log("--- start Audio_out ALSA driver ---");
} }
}; };
/************ /***************
** Server ** ** Component **
************/ ***************/
namespace Server { namespace Component {
char const *name() { return "audio_drv_ep"; } Genode::size_t stack_size() { return 2*1024*sizeof(addr_t); }
size_t stack_size() { return 2*1024*sizeof(addr_t); } void construct(Genode::Env &env) { static Audio_out::Main main(env); }
void construct(Entrypoint &ep) { static Main main(ep); }
} }

View File

@ -1,6 +1,7 @@
REQUIRES = linux REQUIRES = linux
TARGET = audio_drv TARGET = audio_drv
LIBS = lx_hybrid config server LIBS = lx_hybrid
SRC_CC = main.cc SRC_CC = main.cc
SRC_C = alsa.c SRC_C = alsa.c
INC_DIR += $(PRG_DIR)
LX_LIBS = alsa LX_LIBS = alsa