2015-10-19 14:04:11 +02:00
|
|
|
/*
|
|
|
|
* \brief Main window of the mixer frontend
|
|
|
|
* \author Josef Soentgen
|
|
|
|
* \date 2015-10-15
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
2015-10-19 14:04:11 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2015-10-19 14:04:11 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2015-10-19 14:04:11 +02:00
|
|
|
#include <mixer/channel.h>
|
2017-01-30 11:35:12 +01:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
2015-10-19 14:04:11 +02:00
|
|
|
#include <os/reporter.h>
|
|
|
|
#include <rom_session/connection.h>
|
|
|
|
|
|
|
|
/* Qt includes */
|
|
|
|
#include <QCheckBox>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QFrame>
|
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QSlider>
|
|
|
|
#include <QWidget>
|
|
|
|
|
|
|
|
/* application includes */
|
|
|
|
#include "main_window.h"
|
|
|
|
|
|
|
|
|
|
|
|
/************
|
|
|
|
** helper **
|
|
|
|
************/
|
|
|
|
|
|
|
|
typedef Mixer::Channel Channel;
|
|
|
|
|
|
|
|
static struct Names {
|
|
|
|
char const *name;
|
|
|
|
Channel::Number number;
|
|
|
|
} names[] = {
|
|
|
|
{ "left", Channel::Number::LEFT },
|
|
|
|
{ "front left", Channel::Number::LEFT },
|
|
|
|
{ "right", Channel::Number::RIGHT },
|
|
|
|
{ "front right", Channel::Number::RIGHT },
|
|
|
|
{ nullptr, Channel::Number::MAX_CHANNELS }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static char const *channel_string_from_number(Channel::Number ch)
|
|
|
|
{
|
|
|
|
for (Names *n = names; n->name; ++n)
|
|
|
|
if (ch == n->number)
|
|
|
|
return n->name;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* keep sorted! */
|
|
|
|
static struct Types {
|
|
|
|
char const *name;
|
|
|
|
Channel::Type type;
|
|
|
|
} types[] = {
|
|
|
|
{ "invalid", Channel::Type::TYPE_INVALID },
|
|
|
|
{ "input", Channel::Type::INPUT },
|
|
|
|
{ "output", Channel::Type::OUTPUT }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static char const *type_to_string(Channel::Type t) { return types[t].name; }
|
|
|
|
|
|
|
|
|
|
|
|
class Channel_widget : public Compound_widget<QFrame, QVBoxLayout>,
|
|
|
|
public Genode::List<Channel_widget>::Element
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Channel::Number _number;
|
|
|
|
Channel::Type _type;
|
|
|
|
|
|
|
|
QCheckBox _muted_checkbox;
|
|
|
|
QSlider _slider { Qt::Vertical };
|
|
|
|
QHBoxLayout _slider_hbox;
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
|
|
|
void channel_changed();
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Channel_widget(Channel::Type type, Channel::Number number)
|
|
|
|
:
|
|
|
|
_number(number), _type(type),
|
|
|
|
_muted_checkbox("mute")
|
|
|
|
{
|
|
|
|
_slider.setMinimum(Channel::Volume_level::MIN);
|
|
|
|
_slider.setMaximum(Channel::Volume_level::MAX);
|
|
|
|
|
|
|
|
_slider_hbox.addStretch();
|
|
|
|
_slider_hbox.addWidget(&_slider, Qt::AlignCenter);
|
|
|
|
_slider_hbox.addStretch();
|
|
|
|
|
|
|
|
_layout->addLayout(&_slider_hbox);
|
|
|
|
_layout->addWidget(&_muted_checkbox);
|
|
|
|
|
|
|
|
connect(&_slider, SIGNAL(sliderReleased()),
|
|
|
|
this, SIGNAL(channel_changed()));
|
2015-11-24 16:30:54 +01:00
|
|
|
connect(&_muted_checkbox, SIGNAL(clicked(bool)),
|
2015-10-19 14:04:11 +02:00
|
|
|
this, SIGNAL(channel_changed()));
|
|
|
|
}
|
|
|
|
|
|
|
|
Channel::Number number() const { return _number; }
|
|
|
|
Channel::Type type() const { return _type; }
|
|
|
|
int volume() const { return _slider.value(); }
|
|
|
|
void volume(int v) { _slider.setValue(v); }
|
|
|
|
bool muted() const { return _muted_checkbox.checkState() == Qt::Checked; }
|
|
|
|
void muted(bool v) { _muted_checkbox.setChecked(v); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Client_widget : public Compound_widget<QFrame, QVBoxLayout>,
|
|
|
|
public Genode::List<Client_widget>::Element
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
bool valid { true };
|
|
|
|
|
|
|
|
void _sorted_insert(Channel_widget *cw)
|
|
|
|
{
|
|
|
|
Channel::Number const nr = cw->number();
|
|
|
|
|
|
|
|
Channel_widget const *last = nullptr;
|
|
|
|
Channel_widget const *w = _list.first();
|
|
|
|
for (; w; w = w->next()) {
|
|
|
|
if (w->number() > nr)
|
|
|
|
break;
|
|
|
|
last = w;
|
|
|
|
}
|
|
|
|
_list.insert(cw, last);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Genode::List<Channel_widget> _list;
|
|
|
|
Genode::Allocator &_alloc;
|
|
|
|
Channel::Label _label;
|
|
|
|
|
|
|
|
QLabel _name;
|
|
|
|
QHBoxLayout _hlayout;
|
|
|
|
|
|
|
|
static char const *_strip_label(Channel::Label const &label)
|
|
|
|
{
|
|
|
|
char const * str = label.string();
|
|
|
|
int pos = 0;
|
|
|
|
for (int i = 0; str[i]; i++)
|
|
|
|
if (str[i] == '>') pos = i+1;
|
|
|
|
|
|
|
|
return str+pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
|
|
|
void client_changed();
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Client_widget(Genode::Allocator &alloc, Channel::Label const &label)
|
|
|
|
:
|
|
|
|
_alloc(alloc), _label(label),
|
|
|
|
_name(_strip_label(_label))
|
|
|
|
{
|
|
|
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
|
|
|
setLineWidth(4);
|
|
|
|
setToolTip(_label.string());
|
|
|
|
|
|
|
|
_name.setAlignment(Qt::AlignCenter);
|
|
|
|
_name.setContentsMargins(0, 0, 0, 5);
|
|
|
|
|
|
|
|
_layout->addWidget(&_name);
|
|
|
|
_layout->addLayout(&_hlayout);
|
|
|
|
_layout->setContentsMargins(10, 10, 10, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
~Client_widget()
|
|
|
|
{
|
|
|
|
while (Channel_widget *ch = _list.first()) {
|
|
|
|
disconnect(ch, SIGNAL(channel_changed()));
|
|
|
|
_hlayout.removeWidget(ch);
|
|
|
|
_list.remove(ch);
|
|
|
|
Genode::destroy(&_alloc, ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Channel::Label const &label() const { return _label; }
|
|
|
|
|
|
|
|
Channel_widget* lookup_channel(Channel::Number const number)
|
|
|
|
{
|
|
|
|
for (Channel_widget *ch = _list.first(); ch; ch = ch->next())
|
|
|
|
if (number == ch->number())
|
|
|
|
return ch;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Channel_widget* add_channel(Channel::Type const type,
|
|
|
|
Channel::Number const number)
|
|
|
|
{
|
|
|
|
Channel_widget *ch = new (&_alloc) Channel_widget(type, number);
|
|
|
|
connect(ch, SIGNAL(channel_changed()),
|
|
|
|
this, SIGNAL(client_changed()));
|
|
|
|
|
|
|
|
_sorted_insert(ch);
|
|
|
|
_hlayout.addWidget(ch);
|
|
|
|
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
Channel_widget const* first_channel() const { return _list.first(); }
|
|
|
|
|
|
|
|
void only_show_first()
|
|
|
|
{
|
|
|
|
Channel_widget *cw = _list.first();
|
|
|
|
while ((cw = cw->next())) cw->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool combined_control() const
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Having a seperate volume control widget for each channel is
|
|
|
|
* nice-to-have but for now it is unnecessary. We therefore disable
|
|
|
|
* it the hardcoded way.
|
|
|
|
*/
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Client_widget_registry : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Genode::List<Client_widget> _list;
|
|
|
|
Genode::Allocator &_alloc;
|
|
|
|
|
|
|
|
void _remove_destroy(Client_widget *c)
|
|
|
|
{
|
|
|
|
disconnect(c, SIGNAL(client_changed()));
|
|
|
|
_list.remove(c);
|
|
|
|
Genode::destroy(&_alloc, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
|
|
|
|
void registry_changed();
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Client_widget_registry(Genode::Allocator &alloc) : QObject(), _alloc(alloc) { }
|
|
|
|
|
|
|
|
Client_widget* first() { return _list.first(); }
|
|
|
|
|
|
|
|
Client_widget* lookup(Channel::Label const &label)
|
|
|
|
{
|
|
|
|
for (Client_widget *c = _list.first(); c; c = c->next()) {
|
|
|
|
if (label == c->label())
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Client_widget* alloc_insert(Channel::Label const &label)
|
|
|
|
{
|
|
|
|
Client_widget *c = lookup(label);
|
|
|
|
if (c == nullptr) {
|
|
|
|
c = new (&_alloc) Client_widget(_alloc, label);
|
|
|
|
connect(c, SIGNAL(client_changed()),
|
|
|
|
this, SIGNAL(registry_changed()));
|
|
|
|
_list.insert(c);
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_all()
|
|
|
|
{
|
|
|
|
for (Client_widget *c = _list.first(); c; c = c->next())
|
|
|
|
c->valid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove_invalid()
|
|
|
|
{
|
|
|
|
for (Client_widget *c = _list.first(); c; c = c->next())
|
|
|
|
if (c->valid == false) _remove_destroy(c);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Client_widget_registry *client_registry()
|
|
|
|
{
|
|
|
|
static Client_widget_registry inst(*Genode::env()->heap());
|
|
|
|
return &inst;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-24 16:30:54 +01:00
|
|
|
static char const * const config_file = "/config/mixer.config";
|
|
|
|
|
|
|
|
|
|
|
|
static int write_config(char const *file, char const *data, size_t length)
|
|
|
|
{
|
|
|
|
if (length == 0) return 0;
|
|
|
|
|
|
|
|
QFile mixer_file(file);
|
|
|
|
if (!mixer_file.open(QIODevice::WriteOnly)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("could not open '", file, "'");
|
2015-11-24 16:30:54 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
mixer_file.write(data, length);
|
|
|
|
mixer_file.close();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-10-19 14:04:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
void Main_window::_update_config()
|
|
|
|
{
|
2015-11-24 16:30:54 +01:00
|
|
|
char xml_data[2048];
|
|
|
|
size_t xml_used = 0;
|
2015-10-19 14:04:11 +02:00
|
|
|
|
|
|
|
try {
|
2015-11-24 16:30:54 +01:00
|
|
|
Genode::Xml_generator xml(xml_data, sizeof(xml_data), "config", [&] {
|
|
|
|
|
|
|
|
xml.node("default", [&] {
|
|
|
|
xml.attribute("out_volume", _default_out_volume);
|
|
|
|
xml.attribute("volume", _default_volume);
|
|
|
|
xml.attribute("muted", _default_muted);
|
|
|
|
});
|
2015-10-19 14:04:11 +02:00
|
|
|
|
|
|
|
xml.node("channel_list", [&] {
|
|
|
|
for (Client_widget const *c = client_registry()->first(); c; c = c->next()) {
|
|
|
|
bool const combined = c->combined_control();
|
|
|
|
|
|
|
|
static int vol = 0;
|
|
|
|
static bool muted = true;
|
|
|
|
if (combined) {
|
|
|
|
Channel_widget const *w = c->first_channel();
|
|
|
|
vol = w->volume();
|
|
|
|
muted = w->muted();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Channel_widget const *w = c->first_channel(); w; w = w->next()) {
|
|
|
|
Channel::Number const nr = w->number();
|
|
|
|
xml.node("channel", [&] {
|
|
|
|
xml.attribute("type", type_to_string(w->type()));
|
|
|
|
xml.attribute("label", c->label().string());
|
|
|
|
xml.attribute("name", channel_string_from_number(nr));
|
|
|
|
xml.attribute("number", nr);
|
|
|
|
xml.attribute("volume", combined ? vol : w->volume());
|
|
|
|
xml.attribute("muted", combined ? muted : w->muted());
|
|
|
|
});
|
2015-11-24 16:30:54 +01:00
|
|
|
|
|
|
|
if (_verbose)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::log("label: '", c->label(), "' "
|
|
|
|
"volume: ", combined ? vol : w->volume(), " "
|
|
|
|
"muted: ", combined ? muted : w->muted());
|
2015-10-19 14:04:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2015-11-24 16:30:54 +01:00
|
|
|
xml_used = xml.used();
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
} catch (...) { Genode::warning("could generate 'mixer.config'"); }
|
2015-11-24 16:30:54 +01:00
|
|
|
|
|
|
|
write_config(config_file, xml_data, xml_used);
|
2015-10-19 14:04:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Main_window::_update_clients(Genode::Xml_node &channels)
|
|
|
|
{
|
|
|
|
for (Client_widget *c = client_registry()->first(); c; c = c->next())
|
|
|
|
_layout->removeWidget(c);
|
|
|
|
|
|
|
|
client_registry()->invalidate_all();
|
|
|
|
|
|
|
|
channels.for_each_sub_node("channel", [&] (Genode::Xml_node const &node) {
|
|
|
|
try {
|
|
|
|
Channel ch(node);
|
|
|
|
|
|
|
|
Client_widget *c = client_registry()->lookup(ch.label);
|
|
|
|
if (c == nullptr)
|
|
|
|
c = client_registry()->alloc_insert(ch.label);
|
|
|
|
|
|
|
|
Channel_widget *w = c->lookup_channel(ch.number);
|
|
|
|
if (w == nullptr)
|
|
|
|
w = c->add_channel(ch.type, ch.number);
|
|
|
|
|
|
|
|
w->volume(ch.volume);
|
|
|
|
w->muted(ch.muted);
|
|
|
|
|
|
|
|
if (c->combined_control()) c->only_show_first();
|
|
|
|
else w->show();
|
|
|
|
|
|
|
|
c->valid = true;
|
|
|
|
|
|
|
|
_layout->addWidget(c);
|
|
|
|
resize(sizeHint());
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
} catch (Channel::Invalid_channel) { Genode::warning("invalid channel node"); }
|
2015-10-19 14:04:11 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
client_registry()->remove_invalid();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets called from the Genode to Qt proxy object when the report was
|
|
|
|
* updated with a pointer to the XML document.
|
|
|
|
*/
|
|
|
|
void Main_window::report_changed(void *l, void const *p)
|
|
|
|
{
|
|
|
|
Genode::Lock &lock = *reinterpret_cast<Genode::Lock*>(l);
|
|
|
|
Genode::Xml_node &node = *((Genode::Xml_node*)p);
|
|
|
|
|
|
|
|
if (node.has_type("channel_list"))
|
|
|
|
_update_clients(node);
|
|
|
|
|
|
|
|
lock.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-29 14:52:24 +02:00
|
|
|
Main_window::Main_window(Libc::Env &env)
|
2015-11-24 16:30:54 +01:00
|
|
|
:
|
|
|
|
_default_out_volume(0),
|
|
|
|
_default_volume(0),
|
|
|
|
_default_muted(true)
|
2015-10-19 14:04:11 +02:00
|
|
|
{
|
|
|
|
connect(client_registry(), SIGNAL(registry_changed()),
|
|
|
|
this, SLOT(_update_config()));
|
2015-11-24 16:30:54 +01:00
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
2017-05-29 14:52:24 +02:00
|
|
|
Attached_rom_dataspace config(env, "config");
|
2015-11-24 16:30:54 +01:00
|
|
|
try {
|
2017-05-29 14:52:24 +02:00
|
|
|
Xml_node config_node = config.xml();
|
2015-11-24 16:30:54 +01:00
|
|
|
_verbose = config_node.attribute("verbose").has_value("yes");
|
|
|
|
} catch (...) { _verbose = false; }
|
|
|
|
|
|
|
|
try {
|
2017-05-29 14:52:24 +02:00
|
|
|
Xml_node node = config.xml().sub_node("default");
|
2015-11-24 16:30:54 +01:00
|
|
|
_default_out_volume = node.attribute_value<long>("out_volume", 0);
|
|
|
|
_default_volume = node.attribute_value<long>("volume", 0);
|
|
|
|
_default_muted = node.attribute_value<long>("muted", 1);
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
} catch (...) { Genode::warning("no <default> node found, fallback is 'muted=1'"); }
|
2015-10-19 14:04:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Main_window::~Main_window()
|
|
|
|
{
|
|
|
|
disconnect(client_registry(), SIGNAL(registry_changed()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "main_window.moc"
|