config/Param: split block-specific attributes to new struct ConfigBlock
The old struct config_param remains only for top-level string options.
This commit is contained in:
parent
84e74173de
commit
4fa5538e2b
@ -20,8 +20,12 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Block.hxx"
|
#include "Block.hxx"
|
||||||
#include "ConfigParser.hxx"
|
#include "ConfigParser.hxx"
|
||||||
|
#include "ConfigPath.hxx"
|
||||||
#include "system/FatalError.hxx"
|
#include "system/FatalError.hxx"
|
||||||
|
#include "fs/AllocatedPath.hxx"
|
||||||
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -57,3 +61,96 @@ BlockParam::GetBoolValue() const
|
|||||||
|
|
||||||
return value2;
|
return value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigBlock::~ConfigBlock()
|
||||||
|
{
|
||||||
|
delete next;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BlockParam *
|
||||||
|
ConfigBlock::GetBlockParam(const char *name) const
|
||||||
|
{
|
||||||
|
for (const auto &i : block_params) {
|
||||||
|
if (i.name == name) {
|
||||||
|
i.used = true;
|
||||||
|
return &i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
ConfigBlock::GetBlockValue(const char *name, const char *default_value) const
|
||||||
|
{
|
||||||
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
|
if (bp == nullptr)
|
||||||
|
return default_value;
|
||||||
|
|
||||||
|
return bp->value.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocatedPath
|
||||||
|
ConfigBlock::GetBlockPath(const char *name, const char *default_value,
|
||||||
|
Error &error) const
|
||||||
|
{
|
||||||
|
assert(!error.IsDefined());
|
||||||
|
|
||||||
|
int line2 = line;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
|
if (bp != nullptr) {
|
||||||
|
line2 = bp->line;
|
||||||
|
s = bp->value.c_str();
|
||||||
|
} else {
|
||||||
|
if (default_value == nullptr)
|
||||||
|
return AllocatedPath::Null();
|
||||||
|
|
||||||
|
s = default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocatedPath path = ParsePath(s, error);
|
||||||
|
if (gcc_unlikely(path.IsNull()))
|
||||||
|
error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
|
||||||
|
name, line2);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocatedPath
|
||||||
|
ConfigBlock::GetBlockPath(const char *name, Error &error) const
|
||||||
|
{
|
||||||
|
return GetBlockPath(name, nullptr, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ConfigBlock::GetBlockValue(const char *name, int default_value) const
|
||||||
|
{
|
||||||
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
|
if (bp == nullptr)
|
||||||
|
return default_value;
|
||||||
|
|
||||||
|
return bp->GetIntValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const
|
||||||
|
{
|
||||||
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
|
if (bp == nullptr)
|
||||||
|
return default_value;
|
||||||
|
|
||||||
|
return bp->GetUnsignedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
bool
|
||||||
|
ConfigBlock::GetBlockValue(const char *name, bool default_value) const
|
||||||
|
{
|
||||||
|
const BlockParam *bp = GetBlockParam(name);
|
||||||
|
if (bp == nullptr)
|
||||||
|
return default_value;
|
||||||
|
|
||||||
|
return bp->GetBoolValue();
|
||||||
|
}
|
||||||
|
@ -21,9 +21,14 @@
|
|||||||
#define MPD_CONFIG_BLOCK_HXX
|
#define MPD_CONFIG_BLOCK_HXX
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "Param.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Error;
|
||||||
|
class AllocatedPath;
|
||||||
|
|
||||||
struct BlockParam {
|
struct BlockParam {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -50,4 +55,71 @@ struct BlockParam {
|
|||||||
bool GetBoolValue() const;
|
bool GetBoolValue() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ConfigBlock {
|
||||||
|
/**
|
||||||
|
* The next #ConfigBlock with the same name. The destructor
|
||||||
|
* deletes the whole chain.
|
||||||
|
*/
|
||||||
|
ConfigBlock *next;
|
||||||
|
|
||||||
|
int line;
|
||||||
|
|
||||||
|
std::vector<BlockParam> block_params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flag is false when nobody has queried the value of
|
||||||
|
* this option yet.
|
||||||
|
*/
|
||||||
|
bool used;
|
||||||
|
|
||||||
|
explicit ConfigBlock(int _line=-1)
|
||||||
|
:next(nullptr), line(_line), used(false) {}
|
||||||
|
|
||||||
|
ConfigBlock(const ConfigBlock &) = delete;
|
||||||
|
|
||||||
|
~ConfigBlock();
|
||||||
|
|
||||||
|
ConfigBlock &operator=(const ConfigBlock &) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if this is a "null" instance, i.e. an empty
|
||||||
|
* object that was synthesized and not loaded from a
|
||||||
|
* configuration file.
|
||||||
|
*/
|
||||||
|
bool IsNull() const {
|
||||||
|
return line < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_nonnull_all
|
||||||
|
void AddBlockParam(const char *_name, const char *_value,
|
||||||
|
int _line=-1) {
|
||||||
|
block_params.emplace_back(_name, _value, _line);
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_nonnull_all gcc_pure
|
||||||
|
const BlockParam *GetBlockParam(const char *_name) const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
const char *GetBlockValue(const char *name,
|
||||||
|
const char *default_value=nullptr) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as config_get_path(), but looks up the setting in the
|
||||||
|
* specified block.
|
||||||
|
*/
|
||||||
|
AllocatedPath GetBlockPath(const char *name, const char *default_value,
|
||||||
|
Error &error) const;
|
||||||
|
|
||||||
|
AllocatedPath GetBlockPath(const char *name, Error &error) const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
int GetBlockValue(const char *name, int default_value) const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
unsigned GetBlockValue(const char *name, unsigned default_value) const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
bool GetBlockValue(const char *name, bool default_value) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "ConfigFile.hxx"
|
#include "ConfigFile.hxx"
|
||||||
#include "Data.hxx"
|
#include "Data.hxx"
|
||||||
#include "Param.hxx"
|
#include "Param.hxx"
|
||||||
|
#include "Block.hxx"
|
||||||
#include "ConfigTemplates.hxx"
|
#include "ConfigTemplates.hxx"
|
||||||
#include "util/Tokenizer.hxx"
|
#include "util/Tokenizer.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
@ -38,7 +39,7 @@ static constexpr char CONF_COMMENT = '#';
|
|||||||
static constexpr Domain config_file_domain("config_file");
|
static constexpr Domain config_file_domain("config_file");
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
config_read_name_value(struct config_param *param, char *input, unsigned line,
|
config_read_name_value(ConfigBlock &block, char *input, unsigned line,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
Tokenizer tokenizer(input);
|
Tokenizer tokenizer(input);
|
||||||
@ -65,7 +66,7 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockParam *bp = param->GetBlockParam(name);
|
const BlockParam *bp = block.GetBlockParam(name);
|
||||||
if (bp != nullptr) {
|
if (bp != nullptr) {
|
||||||
error.Format(config_file_domain,
|
error.Format(config_file_domain,
|
||||||
"\"%s\" is duplicate, first defined on line %i",
|
"\"%s\" is duplicate, first defined on line %i",
|
||||||
@ -73,14 +74,14 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
param->AddBlockParam(name, value, line);
|
block.AddBlockParam(name, value, line);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct config_param *
|
static ConfigBlock *
|
||||||
config_read_block(BufferedReader &reader, Error &error)
|
config_read_block(BufferedReader &reader, Error &error)
|
||||||
{
|
{
|
||||||
struct config_param *ret = new config_param(reader.GetLineNumber());
|
auto *ret = new ConfigBlock(reader.GetLineNumber());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char *line = reader.ReadLine();
|
char *line = reader.ReadLine();
|
||||||
@ -115,7 +116,7 @@ config_read_block(BufferedReader &reader, Error &error)
|
|||||||
|
|
||||||
/* parse name and value */
|
/* parse name and value */
|
||||||
|
|
||||||
if (!config_read_name_value(ret, line, reader.GetLineNumber(),
|
if (!config_read_name_value(*ret, line, reader.GetLineNumber(),
|
||||||
error)) {
|
error)) {
|
||||||
assert(*line != 0);
|
assert(*line != 0);
|
||||||
delete ret;
|
delete ret;
|
||||||
@ -125,6 +126,64 @@ config_read_block(BufferedReader &reader, Error &error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcc_nonnull_all
|
||||||
|
static void
|
||||||
|
Append(ConfigBlock *&head, ConfigBlock *p)
|
||||||
|
{
|
||||||
|
assert(p->next == nullptr);
|
||||||
|
|
||||||
|
auto **i = &head;
|
||||||
|
while (*i != nullptr)
|
||||||
|
i = &(*i)->next;
|
||||||
|
|
||||||
|
*i = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ReadConfigBlock(ConfigData &config_data, BufferedReader &reader,
|
||||||
|
const char *name, ConfigOption o,
|
||||||
|
Tokenizer &tokenizer,
|
||||||
|
Error &error)
|
||||||
|
{
|
||||||
|
const unsigned i = unsigned(o);
|
||||||
|
const ConfigTemplate &option = config_block_templates[i];
|
||||||
|
ConfigBlock *&head = config_data.blocks[i];
|
||||||
|
|
||||||
|
if (head != nullptr && !option.repeatable) {
|
||||||
|
ConfigBlock *block = head;
|
||||||
|
error.Format(config_file_domain,
|
||||||
|
"config parameter \"%s\" is first defined "
|
||||||
|
"on line %d and redefined on line %u\n",
|
||||||
|
name, block->line,
|
||||||
|
reader.GetLineNumber());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now parse the block or the value */
|
||||||
|
|
||||||
|
if (tokenizer.CurrentChar() != '{') {
|
||||||
|
error.Format(config_file_domain,
|
||||||
|
"line %u: '{' expected",
|
||||||
|
reader.GetLineNumber());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *line = StripLeft(tokenizer.Rest() + 1);
|
||||||
|
if (*line != 0 && *line != CONF_COMMENT) {
|
||||||
|
error.Format(config_file_domain,
|
||||||
|
"line %u: Unknown tokens after '{'",
|
||||||
|
reader.GetLineNumber());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *param = config_read_block(reader, error);
|
||||||
|
if (param == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Append(head, param);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
gcc_nonnull_all
|
gcc_nonnull_all
|
||||||
static void
|
static void
|
||||||
Append(config_param *&head, config_param *p)
|
Append(config_param *&head, config_param *p)
|
||||||
@ -145,7 +204,7 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
|
|||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
const unsigned i = unsigned(o);
|
const unsigned i = unsigned(o);
|
||||||
const ConfigTemplate &option = config_templates[i];
|
const ConfigTemplate &option = config_param_templates[i];
|
||||||
config_param *&head = config_data.params[i];
|
config_param *&head = config_data.params[i];
|
||||||
|
|
||||||
if (head != nullptr && !option.repeatable) {
|
if (head != nullptr && !option.repeatable) {
|
||||||
@ -160,57 +219,28 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
|
|||||||
|
|
||||||
/* now parse the block or the value */
|
/* now parse the block or the value */
|
||||||
|
|
||||||
struct config_param *param;
|
const char *value = tokenizer.NextString(error);
|
||||||
if (option.block) {
|
if (value == nullptr) {
|
||||||
/* it's a block, call config_read_block() */
|
if (tokenizer.IsEnd())
|
||||||
|
|
||||||
if (tokenizer.CurrentChar() != '{') {
|
|
||||||
error.Format(config_file_domain,
|
error.Format(config_file_domain,
|
||||||
"line %u: '{' expected",
|
"line %u: Value missing",
|
||||||
reader.GetLineNumber());
|
reader.GetLineNumber());
|
||||||
return false;
|
else
|
||||||
}
|
error.FormatPrefix("line %u: ",
|
||||||
|
reader.GetLineNumber());
|
||||||
|
|
||||||
char *line = StripLeft(tokenizer.Rest() + 1);
|
return false;
|
||||||
if (*line != 0 && *line != CONF_COMMENT) {
|
|
||||||
error.Format(config_file_domain,
|
|
||||||
"line %u: Unknown tokens after '{'",
|
|
||||||
reader.GetLineNumber());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
param = config_read_block(reader, error);
|
|
||||||
if (param == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* a string value */
|
|
||||||
|
|
||||||
const char *value = tokenizer.NextString(error);
|
|
||||||
if (value == nullptr) {
|
|
||||||
if (tokenizer.IsEnd())
|
|
||||||
error.Format(config_file_domain,
|
|
||||||
"line %u: Value missing",
|
|
||||||
reader.GetLineNumber());
|
|
||||||
else
|
|
||||||
error.FormatPrefix("line %u: ",
|
|
||||||
reader.GetLineNumber());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tokenizer.IsEnd() &&
|
|
||||||
tokenizer.CurrentChar() != CONF_COMMENT) {
|
|
||||||
error.Format(config_file_domain,
|
|
||||||
"line %u: Unknown tokens after value",
|
|
||||||
reader.GetLineNumber());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
param = new config_param(value,
|
|
||||||
reader.GetLineNumber());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tokenizer.IsEnd() &&
|
||||||
|
tokenizer.CurrentChar() != CONF_COMMENT) {
|
||||||
|
error.Format(config_file_domain,
|
||||||
|
"line %u: Unknown tokens after value",
|
||||||
|
reader.GetLineNumber());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *param = new config_param(value, reader.GetLineNumber());
|
||||||
Append(head, param);
|
Append(head, param);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -242,10 +272,15 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
|
|||||||
"repeatable" flag */
|
"repeatable" flag */
|
||||||
|
|
||||||
const ConfigOption o = ParseConfigOptionName(name);
|
const ConfigOption o = ParseConfigOptionName(name);
|
||||||
|
ConfigBlockOption bo;
|
||||||
if (o != ConfigOption::MAX) {
|
if (o != ConfigOption::MAX) {
|
||||||
if (!ReadConfigParam(config_data, reader, name, o,
|
if (!ReadConfigParam(config_data, reader, name, o,
|
||||||
tokenizer, error))
|
tokenizer, error))
|
||||||
return false;
|
return false;
|
||||||
|
} else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) {
|
||||||
|
if (!ReadConfigBlock(config_data, reader, name, o,
|
||||||
|
tokenizer, error))
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
error.Format(config_file_domain,
|
error.Format(config_file_domain,
|
||||||
"unrecognized parameter in config file at "
|
"unrecognized parameter in config file at "
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "ConfigParser.hxx"
|
#include "ConfigParser.hxx"
|
||||||
#include "Data.hxx"
|
#include "Data.hxx"
|
||||||
#include "Param.hxx"
|
#include "Param.hxx"
|
||||||
|
#include "Block.hxx"
|
||||||
#include "ConfigFile.hxx"
|
#include "ConfigFile.hxx"
|
||||||
#include "ConfigPath.hxx"
|
#include "ConfigPath.hxx"
|
||||||
#include "ConfigError.hxx"
|
#include "ConfigError.hxx"
|
||||||
@ -51,15 +52,15 @@ ReadConfigFile(Path path, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Check(const config_param *param)
|
Check(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
if (!param->used)
|
if (!block.used)
|
||||||
/* this whole config_param was not queried at all -
|
/* this whole block was not queried at all -
|
||||||
the feature might be disabled at compile time?
|
the feature might be disabled at compile time?
|
||||||
Silently ignore it here. */
|
Silently ignore it here. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const auto &i : param->block_params) {
|
for (const auto &i : block.block_params) {
|
||||||
if (!i.used)
|
if (!i.used)
|
||||||
FormatWarning(config_domain,
|
FormatWarning(config_domain,
|
||||||
"option '%s' on line %i was not recognized",
|
"option '%s' on line %i was not recognized",
|
||||||
@ -69,9 +70,9 @@ Check(const config_param *param)
|
|||||||
|
|
||||||
void config_global_check(void)
|
void config_global_check(void)
|
||||||
{
|
{
|
||||||
for (auto i : config_data.params)
|
for (auto i : config_data.blocks)
|
||||||
for (const config_param *p = i; p != nullptr; p = p->next)
|
for (const auto *p = i; p != nullptr; p = p->next)
|
||||||
Check(p);
|
Check(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
const config_param *
|
const config_param *
|
||||||
@ -83,18 +84,27 @@ config_get_param(ConfigOption option)
|
|||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config_param *
|
const ConfigBlock *
|
||||||
config_find_block(ConfigOption option, const char *key, const char *value)
|
config_get_block(ConfigBlockOption option)
|
||||||
{
|
{
|
||||||
for (const config_param *param = config_get_param(option);
|
ConfigBlock *block = config_data.blocks[unsigned(option)];
|
||||||
param != nullptr; param = param->next) {
|
if (block != nullptr)
|
||||||
const char *value2 = param->GetBlockValue(key);
|
block->used = true;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfigBlock *
|
||||||
|
config_find_block(ConfigBlockOption option, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
for (const auto *block = config_get_block(option);
|
||||||
|
block != nullptr; block = block->next) {
|
||||||
|
const char *value2 = block->GetBlockValue(key);
|
||||||
if (value2 == nullptr)
|
if (value2 == nullptr)
|
||||||
FormatFatalError("block without '%s' name in line %d",
|
FormatFatalError("block without '%s' name in line %d",
|
||||||
key, param->line);
|
key, block->line);
|
||||||
|
|
||||||
if (strcmp(value2, value) == 0)
|
if (strcmp(value2, value) == 0)
|
||||||
return param;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -27,6 +27,7 @@ class Error;
|
|||||||
class Path;
|
class Path;
|
||||||
class AllocatedPath;
|
class AllocatedPath;
|
||||||
struct config_param;
|
struct config_param;
|
||||||
|
struct ConfigBlock;
|
||||||
|
|
||||||
void config_global_init(void);
|
void config_global_init(void);
|
||||||
void config_global_finish(void);
|
void config_global_finish(void);
|
||||||
@ -44,6 +45,10 @@ gcc_pure
|
|||||||
const config_param *
|
const config_param *
|
||||||
config_get_param(enum ConfigOption option);
|
config_get_param(enum ConfigOption option);
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
const ConfigBlock *
|
||||||
|
config_get_block(enum ConfigBlockOption option);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a block with a matching attribute.
|
* Find a block with a matching attribute.
|
||||||
*
|
*
|
||||||
@ -52,8 +57,8 @@ config_get_param(enum ConfigOption option);
|
|||||||
* @param value the expected attribute value
|
* @param value the expected attribute value
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const config_param *
|
const ConfigBlock *
|
||||||
config_find_block(ConfigOption option, const char *key, const char *value);
|
config_find_block(ConfigBlockOption option, const char *key, const char *value);
|
||||||
|
|
||||||
/* Note on gcc_pure: Some of the functions declared pure are not
|
/* Note on gcc_pure: Some of the functions declared pure are not
|
||||||
really pure in strict sense. They have side effect such that they
|
really pure in strict sense. They have side effect such that they
|
||||||
|
@ -49,7 +49,6 @@ enum class ConfigOption {
|
|||||||
ZEROCONF_ENABLED,
|
ZEROCONF_ENABLED,
|
||||||
PASSWORD,
|
PASSWORD,
|
||||||
DEFAULT_PERMS,
|
DEFAULT_PERMS,
|
||||||
AUDIO_OUTPUT,
|
|
||||||
AUDIO_OUTPUT_FORMAT,
|
AUDIO_OUTPUT_FORMAT,
|
||||||
MIXER_TYPE,
|
MIXER_TYPE,
|
||||||
REPLAYGAIN,
|
REPLAYGAIN,
|
||||||
@ -73,15 +72,20 @@ enum class ConfigOption {
|
|||||||
ID3V1_ENCODING,
|
ID3V1_ENCODING,
|
||||||
METADATA_TO_USE,
|
METADATA_TO_USE,
|
||||||
SAVE_ABSOLUTE_PATHS,
|
SAVE_ABSOLUTE_PATHS,
|
||||||
DECODER,
|
|
||||||
INPUT,
|
|
||||||
GAPLESS_MP3_PLAYBACK,
|
GAPLESS_MP3_PLAYBACK,
|
||||||
PLAYLIST_PLUGIN,
|
|
||||||
AUTO_UPDATE,
|
AUTO_UPDATE,
|
||||||
AUTO_UPDATE_DEPTH,
|
AUTO_UPDATE_DEPTH,
|
||||||
DESPOTIFY_USER,
|
DESPOTIFY_USER,
|
||||||
DESPOTIFY_PASSWORD,
|
DESPOTIFY_PASSWORD,
|
||||||
DESPOTIFY_HIGH_BITRATE,
|
DESPOTIFY_HIGH_BITRATE,
|
||||||
|
MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ConfigBlockOption {
|
||||||
|
AUDIO_OUTPUT,
|
||||||
|
DECODER,
|
||||||
|
INPUT,
|
||||||
|
PLAYLIST_PLUGIN,
|
||||||
AUDIO_FILTER,
|
AUDIO_FILTER,
|
||||||
DATABASE,
|
DATABASE,
|
||||||
NEIGHBORS,
|
NEIGHBORS,
|
||||||
@ -99,4 +103,11 @@ gcc_pure
|
|||||||
enum ConfigOption
|
enum ConfigOption
|
||||||
ParseConfigOptionName(const char *name);
|
ParseConfigOptionName(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return #ConfigOption::MAX if not found
|
||||||
|
*/
|
||||||
|
gcc_pure
|
||||||
|
enum ConfigBlockOption
|
||||||
|
ParseConfigBlockOptionName(const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,76 +23,105 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
const ConfigTemplate config_templates[] = {
|
const ConfigTemplate config_param_templates[] = {
|
||||||
{ "music_directory", false, false },
|
{ "music_directory", false },
|
||||||
{ "playlist_directory", false, false },
|
{ "playlist_directory", false },
|
||||||
{ "follow_inside_symlinks", false, false },
|
{ "follow_inside_symlinks", false },
|
||||||
{ "follow_outside_symlinks", false, false },
|
{ "follow_outside_symlinks", false },
|
||||||
{ "db_file", false, false },
|
{ "db_file", false },
|
||||||
{ "sticker_file", false, false },
|
{ "sticker_file", false },
|
||||||
{ "log_file", false, false },
|
{ "log_file", false },
|
||||||
{ "pid_file", false, false },
|
{ "pid_file", false },
|
||||||
{ "state_file", false, false },
|
{ "state_file", false },
|
||||||
{ "state_file_interval", false, false },
|
{ "state_file_interval", false },
|
||||||
{ "restore_paused", false, false },
|
{ "restore_paused", false },
|
||||||
{ "user", false, false },
|
{ "user", false },
|
||||||
{ "group", false, false },
|
{ "group", false },
|
||||||
{ "bind_to_address", true, false },
|
{ "bind_to_address", true },
|
||||||
{ "port", false, false },
|
{ "port", false },
|
||||||
{ "log_level", false, false },
|
{ "log_level", false },
|
||||||
{ "zeroconf_name", false, false },
|
{ "zeroconf_name", false },
|
||||||
{ "zeroconf_enabled", false, false },
|
{ "zeroconf_enabled", false },
|
||||||
{ "password", true, false },
|
{ "password", true },
|
||||||
{ "default_permissions", false, false },
|
{ "default_permissions", false },
|
||||||
{ "audio_output", true, true },
|
{ "audio_output_format", false },
|
||||||
{ "audio_output_format", false, false },
|
{ "mixer_type", false },
|
||||||
{ "mixer_type", false, false },
|
{ "replaygain", false },
|
||||||
{ "replaygain", false, false },
|
{ "replaygain_preamp", false },
|
||||||
{ "replaygain_preamp", false, false },
|
{ "replaygain_missing_preamp", false },
|
||||||
{ "replaygain_missing_preamp", false, false },
|
{ "replaygain_limit", false },
|
||||||
{ "replaygain_limit", false, false },
|
{ "volume_normalization", false },
|
||||||
{ "volume_normalization", false, false },
|
{ "samplerate_converter", false },
|
||||||
{ "samplerate_converter", false, false },
|
{ "audio_buffer_size", false },
|
||||||
{ "audio_buffer_size", false, false },
|
{ "buffer_before_play", false },
|
||||||
{ "buffer_before_play", false, false },
|
{ "http_proxy_host", false },
|
||||||
{ "http_proxy_host", false, false },
|
{ "http_proxy_port", false },
|
||||||
{ "http_proxy_port", false, false },
|
{ "http_proxy_user", false },
|
||||||
{ "http_proxy_user", false, false },
|
{ "http_proxy_password", false },
|
||||||
{ "http_proxy_password", false, false },
|
{ "connection_timeout", false },
|
||||||
{ "connection_timeout", false, false },
|
{ "max_connections", false },
|
||||||
{ "max_connections", false, false },
|
{ "max_playlist_length", false },
|
||||||
{ "max_playlist_length", false, false },
|
{ "max_command_list_size", false },
|
||||||
{ "max_command_list_size", false, false },
|
{ "max_output_buffer_size", false },
|
||||||
{ "max_output_buffer_size", false, false },
|
{ "filesystem_charset", false },
|
||||||
{ "filesystem_charset", false, false },
|
{ "id3v1_encoding", false },
|
||||||
{ "id3v1_encoding", false, false },
|
{ "metadata_to_use", false },
|
||||||
{ "metadata_to_use", false, false },
|
{ "save_absolute_paths_in_playlists", false },
|
||||||
{ "save_absolute_paths_in_playlists", false, false },
|
{ "gapless_mp3_playback", false },
|
||||||
{ "decoder", true, true },
|
{ "auto_update", false },
|
||||||
{ "input", true, true },
|
{ "auto_update_depth", false },
|
||||||
{ "gapless_mp3_playback", false, false },
|
{ "despotify_user", false },
|
||||||
{ "playlist_plugin", true, true },
|
{ "despotify_password", false },
|
||||||
{ "auto_update", false, false },
|
{ "despotify_high_bitrate", false },
|
||||||
{ "auto_update_depth", false, false },
|
|
||||||
{ "despotify_user", false, false },
|
|
||||||
{ "despotify_password", false, false},
|
|
||||||
{ "despotify_high_bitrate", false, false },
|
|
||||||
{ "filter", true, true },
|
|
||||||
{ "database", false, true },
|
|
||||||
{ "neighbors", true, true },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr unsigned n_config_templates = ARRAY_SIZE(config_templates);
|
static constexpr unsigned n_config_param_templates =
|
||||||
|
ARRAY_SIZE(config_param_templates);
|
||||||
|
|
||||||
static_assert(n_config_templates == unsigned(ConfigOption::MAX),
|
static_assert(n_config_param_templates == unsigned(ConfigOption::MAX),
|
||||||
"Wrong number of config_templates");
|
"Wrong number of config_param_templates");
|
||||||
|
|
||||||
|
const ConfigTemplate config_block_templates[] = {
|
||||||
|
{ "audio_output", true },
|
||||||
|
{ "decoder", true },
|
||||||
|
{ "input", true },
|
||||||
|
{ "playlist_plugin", true },
|
||||||
|
{ "filter", true },
|
||||||
|
{ "database", false },
|
||||||
|
{ "neighbors", true },
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr unsigned n_config_block_templates =
|
||||||
|
ARRAY_SIZE(config_block_templates);
|
||||||
|
|
||||||
|
static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX),
|
||||||
|
"Wrong number of config_block_templates");
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
static inline unsigned
|
||||||
|
ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
for (; i < count; ++i)
|
||||||
|
if (strcmp(templates[i].name, name) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
ConfigOption
|
ConfigOption
|
||||||
ParseConfigOptionName(const char *name)
|
ParseConfigOptionName(const char *name)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < n_config_templates; ++i)
|
return ConfigOption(ParseConfigTemplateName(config_param_templates,
|
||||||
if (strcmp(config_templates[i].name, name) == 0)
|
n_config_param_templates,
|
||||||
return ConfigOption(i);
|
name));
|
||||||
|
}
|
||||||
return ConfigOption::MAX;
|
|
||||||
|
ConfigBlockOption
|
||||||
|
ParseConfigBlockOptionName(const char *name)
|
||||||
|
{
|
||||||
|
return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
|
||||||
|
n_config_block_templates,
|
||||||
|
name));
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
struct ConfigTemplate {
|
struct ConfigTemplate {
|
||||||
const char *const name;
|
const char *const name;
|
||||||
const bool repeatable;
|
const bool repeatable;
|
||||||
const bool block;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const ConfigTemplate config_templates[];
|
extern const ConfigTemplate config_param_templates[];
|
||||||
|
extern const ConfigTemplate config_block_templates[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Data.hxx"
|
#include "Data.hxx"
|
||||||
#include "Param.hxx"
|
#include "Param.hxx"
|
||||||
|
#include "Block.hxx"
|
||||||
|
|
||||||
void
|
void
|
||||||
ConfigData::Clear()
|
ConfigData::Clear()
|
||||||
@ -28,4 +29,9 @@ ConfigData::Clear()
|
|||||||
delete i;
|
delete i;
|
||||||
i = nullptr;
|
i = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &i : blocks) {
|
||||||
|
delete i;
|
||||||
|
i = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,11 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
struct config_param;
|
struct config_param;
|
||||||
|
struct ConfigBlock;
|
||||||
|
|
||||||
struct ConfigData {
|
struct ConfigData {
|
||||||
std::array<config_param *, std::size_t(ConfigOption::MAX)> params;
|
std::array<config_param *, std::size_t(ConfigOption::MAX)> params;
|
||||||
|
std::array<ConfigBlock *, std::size_t(ConfigBlockOption::MAX)> blocks;
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
@ -19,12 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Param.hxx"
|
#include "Param.hxx"
|
||||||
#include "ConfigPath.hxx"
|
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "fs/AllocatedPath.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
config_param::config_param(const char *_value, int _line)
|
config_param::config_param(const char *_value, int _line)
|
||||||
:next(nullptr), value(_value), line(_line), used(false) {}
|
:next(nullptr), value(_value), line(_line), used(false) {}
|
||||||
@ -33,91 +27,3 @@ config_param::~config_param()
|
|||||||
{
|
{
|
||||||
delete next;
|
delete next;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockParam *
|
|
||||||
config_param::GetBlockParam(const char *name) const
|
|
||||||
{
|
|
||||||
for (const auto &i : block_params) {
|
|
||||||
if (i.name == name) {
|
|
||||||
i.used = true;
|
|
||||||
return &i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
config_param::GetBlockValue(const char *name, const char *default_value) const
|
|
||||||
{
|
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
|
||||||
if (bp == nullptr)
|
|
||||||
return default_value;
|
|
||||||
|
|
||||||
return bp->value.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPath
|
|
||||||
config_param::GetBlockPath(const char *name, const char *default_value,
|
|
||||||
Error &error) const
|
|
||||||
{
|
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
int line2 = line;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
|
||||||
if (bp != nullptr) {
|
|
||||||
line2 = bp->line;
|
|
||||||
s = bp->value.c_str();
|
|
||||||
} else {
|
|
||||||
if (default_value == nullptr)
|
|
||||||
return AllocatedPath::Null();
|
|
||||||
|
|
||||||
s = default_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPath path = ParsePath(s, error);
|
|
||||||
if (gcc_unlikely(path.IsNull()))
|
|
||||||
error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
|
|
||||||
name, line2);
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPath
|
|
||||||
config_param::GetBlockPath(const char *name, Error &error) const
|
|
||||||
{
|
|
||||||
return GetBlockPath(name, nullptr, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
config_param::GetBlockValue(const char *name, int default_value) const
|
|
||||||
{
|
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
|
||||||
if (bp == nullptr)
|
|
||||||
return default_value;
|
|
||||||
|
|
||||||
return bp->GetIntValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
config_param::GetBlockValue(const char *name, unsigned default_value) const
|
|
||||||
{
|
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
|
||||||
if (bp == nullptr)
|
|
||||||
return default_value;
|
|
||||||
|
|
||||||
return bp->GetUnsignedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool
|
|
||||||
config_param::GetBlockValue(const char *name, bool default_value) const
|
|
||||||
{
|
|
||||||
const BlockParam *bp = GetBlockParam(name);
|
|
||||||
if (bp == nullptr)
|
|
||||||
return default_value;
|
|
||||||
|
|
||||||
return bp->GetBoolValue();
|
|
||||||
}
|
|
||||||
|
@ -20,14 +20,10 @@
|
|||||||
#ifndef MPD_CONFIG_PARAM_HXX
|
#ifndef MPD_CONFIG_PARAM_HXX
|
||||||
#define MPD_CONFIG_PARAM_HXX
|
#define MPD_CONFIG_PARAM_HXX
|
||||||
|
|
||||||
#include "Block.hxx"
|
#include "check.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class AllocatedPath;
|
|
||||||
class Error;
|
|
||||||
|
|
||||||
struct config_param {
|
struct config_param {
|
||||||
/**
|
/**
|
||||||
@ -40,8 +36,6 @@ struct config_param {
|
|||||||
|
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
std::vector<BlockParam> block_params;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This flag is false when nobody has queried the value of
|
* This flag is false when nobody has queried the value of
|
||||||
* this option yet.
|
* this option yet.
|
||||||
@ -68,37 +62,6 @@ struct config_param {
|
|||||||
bool IsNull() const {
|
bool IsNull() const {
|
||||||
return line < 0;
|
return line < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_nonnull_all
|
|
||||||
void AddBlockParam(const char *_name, const char *_value,
|
|
||||||
int _line=-1) {
|
|
||||||
block_params.emplace_back(_name, _value, _line);
|
|
||||||
}
|
|
||||||
|
|
||||||
gcc_nonnull_all gcc_pure
|
|
||||||
const BlockParam *GetBlockParam(const char *_name) const;
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
const char *GetBlockValue(const char *name,
|
|
||||||
const char *default_value=nullptr) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as config_get_path(), but looks up the setting in the
|
|
||||||
* specified block.
|
|
||||||
*/
|
|
||||||
AllocatedPath GetBlockPath(const char *name, const char *default_value,
|
|
||||||
Error &error) const;
|
|
||||||
|
|
||||||
AllocatedPath GetBlockPath(const char *name, Error &error) const;
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
int GetBlockValue(const char *name, int default_value) const;
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
unsigned GetBlockValue(const char *name, unsigned default_value) const;
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool GetBlockValue(const char *name, bool default_value) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "DatabaseGlue.hxx"
|
#include "DatabaseGlue.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Param.hxx"
|
||||||
|
#include "config/Block.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/StandardDirectory.hxx"
|
#include "fs/StandardDirectory.hxx"
|
||||||
@ -32,7 +33,7 @@ Database *
|
|||||||
CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
|
CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
const auto *param = config_get_param(ConfigOption::DATABASE);
|
const auto *param = config_get_block(ConfigBlockOption::DATABASE);
|
||||||
const auto *path = config_get_param(ConfigOption::DB_FILE);
|
const auto *path = config_get_param(ConfigOption::DB_FILE);
|
||||||
|
|
||||||
if (param != nullptr && path != nullptr) {
|
if (param != nullptr && path != nullptr) {
|
||||||
@ -42,10 +43,10 @@ CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct config_param *allocated = nullptr;
|
ConfigBlock *allocated = nullptr;
|
||||||
|
|
||||||
if (param == nullptr && path != nullptr) {
|
if (param == nullptr && path != nullptr) {
|
||||||
allocated = new config_param("database", path->line);
|
allocated = new ConfigBlock(path->line);
|
||||||
allocated->AddBlockParam("path", path->value.c_str(),
|
allocated->AddBlockParam("path", path->value.c_str(),
|
||||||
path->line);
|
path->line);
|
||||||
param = allocated;
|
param = allocated;
|
||||||
@ -60,7 +61,7 @@ CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
|
|||||||
|
|
||||||
const auto db_file = AllocatedPath::Build(cache_dir, "mpd.db");
|
const auto db_file = AllocatedPath::Build(cache_dir, "mpd.db");
|
||||||
|
|
||||||
allocated = new config_param("database");
|
allocated = new ConfigBlock();
|
||||||
allocated->AddBlockParam("path", db_file.c_str(), -1);
|
allocated->AddBlockParam("path", db_file.c_str(), -1);
|
||||||
param = allocated;
|
param = allocated;
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,17 @@
|
|||||||
#include "Registry.hxx"
|
#include "Registry.hxx"
|
||||||
#include "DatabaseError.hxx"
|
#include "DatabaseError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
Database *
|
Database *
|
||||||
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
|
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *plugin_name =
|
const char *plugin_name =
|
||||||
param.GetBlockValue("plugin", "simple");
|
block.GetBlockValue("plugin", "simple");
|
||||||
|
|
||||||
const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name);
|
const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name);
|
||||||
if (plugin == nullptr) {
|
if (plugin == nullptr) {
|
||||||
@ -41,5 +41,5 @@ DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugin->create(loop, listener, param, error);
|
return plugin->create(loop, listener, block, error);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
class DatabaseListener;
|
class DatabaseListener;
|
||||||
class Database;
|
class Database;
|
||||||
@ -35,6 +35,6 @@ class Error;
|
|||||||
*/
|
*/
|
||||||
Database *
|
Database *
|
||||||
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
|
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m, Error &error);
|
const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#ifndef MPD_DATABASE_PLUGIN_HXX
|
#ifndef MPD_DATABASE_PLUGIN_HXX
|
||||||
#define MPD_DATABASE_PLUGIN_HXX
|
#define MPD_DATABASE_PLUGIN_HXX
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class Error;
|
class Error;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
class DatabaseListener;
|
class DatabaseListener;
|
||||||
@ -47,7 +47,7 @@ struct DatabasePlugin {
|
|||||||
* Allocates and configures a database.
|
* Allocates and configures a database.
|
||||||
*/
|
*/
|
||||||
Database *(*create)(EventLoop &loop, DatabaseListener &listener,
|
Database *(*create)(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
constexpr bool RequireStorage() const {
|
constexpr bool RequireStorage() const {
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "db/Stats.hxx"
|
#include "db/Stats.hxx"
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
@ -97,7 +97,7 @@ public:
|
|||||||
listener(_listener) {}
|
listener(_listener) {}
|
||||||
|
|
||||||
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
virtual bool Open(Error &error) override;
|
virtual bool Open(Error &error) override;
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Connect(Error &error);
|
bool Connect(Error &error);
|
||||||
bool CheckConnection(Error &error);
|
bool CheckConnection(Error &error);
|
||||||
@ -321,10 +321,10 @@ SendConstraints(mpd_connection *connection, const DatabaseSelection &selection)
|
|||||||
|
|
||||||
Database *
|
Database *
|
||||||
ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener,
|
ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
ProxyDatabase *db = new ProxyDatabase(loop, listener);
|
ProxyDatabase *db = new ProxyDatabase(loop, listener);
|
||||||
if (!db->Configure(param, error)) {
|
if (!db->Configure(block, error)) {
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
}
|
}
|
||||||
@ -333,11 +333,11 @@ ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ProxyDatabase::Configure(const config_param ¶m, gcc_unused Error &error)
|
ProxyDatabase::Configure(const ConfigBlock &block, gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
host = param.GetBlockValue("host", "");
|
host = block.GetBlockValue("host", "");
|
||||||
port = param.GetBlockValue("port", 0u);
|
port = block.GetBlockValue("port", 0u);
|
||||||
keepalive = param.GetBlockValue("keepalive", false);
|
keepalive = block.GetBlockValue("keepalive", false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#include "fs/io/TextFile.hxx"
|
#include "fs/io/TextFile.hxx"
|
||||||
#include "fs/io/BufferedOutputStream.hxx"
|
#include "fs/io/BufferedOutputStream.hxx"
|
||||||
#include "fs/io/FileOutputStream.hxx"
|
#include "fs/io/FileOutputStream.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "util/CharUtil.hxx"
|
#include "util/CharUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
@ -76,10 +76,10 @@ inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path,
|
|||||||
Database *
|
Database *
|
||||||
SimpleDatabase::Create(gcc_unused EventLoop &loop,
|
SimpleDatabase::Create(gcc_unused EventLoop &loop,
|
||||||
gcc_unused DatabaseListener &listener,
|
gcc_unused DatabaseListener &listener,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
SimpleDatabase *db = new SimpleDatabase();
|
SimpleDatabase *db = new SimpleDatabase();
|
||||||
if (!db->Configure(param, error)) {
|
if (!db->Configure(block, error)) {
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
}
|
}
|
||||||
@ -88,9 +88,9 @@ SimpleDatabase::Create(gcc_unused EventLoop &loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SimpleDatabase::Configure(const config_param ¶m, Error &error)
|
SimpleDatabase::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
path = param.GetBlockPath("path", error);
|
path = block.GetBlockPath("path", error);
|
||||||
if (path.IsNull()) {
|
if (path.IsNull()) {
|
||||||
if (!error.IsDefined())
|
if (!error.IsDefined())
|
||||||
error.Set(simple_db_domain,
|
error.Set(simple_db_domain,
|
||||||
@ -100,12 +100,12 @@ SimpleDatabase::Configure(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
path_utf8 = path.ToUTF8();
|
path_utf8 = path.ToUTF8();
|
||||||
|
|
||||||
cache_path = param.GetBlockPath("cache_directory", error);
|
cache_path = block.GetBlockPath("cache_directory", error);
|
||||||
if (path.IsNull() && error.IsDefined())
|
if (path.IsNull() && error.IsDefined())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifdef ENABLE_ZLIB
|
#ifdef ENABLE_ZLIB
|
||||||
compress = param.GetBlockValue("compress", compress);
|
compress = block.GetBlockValue("compress", compress);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
struct Directory;
|
struct Directory;
|
||||||
struct DatabasePlugin;
|
struct DatabasePlugin;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
@ -73,7 +73,7 @@ class SimpleDatabase : public Database {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
@ -134,7 +134,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Check(Error &error) const;
|
bool Check(Error &error) const;
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include "db/LightDirectory.hxx"
|
#include "db/LightDirectory.hxx"
|
||||||
#include "db/LightSong.hxx"
|
#include "db/LightSong.hxx"
|
||||||
#include "db/Stats.hxx"
|
#include "db/Stats.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "tag/TagTable.hxx"
|
#include "tag/TagTable.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
@ -78,7 +78,7 @@ public:
|
|||||||
UpnpDatabase():Database(upnp_db_plugin) {}
|
UpnpDatabase():Database(upnp_db_plugin) {}
|
||||||
|
|
||||||
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
static Database *Create(EventLoop &loop, DatabaseListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
virtual bool Open(Error &error) override;
|
virtual bool Open(Error &error) override;
|
||||||
@ -106,7 +106,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool VisitServer(const ContentDirectoryService &server,
|
bool VisitServer(const ContentDirectoryService &server,
|
||||||
@ -158,10 +158,10 @@ private:
|
|||||||
Database *
|
Database *
|
||||||
UpnpDatabase::Create(gcc_unused EventLoop &loop,
|
UpnpDatabase::Create(gcc_unused EventLoop &loop,
|
||||||
gcc_unused DatabaseListener &listener,
|
gcc_unused DatabaseListener &listener,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
UpnpDatabase *db = new UpnpDatabase();
|
UpnpDatabase *db = new UpnpDatabase();
|
||||||
if (!db->Configure(param, error)) {
|
if (!db->Configure(block, error)) {
|
||||||
delete db;
|
delete db;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ UpnpDatabase::Create(gcc_unused EventLoop &loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
UpnpDatabase::Configure(const config_param &, Error &)
|
UpnpDatabase::Configure(const ConfigBlock &, Error &)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "MixRampInfo.hxx"
|
#include "MixRampInfo.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "Chrono.hxx"
|
#include "Chrono.hxx"
|
||||||
|
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "DecoderList.hxx"
|
#include "DecoderList.hxx"
|
||||||
#include "DecoderPlugin.hxx"
|
#include "DecoderPlugin.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "plugins/AudiofileDecoderPlugin.hxx"
|
#include "plugins/AudiofileDecoderPlugin.hxx"
|
||||||
#include "plugins/PcmDecoderPlugin.hxx"
|
#include "plugins/PcmDecoderPlugin.hxx"
|
||||||
#include "plugins/DsdiffDecoderPlugin.hxx"
|
#include "plugins/DsdiffDecoderPlugin.hxx"
|
||||||
@ -127,12 +127,12 @@ decoder_plugin_from_name(const char *name)
|
|||||||
|
|
||||||
void decoder_plugin_init_all(void)
|
void decoder_plugin_init_all(void)
|
||||||
{
|
{
|
||||||
struct config_param empty;
|
ConfigBlock empty;
|
||||||
|
|
||||||
for (unsigned i = 0; decoder_plugins[i] != nullptr; ++i) {
|
for (unsigned i = 0; decoder_plugins[i] != nullptr; ++i) {
|
||||||
const DecoderPlugin &plugin = *decoder_plugins[i];
|
const DecoderPlugin &plugin = *decoder_plugins[i];
|
||||||
const struct config_param *param =
|
const auto *param =
|
||||||
config_find_block(ConfigOption::DECODER, "plugin",
|
config_find_block(ConfigBlockOption::DECODER, "plugin",
|
||||||
plugin.name);
|
plugin.name);
|
||||||
|
|
||||||
if (param == nullptr)
|
if (param == nullptr)
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class InputStream;
|
class InputStream;
|
||||||
struct tag_handler;
|
struct tag_handler;
|
||||||
class Path;
|
class Path;
|
||||||
@ -44,7 +44,7 @@ struct DecoderPlugin {
|
|||||||
* @return true if the plugin was initialized successfully,
|
* @return true if the plugin was initialized successfully,
|
||||||
* false if the plugin is not available
|
* false if the plugin is not available
|
||||||
*/
|
*/
|
||||||
bool (*init)(const config_param ¶m);
|
bool (*init)(const ConfigBlock &block);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deinitialize a decoder plugin which was initialized
|
* Deinitialize a decoder plugin which was initialized
|
||||||
@ -112,9 +112,9 @@ struct DecoderPlugin {
|
|||||||
* @return true if the plugin was initialized successfully, false if
|
* @return true if the plugin was initialized successfully, false if
|
||||||
* the plugin is not available
|
* the plugin is not available
|
||||||
*/
|
*/
|
||||||
bool Init(const config_param ¶m) const {
|
bool Init(const ConfigBlock &block) const {
|
||||||
return init != nullptr
|
return init != nullptr
|
||||||
? init(param)
|
? init(block)
|
||||||
: true;
|
: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,14 +38,14 @@ static constexpr Domain adplug_domain("adplug");
|
|||||||
static unsigned sample_rate;
|
static unsigned sample_rate;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
adplug_init(const config_param ¶m)
|
adplug_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
FormatDebug(adplug_domain, "adplug %s",
|
FormatDebug(adplug_domain, "adplug %s",
|
||||||
CAdPlug::get_version().c_str());
|
CAdPlug::get_version().c_str());
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
|
|
||||||
sample_rate = param.GetBlockValue("sample_rate", 48000u);
|
sample_rate = block.GetBlockValue("sample_rate", 48000u);
|
||||||
if (!audio_check_sample_rate(sample_rate, error)) {
|
if (!audio_check_sample_rate(sample_rate, error)) {
|
||||||
LogError(error);
|
LogError(error);
|
||||||
return false;
|
return false;
|
||||||
|
@ -43,7 +43,7 @@ audiofile_error_func(long, const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
audiofile_init(const config_param &)
|
audiofile_init(const ConfigBlock &)
|
||||||
{
|
{
|
||||||
afSetErrorHandler(audiofile_error_func);
|
afSetErrorHandler(audiofile_error_func);
|
||||||
return true;
|
return true;
|
||||||
|
@ -72,9 +72,9 @@ struct DsdiffMetaData {
|
|||||||
static bool lsbitfirst;
|
static bool lsbitfirst;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
dsdiff_init(const config_param ¶m)
|
dsdiff_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
lsbitfirst = param.GetBlockValue("lsbitfirst", false);
|
lsbitfirst = block.GetBlockValue("lsbitfirst", false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ FfmpegOpenInput(AVIOContext *pb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ffmpeg_init(gcc_unused const config_param ¶m)
|
ffmpeg_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
FfmpegInit();
|
FfmpegInit();
|
||||||
return true;
|
return true;
|
||||||
|
@ -291,7 +291,7 @@ flac_decode(Decoder &decoder, InputStream &input_stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
oggflac_init(gcc_unused const config_param ¶m)
|
oggflac_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
return !!FLAC_API_SUPPORTS_OGG_FLAC;
|
return !!FLAC_API_SUPPORTS_OGG_FLAC;
|
||||||
}
|
}
|
||||||
|
@ -73,17 +73,17 @@ fluidsynth_mpd_log_function(int level, char *message, gcc_unused void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
fluidsynth_init(const config_param ¶m)
|
fluidsynth_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
Error error;
|
Error error;
|
||||||
|
|
||||||
sample_rate = param.GetBlockValue("sample_rate", 48000u);
|
sample_rate = block.GetBlockValue("sample_rate", 48000u);
|
||||||
if (!audio_check_sample_rate(sample_rate, error)) {
|
if (!audio_check_sample_rate(sample_rate, error)) {
|
||||||
LogError(error);
|
LogError(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
soundfont_path = param.GetBlockValue("soundfont",
|
soundfont_path = block.GetBlockValue("soundfont",
|
||||||
"/usr/share/sounds/sf2/FluidR3_GM.sf2");
|
"/usr/share/sounds/sf2/FluidR3_GM.sf2");
|
||||||
|
|
||||||
fluid_set_log_function(LAST_LOG_LEVEL,
|
fluid_set_log_function(LAST_LOG_LEVEL,
|
||||||
|
@ -107,7 +107,7 @@ mad_fixed_to_24_buffer(int32_t *dest, const struct mad_synth *synth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mp3_plugin_init(gcc_unused const config_param ¶m)
|
mp3_plugin_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
gapless_playback = config_get_bool(ConfigOption::GAPLESS_MP3_PLAYBACK,
|
gapless_playback = config_get_bool(ConfigOption::GAPLESS_MP3_PLAYBACK,
|
||||||
DEFAULT_GAPLESS_MP3_PLAYBACK);
|
DEFAULT_GAPLESS_MP3_PLAYBACK);
|
||||||
|
@ -109,15 +109,15 @@ static bool mikmod_loop;
|
|||||||
static unsigned mikmod_sample_rate;
|
static unsigned mikmod_sample_rate;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mikmod_decoder_init(const config_param ¶m)
|
mikmod_decoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
static char params[] = "";
|
static char params[] = "";
|
||||||
|
|
||||||
mikmod_loop = param.GetBlockValue("loop", false);
|
mikmod_loop = block.GetBlockValue("loop", false);
|
||||||
mikmod_sample_rate = param.GetBlockValue("sample_rate", 44100u);
|
mikmod_sample_rate = block.GetBlockValue("sample_rate", 44100u);
|
||||||
if (!audio_valid_sample_rate(mikmod_sample_rate))
|
if (!audio_valid_sample_rate(mikmod_sample_rate))
|
||||||
FormatFatalError("Invalid sample rate in line %d: %u",
|
FormatFatalError("Invalid sample rate in line %d: %u",
|
||||||
param.line, mikmod_sample_rate);
|
block.line, mikmod_sample_rate);
|
||||||
|
|
||||||
md_device = 0;
|
md_device = 0;
|
||||||
md_reverb = 0;
|
md_reverb = 0;
|
||||||
|
@ -41,12 +41,12 @@ static constexpr offset_type MODPLUG_FILE_LIMIT = 100 * 1024 * 1024;
|
|||||||
static int modplug_loop_count;
|
static int modplug_loop_count;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
modplug_decoder_init(const config_param ¶m)
|
modplug_decoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
modplug_loop_count = param.GetBlockValue("loop_count", 0);
|
modplug_loop_count = block.GetBlockValue("loop_count", 0);
|
||||||
if (modplug_loop_count < -1)
|
if (modplug_loop_count < -1)
|
||||||
FormatFatalError("Invalid loop count in line %d: %i",
|
FormatFatalError("Invalid loop count in line %d: %i",
|
||||||
param.line, modplug_loop_count);
|
block.line, modplug_loop_count);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
static constexpr Domain mpg123_domain("mpg123");
|
static constexpr Domain mpg123_domain("mpg123");
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mpd_mpg123_init(gcc_unused const config_param ¶m)
|
mpd_mpg123_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
mpg123_init();
|
mpg123_init();
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ IsOpusTags(const ogg_packet &packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mpd_opus_init(gcc_unused const config_param ¶m)
|
mpd_opus_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
LogDebug(opus_domain, opus_get_version_string());
|
LogDebug(opus_domain, opus_get_version_string());
|
||||||
|
|
||||||
|
@ -64,22 +64,22 @@ sidplay_load_songlength_db(const Path path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sidplay_init(const config_param ¶m)
|
sidplay_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
/* read the songlengths database file */
|
/* read the songlengths database file */
|
||||||
Error error;
|
Error error;
|
||||||
const auto database_path = param.GetBlockPath("songlength_database", error);
|
const auto database_path = block.GetBlockPath("songlength_database", error);
|
||||||
if (!database_path.IsNull())
|
if (!database_path.IsNull())
|
||||||
songlength_database = sidplay_load_songlength_db(database_path);
|
songlength_database = sidplay_load_songlength_db(database_path);
|
||||||
else if (error.IsDefined())
|
else if (error.IsDefined())
|
||||||
FatalError(error);
|
FatalError(error);
|
||||||
|
|
||||||
default_songlength = param.GetBlockValue("default_songlength", 0u);
|
default_songlength = block.GetBlockValue("default_songlength", 0u);
|
||||||
|
|
||||||
all_files_are_containers =
|
all_files_are_containers =
|
||||||
param.GetBlockValue("all_files_are_containers", true);
|
block.GetBlockValue("all_files_are_containers", true);
|
||||||
|
|
||||||
filter_setting = param.GetBlockValue("filter", true);
|
filter_setting = block.GetBlockValue("filter", true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
static constexpr Domain sndfile_domain("sndfile");
|
static constexpr Domain sndfile_domain("sndfile");
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sndfile_init(gcc_unused const config_param ¶m)
|
sndfile_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
LogDebug(sndfile_domain, sf_version_string());
|
LogDebug(sndfile_domain, sf_version_string());
|
||||||
return true;
|
return true;
|
||||||
|
@ -194,7 +194,7 @@ vorbis_interleave(float *dest, const float *const*src,
|
|||||||
/* public */
|
/* public */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
vorbis_init(gcc_unused const config_param ¶m)
|
vorbis_init(gcc_unused const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_TREMOR
|
#ifndef HAVE_TREMOR
|
||||||
LogDebug(vorbis_domain, vorbis_version_string());
|
LogDebug(vorbis_domain, vorbis_version_string());
|
||||||
|
@ -38,11 +38,11 @@ static constexpr Domain wildmidi_domain("wildmidi");
|
|||||||
static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000;
|
static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wildmidi_init(const config_param ¶m)
|
wildmidi_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
Error error;
|
Error error;
|
||||||
const AllocatedPath path =
|
const AllocatedPath path =
|
||||||
param.GetBlockPath("config_file",
|
block.GetBlockPath("config_file",
|
||||||
"/etc/timidity/timidity.cfg",
|
"/etc/timidity/timidity.cfg",
|
||||||
error);
|
error);
|
||||||
if (path.IsNull())
|
if (path.IsNull())
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "EncoderPlugin.hxx"
|
#include "EncoderPlugin.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
|
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@
|
|||||||
|
|
||||||
struct Encoder;
|
struct Encoder;
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
class Error;
|
class Error;
|
||||||
|
|
||||||
struct EncoderPlugin {
|
struct EncoderPlugin {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
Encoder *(*init)(const config_param ¶m,
|
Encoder *(*init)(const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
void (*finish)(Encoder *encoder);
|
void (*finish)(Encoder *encoder);
|
||||||
@ -69,10 +69,10 @@ struct EncoderPlugin {
|
|||||||
* @return an encoder object on success, nullptr on failure
|
* @return an encoder object on success, nullptr on failure
|
||||||
*/
|
*/
|
||||||
static inline Encoder *
|
static inline Encoder *
|
||||||
encoder_init(const EncoderPlugin &plugin, const config_param ¶m,
|
encoder_init(const EncoderPlugin &plugin, const ConfigBlock &block,
|
||||||
Error &error_r)
|
Error &error_r)
|
||||||
{
|
{
|
||||||
return plugin.init(param, error_r);
|
return plugin.init(block, error_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,21 +56,21 @@ struct flac_encoder {
|
|||||||
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
flac_encoder_configure(struct flac_encoder *encoder, const config_param ¶m,
|
flac_encoder_configure(struct flac_encoder *encoder, const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
encoder->compression = param.GetBlockValue("compression", 5u);
|
encoder->compression = block.GetBlockValue("compression", 5u);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
flac_encoder_init(const config_param ¶m, Error &error)
|
flac_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
flac_encoder *encoder = new flac_encoder();
|
flac_encoder *encoder = new flac_encoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!flac_encoder_configure(encoder, param, error)) {
|
if (!flac_encoder_configure(encoder, block, error)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -47,18 +47,18 @@ struct LameEncoder final {
|
|||||||
|
|
||||||
LameEncoder():encoder(lame_encoder_plugin) {}
|
LameEncoder():encoder(lame_encoder_plugin) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain lame_encoder_domain("lame_encoder");
|
static constexpr Domain lame_encoder_domain("lame_encoder");
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LameEncoder::Configure(const config_param ¶m, Error &error)
|
LameEncoder::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
value = param.GetBlockValue("quality");
|
value = block.GetBlockValue("quality");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
/* a quality was configured (VBR) */
|
/* a quality was configured (VBR) */
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ LameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"quality and bitrate are both defined");
|
"quality and bitrate are both defined");
|
||||||
return false;
|
return false;
|
||||||
@ -80,7 +80,7 @@ LameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = param.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"neither bitrate nor quality defined");
|
"neither bitrate nor quality defined");
|
||||||
@ -101,12 +101,12 @@ LameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
lame_encoder_init(const config_param ¶m, Error &error)
|
lame_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
LameEncoder *encoder = new LameEncoder();
|
LameEncoder *encoder = new LameEncoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!encoder->Configure(param, error)) {
|
if (!encoder->Configure(block, error)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -36,7 +36,7 @@ struct NullEncoder final {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
null_encoder_init(gcc_unused const config_param ¶m,
|
null_encoder_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
NullEncoder *encoder = new NullEncoder();
|
NullEncoder *encoder = new NullEncoder();
|
||||||
|
@ -73,9 +73,9 @@ static constexpr Domain opus_encoder_domain("opus_encoder");
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
opus_encoder_configure(struct opus_encoder *encoder,
|
opus_encoder_configure(struct opus_encoder *encoder,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value = param.GetBlockValue("bitrate", "auto");
|
const char *value = block.GetBlockValue("bitrate", "auto");
|
||||||
if (strcmp(value, "auto") == 0)
|
if (strcmp(value, "auto") == 0)
|
||||||
encoder->bitrate = OPUS_AUTO;
|
encoder->bitrate = OPUS_AUTO;
|
||||||
else if (strcmp(value, "max") == 0)
|
else if (strcmp(value, "max") == 0)
|
||||||
@ -90,13 +90,13 @@ opus_encoder_configure(struct opus_encoder *encoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder->complexity = param.GetBlockValue("complexity", 10u);
|
encoder->complexity = block.GetBlockValue("complexity", 10u);
|
||||||
if (encoder->complexity > 10) {
|
if (encoder->complexity > 10) {
|
||||||
error.Format(config_domain, "Invalid complexity");
|
error.Format(config_domain, "Invalid complexity");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = param.GetBlockValue("signal", "auto");
|
value = block.GetBlockValue("signal", "auto");
|
||||||
if (strcmp(value, "auto") == 0)
|
if (strcmp(value, "auto") == 0)
|
||||||
encoder->signal = OPUS_AUTO;
|
encoder->signal = OPUS_AUTO;
|
||||||
else if (strcmp(value, "voice") == 0)
|
else if (strcmp(value, "voice") == 0)
|
||||||
@ -112,12 +112,12 @@ opus_encoder_configure(struct opus_encoder *encoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
opus_encoder_init(const config_param ¶m, Error &error)
|
opus_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
opus_encoder *encoder = new opus_encoder();
|
opus_encoder *encoder = new opus_encoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!opus_encoder_configure(encoder, param, error)) {
|
if (!opus_encoder_configure(encoder, block, error)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -53,7 +53,7 @@ struct ShineEncoder {
|
|||||||
|
|
||||||
ShineEncoder():encoder(shine_encoder_plugin){}
|
ShineEncoder():encoder(shine_encoder_plugin){}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Setup(Error &error);
|
bool Setup(Error &error);
|
||||||
|
|
||||||
@ -63,22 +63,21 @@ struct ShineEncoder {
|
|||||||
static constexpr Domain shine_encoder_domain("shine_encoder");
|
static constexpr Domain shine_encoder_domain("shine_encoder");
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ShineEncoder::Configure(const config_param ¶m,
|
ShineEncoder::Configure(const ConfigBlock &block, gcc_unused Error &error)
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
{
|
||||||
shine_set_config_mpeg_defaults(&config.mpeg);
|
shine_set_config_mpeg_defaults(&config.mpeg);
|
||||||
config.mpeg.bitr = param.GetBlockValue("bitrate", 128);
|
config.mpeg.bitr = block.GetBlockValue("bitrate", 128);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
shine_encoder_init(const config_param ¶m, Error &error)
|
shine_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
ShineEncoder *encoder = new ShineEncoder();
|
ShineEncoder *encoder = new ShineEncoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!encoder->Configure(param, error)) {
|
if (!encoder->Configure(block, error)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -53,18 +53,18 @@ struct TwolameEncoder final {
|
|||||||
|
|
||||||
TwolameEncoder():encoder(twolame_encoder_plugin) {}
|
TwolameEncoder():encoder(twolame_encoder_plugin) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TwolameEncoder::Configure(const config_param ¶m, Error &error)
|
TwolameEncoder::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
value = param.GetBlockValue("quality");
|
value = block.GetBlockValue("quality");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
/* a quality was configured (VBR) */
|
/* a quality was configured (VBR) */
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ TwolameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"quality and bitrate are both defined");
|
"quality and bitrate are both defined");
|
||||||
return false;
|
return false;
|
||||||
@ -86,7 +86,7 @@ TwolameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = param.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"neither bitrate nor quality defined");
|
"neither bitrate nor quality defined");
|
||||||
@ -107,15 +107,15 @@ TwolameEncoder::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
twolame_encoder_init(const config_param ¶m, Error &error_r)
|
twolame_encoder_init(const ConfigBlock &block, Error &error_r)
|
||||||
{
|
{
|
||||||
FormatDebug(twolame_encoder_domain,
|
FormatDebug(twolame_encoder_domain,
|
||||||
"libtwolame version %s", get_twolame_version());
|
"libtwolame version %s", get_twolame_version());
|
||||||
|
|
||||||
TwolameEncoder *encoder = new TwolameEncoder();
|
TwolameEncoder *encoder = new TwolameEncoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!encoder->Configure(param, error_r)) {
|
if (!encoder->Configure(block, error_r)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -58,9 +58,9 @@ static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
vorbis_encoder_configure(struct vorbis_encoder &encoder,
|
vorbis_encoder_configure(struct vorbis_encoder &encoder,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value = param.GetBlockValue("quality");
|
const char *value = block.GetBlockValue("quality");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
/* a quality was configured (VBR) */
|
/* a quality was configured (VBR) */
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ vorbis_encoder_configure(struct vorbis_encoder &encoder,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"quality and bitrate are both defined");
|
"quality and bitrate are both defined");
|
||||||
return false;
|
return false;
|
||||||
@ -84,7 +84,7 @@ vorbis_encoder_configure(struct vorbis_encoder &encoder,
|
|||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = param.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"neither bitrate nor quality defined");
|
"neither bitrate nor quality defined");
|
||||||
@ -106,12 +106,12 @@ vorbis_encoder_configure(struct vorbis_encoder &encoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
vorbis_encoder_init(const config_param ¶m, Error &error)
|
vorbis_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
vorbis_encoder *encoder = new vorbis_encoder();
|
vorbis_encoder *encoder = new vorbis_encoder();
|
||||||
|
|
||||||
/* load configuration from "param" */
|
/* load configuration from "block" */
|
||||||
if (!vorbis_encoder_configure(*encoder, param, error)) {
|
if (!vorbis_encoder_configure(*encoder, block, error)) {
|
||||||
/* configuration has failed, roll back and return error */
|
/* configuration has failed, roll back and return error */
|
||||||
delete encoder;
|
delete encoder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -79,7 +79,7 @@ fill_wave_header(struct wave_header *header, int channels, int bits,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
static Encoder *
|
||||||
wave_encoder_init(gcc_unused const config_param ¶m,
|
wave_encoder_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
WaveEncoder *encoder = new WaveEncoder();
|
WaveEncoder *encoder = new WaveEncoder();
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
|
#include "config/Block.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -34,9 +35,8 @@
|
|||||||
static bool
|
static bool
|
||||||
filter_chain_append_new(Filter &chain, const char *template_name, Error &error)
|
filter_chain_append_new(Filter &chain, const char *template_name, Error &error)
|
||||||
{
|
{
|
||||||
const struct config_param *cfg =
|
const auto *cfg = config_find_block(ConfigBlockOption::AUDIO_FILTER,
|
||||||
config_find_block(ConfigOption::AUDIO_FILTER, "name",
|
"name", template_name);
|
||||||
template_name);
|
|
||||||
if (cfg == nullptr) {
|
if (cfg == nullptr) {
|
||||||
error.Format(config_domain,
|
error.Format(config_domain,
|
||||||
"filter template not found: %s",
|
"filter template not found: %s",
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "FilterPlugin.hxx"
|
#include "FilterPlugin.hxx"
|
||||||
#include "FilterRegistry.hxx"
|
#include "FilterRegistry.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
@ -28,20 +28,20 @@
|
|||||||
|
|
||||||
Filter *
|
Filter *
|
||||||
filter_new(const struct filter_plugin *plugin,
|
filter_new(const struct filter_plugin *plugin,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
assert(plugin != nullptr);
|
assert(plugin != nullptr);
|
||||||
assert(!error.IsDefined());
|
assert(!error.IsDefined());
|
||||||
|
|
||||||
return plugin->init(param, error);
|
return plugin->init(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Filter *
|
Filter *
|
||||||
filter_configured_new(const config_param ¶m, Error &error)
|
filter_configured_new(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
assert(!error.IsDefined());
|
assert(!error.IsDefined());
|
||||||
|
|
||||||
const char *plugin_name = param.GetBlockValue("plugin");
|
const char *plugin_name = block.GetBlockValue("plugin");
|
||||||
if (plugin_name == nullptr) {
|
if (plugin_name == nullptr) {
|
||||||
error.Set(config_domain, "No filter plugin specified");
|
error.Set(config_domain, "No filter plugin specified");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -54,5 +54,5 @@ filter_configured_new(const config_param ¶m, Error &error)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter_new(plugin, param, error);
|
return filter_new(plugin, block, error);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#ifndef MPD_FILTER_PLUGIN_HXX
|
#ifndef MPD_FILTER_PLUGIN_HXX
|
||||||
#define MPD_FILTER_PLUGIN_HXX
|
#define MPD_FILTER_PLUGIN_HXX
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class Filter;
|
class Filter;
|
||||||
class Error;
|
class Error;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ struct filter_plugin {
|
|||||||
/**
|
/**
|
||||||
* Allocates and configures a filter.
|
* Allocates and configures a filter.
|
||||||
*/
|
*/
|
||||||
Filter *(*init)(const config_param ¶m, Error &error);
|
Filter *(*init)(const ConfigBlock &block, Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +50,7 @@ struct filter_plugin {
|
|||||||
*/
|
*/
|
||||||
Filter *
|
Filter *
|
||||||
filter_new(const struct filter_plugin *plugin,
|
filter_new(const struct filter_plugin *plugin,
|
||||||
const config_param ¶m, Error &error);
|
const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new filter, loads configuration and the plugin name from
|
* Creates a new filter, loads configuration and the plugin name from
|
||||||
@ -62,6 +62,6 @@ filter_new(const struct filter_plugin *plugin,
|
|||||||
* @return a new filter object, or nullptr on error
|
* @return a new filter object, or nullptr on error
|
||||||
*/
|
*/
|
||||||
Filter *
|
Filter *
|
||||||
filter_configured_new(const config_param ¶m, Error &error);
|
filter_configured_new(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "filter/FilterInternal.hxx"
|
#include "filter/FilterInternal.hxx"
|
||||||
#include "filter/FilterRegistry.hxx"
|
#include "filter/FilterRegistry.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "util/ConstBuffer.hxx"
|
#include "util/ConstBuffer.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -70,7 +70,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
|
|||||||
if (in_audio_format != child_audio_format) {
|
if (in_audio_format != child_audio_format) {
|
||||||
/* yes - create a convert_filter */
|
/* yes - create a convert_filter */
|
||||||
|
|
||||||
const config_param empty;
|
const ConfigBlock empty;
|
||||||
convert = filter_new(&convert_filter_plugin, empty, error);
|
convert = filter_new(&convert_filter_plugin, empty, error);
|
||||||
if (convert == nullptr) {
|
if (convert == nullptr) {
|
||||||
filter->Close();
|
filter->Close();
|
||||||
|
@ -70,7 +70,7 @@ private:
|
|||||||
static constexpr Domain chain_filter_domain("chain_filter");
|
static constexpr Domain chain_filter_domain("chain_filter");
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
chain_filter_init(gcc_unused const config_param ¶m,
|
chain_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new ChainFilter();
|
return new ChainFilter();
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
convert_filter_init(gcc_unused const config_param ¶m,
|
convert_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new ConvertFilter();
|
return new ConvertFilter();
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
normalize_filter_init(gcc_unused const config_param ¶m,
|
normalize_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new NormalizeFilter();
|
return new NormalizeFilter();
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
null_filter_init(gcc_unused const config_param ¶m,
|
null_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new NullFilter();
|
return new NullFilter();
|
||||||
|
@ -150,7 +150,7 @@ ReplayGainFilter::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
replay_gain_filter_init(gcc_unused const config_param ¶m,
|
replay_gain_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new ReplayGainFilter();
|
return new ReplayGainFilter();
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "filter/FilterPlugin.hxx"
|
#include "filter/FilterPlugin.hxx"
|
||||||
#include "filter/FilterInternal.hxx"
|
#include "filter/FilterInternal.hxx"
|
||||||
@ -114,11 +114,11 @@ public:
|
|||||||
* a>b, c>d, e>f, ...
|
* a>b, c>d, e>f, ...
|
||||||
* where a... are non-unique, non-negative integers
|
* where a... are non-unique, non-negative integers
|
||||||
* and input channel a gets copied to output channel b, etc.
|
* and input channel a gets copied to output channel b, etc.
|
||||||
* @param param the configuration block to read
|
* @param block the configuration block to read
|
||||||
* @param filter a route_filter whose min_channels and sources[] to set
|
* @param filter a route_filter whose min_channels and sources[] to set
|
||||||
* @return true on success, false on error
|
* @return true on success, false on error
|
||||||
*/
|
*/
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
/* virtual methods from class Filter */
|
/* virtual methods from class Filter */
|
||||||
AudioFormat Open(AudioFormat &af, Error &error) override;
|
AudioFormat Open(AudioFormat &af, Error &error) override;
|
||||||
@ -128,7 +128,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RouteFilter::Configure(const config_param ¶m, Error &error) {
|
RouteFilter::Configure(const ConfigBlock &block, Error &error) {
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* With a more clever way of marking "don't copy to output N",
|
* With a more clever way of marking "don't copy to output N",
|
||||||
@ -142,7 +142,7 @@ RouteFilter::Configure(const config_param ¶m, Error &error) {
|
|||||||
min_output_channels = 0;
|
min_output_channels = 0;
|
||||||
|
|
||||||
// A cowardly default, just passthrough stereo
|
// A cowardly default, just passthrough stereo
|
||||||
const char *routes = param.GetBlockValue("routes", "0>0, 1>1");
|
const char *routes = block.GetBlockValue("routes", "0>0, 1>1");
|
||||||
while (true) {
|
while (true) {
|
||||||
routes = StripLeft(routes);
|
routes = StripLeft(routes);
|
||||||
|
|
||||||
@ -205,10 +205,10 @@ RouteFilter::Configure(const config_param ¶m, Error &error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
route_filter_init(const config_param ¶m, Error &error)
|
route_filter_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
RouteFilter *filter = new RouteFilter();
|
RouteFilter *filter = new RouteFilter();
|
||||||
if (!filter->Configure(param, error)) {
|
if (!filter->Configure(block, error)) {
|
||||||
delete filter;
|
delete filter;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public:
|
|||||||
static constexpr Domain volume_domain("pcm_volume");
|
static constexpr Domain volume_domain("pcm_volume");
|
||||||
|
|
||||||
static Filter *
|
static Filter *
|
||||||
volume_filter_init(gcc_unused const config_param ¶m,
|
volume_filter_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new VolumeFilter();
|
return new VolumeFilter();
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
bool
|
bool
|
||||||
input_stream_global_init(Error &error)
|
input_stream_global_init(Error &error)
|
||||||
{
|
{
|
||||||
const config_param empty;
|
const ConfigBlock empty;
|
||||||
|
|
||||||
for (unsigned i = 0; input_plugins[i] != nullptr; ++i) {
|
for (unsigned i = 0; input_plugins[i] != nullptr; ++i) {
|
||||||
const InputPlugin *plugin = input_plugins[i];
|
const InputPlugin *plugin = input_plugins[i];
|
||||||
@ -42,17 +42,17 @@ input_stream_global_init(Error &error)
|
|||||||
assert(*plugin->name != 0);
|
assert(*plugin->name != 0);
|
||||||
assert(plugin->open != nullptr);
|
assert(plugin->open != nullptr);
|
||||||
|
|
||||||
const struct config_param *param =
|
const auto *block =
|
||||||
config_find_block(ConfigOption::INPUT, "plugin",
|
config_find_block(ConfigBlockOption::INPUT, "plugin",
|
||||||
plugin->name);
|
plugin->name);
|
||||||
if (param == nullptr) {
|
if (block == nullptr) {
|
||||||
param = ∅
|
block = ∅
|
||||||
} else if (!param->GetBlockValue("enabled", true))
|
} else if (!block->GetBlockValue("enabled", true))
|
||||||
/* the plugin is disabled in mpd.conf */
|
/* the plugin is disabled in mpd.conf */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
InputPlugin::InitResult result = plugin->init != nullptr
|
InputPlugin::InitResult result = plugin->init != nullptr
|
||||||
? plugin->init(*param, error)
|
? plugin->init(*block, error)
|
||||||
: InputPlugin::InitResult::SUCCESS;
|
: InputPlugin::InitResult::SUCCESS;
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class InputStream;
|
class InputStream;
|
||||||
class Error;
|
class Error;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
@ -69,7 +69,7 @@ struct InputPlugin {
|
|||||||
* @return true on success, false if the plugin should be
|
* @return true on success, false if the plugin should be
|
||||||
* disabled
|
* disabled
|
||||||
*/
|
*/
|
||||||
InitResult (*init)(const config_param ¶m, Error &error);
|
InitResult (*init)(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global deinitialization. Called once before MPD shuts
|
* Global deinitialization. Called once before MPD shuts
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "system/ByteOrder.hxx"
|
#include "system/ByteOrder.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -106,9 +106,9 @@ static constexpr Domain cdio_domain("cdio");
|
|||||||
static bool default_reverse_endian;
|
static bool default_reverse_endian;
|
||||||
|
|
||||||
static InputPlugin::InitResult
|
static InputPlugin::InitResult
|
||||||
input_cdio_init(const config_param ¶m, Error &error)
|
input_cdio_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value = param.GetBlockValue("default_byte_order");
|
const char *value = block.GetBlockValue("default_byte_order");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
if (strcmp(value, "little_endian") == 0)
|
if (strcmp(value, "little_endian") == 0)
|
||||||
default_reverse_endian = IsBigEndian();
|
default_reverse_endian = IsBigEndian();
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "../IcyInputStream.hxx"
|
#include "../IcyInputStream.hxx"
|
||||||
#include "../InputPlugin.hxx"
|
#include "../InputPlugin.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "event/SocketMonitor.hxx"
|
#include "event/SocketMonitor.hxx"
|
||||||
@ -535,7 +535,7 @@ CurlMulti::OnTimeout()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static InputPlugin::InitResult
|
static InputPlugin::InitResult
|
||||||
input_curl_init(const config_param ¶m, Error &error)
|
input_curl_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
|
CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
|
||||||
if (code != CURLE_OK) {
|
if (code != CURLE_OK) {
|
||||||
@ -557,10 +557,10 @@ input_curl_init(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK");
|
http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK");
|
||||||
|
|
||||||
proxy = param.GetBlockValue("proxy");
|
proxy = block.GetBlockValue("proxy");
|
||||||
proxy_port = param.GetBlockValue("proxy_port", 0u);
|
proxy_port = block.GetBlockValue("proxy_port", 0u);
|
||||||
proxy_user = param.GetBlockValue("proxy_user");
|
proxy_user = block.GetBlockValue("proxy_user");
|
||||||
proxy_password = param.GetBlockValue("proxy_password");
|
proxy_password = block.GetBlockValue("proxy_password");
|
||||||
|
|
||||||
if (proxy == nullptr) {
|
if (proxy == nullptr) {
|
||||||
/* deprecated proxy configuration */
|
/* deprecated proxy configuration */
|
||||||
@ -571,8 +571,8 @@ input_curl_init(const config_param ¶m, Error &error)
|
|||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
verify_peer = param.GetBlockValue("verify_peer", true);
|
verify_peer = block.GetBlockValue("verify_peer", true);
|
||||||
verify_host = param.GetBlockValue("verify_host", true);
|
verify_host = block.GetBlockValue("verify_host", true);
|
||||||
|
|
||||||
CURLM *multi = curl_multi_init();
|
CURLM *multi = curl_multi_init();
|
||||||
if (multi == nullptr) {
|
if (multi == nullptr) {
|
||||||
|
@ -72,7 +72,7 @@ input_ffmpeg_supported(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static InputPlugin::InitResult
|
static InputPlugin::InitResult
|
||||||
input_ffmpeg_init(gcc_unused const config_param ¶m,
|
input_ffmpeg_init(gcc_unused const ConfigBlock &block,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
FfmpegInit();
|
FfmpegInit();
|
||||||
|
@ -221,7 +221,7 @@ NfsInputStream::OnNfsFileError(Error &&error)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static InputPlugin::InitResult
|
static InputPlugin::InitResult
|
||||||
input_nfs_init(const config_param &, Error &)
|
input_nfs_init(const ConfigBlock &, Error &)
|
||||||
{
|
{
|
||||||
nfs_init();
|
nfs_init();
|
||||||
return InputPlugin::InitResult::SUCCESS;
|
return InputPlugin::InitResult::SUCCESS;
|
||||||
|
@ -66,14 +66,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static InputPlugin::InitResult
|
static InputPlugin::InitResult
|
||||||
input_smbclient_init(gcc_unused const config_param ¶m, Error &error)
|
input_smbclient_init(gcc_unused const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!SmbclientInit(error))
|
if (!SmbclientInit(error))
|
||||||
return InputPlugin::InitResult::UNAVAILABLE;
|
return InputPlugin::InitResult::UNAVAILABLE;
|
||||||
|
|
||||||
// TODO: create one global SMBCCTX here?
|
// TODO: create one global SMBCCTX here?
|
||||||
|
|
||||||
// TODO: evaluate config_param, call smbc_setOption*()
|
// TODO: evaluate ConfigBlock, call smbc_setOption*()
|
||||||
|
|
||||||
return InputPlugin::InitResult::SUCCESS;
|
return InputPlugin::InitResult::SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@ Mixer *
|
|||||||
mixer_new(EventLoop &event_loop,
|
mixer_new(EventLoop &event_loop,
|
||||||
const MixerPlugin &plugin, AudioOutput &ao,
|
const MixerPlugin &plugin, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
Mixer *mixer = plugin.init(event_loop, ao, listener, param, error);
|
Mixer *mixer = plugin.init(event_loop, ao, listener, block, error);
|
||||||
|
|
||||||
assert(mixer == nullptr || mixer->IsPlugin(plugin));
|
assert(mixer == nullptr || mixer->IsPlugin(plugin));
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ class EventLoop;
|
|||||||
struct AudioOutput;
|
struct AudioOutput;
|
||||||
struct MixerPlugin;
|
struct MixerPlugin;
|
||||||
class MixerListener;
|
class MixerListener;
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
|
|
||||||
Mixer *
|
Mixer *
|
||||||
mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao,
|
mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef MPD_MIXER_PLUGIN_HXX
|
#ifndef MPD_MIXER_PLUGIN_HXX
|
||||||
#define MPD_MIXER_PLUGIN_HXX
|
#define MPD_MIXER_PLUGIN_HXX
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
struct AudioOutput;
|
struct AudioOutput;
|
||||||
class Mixer;
|
class Mixer;
|
||||||
class MixerListener;
|
class MixerListener;
|
||||||
@ -46,7 +46,7 @@ struct MixerPlugin {
|
|||||||
*/
|
*/
|
||||||
Mixer *(*init)(EventLoop &event_loop, AudioOutput &ao,
|
Mixer *(*init)(EventLoop &event_loop, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +82,7 @@ public:
|
|||||||
|
|
||||||
virtual ~AlsaMixer();
|
virtual ~AlsaMixer();
|
||||||
|
|
||||||
void Configure(const config_param ¶m);
|
void Configure(const ConfigBlock &block);
|
||||||
bool Setup(Error &error);
|
bool Setup(Error &error);
|
||||||
|
|
||||||
/* virtual methods from class Mixer */
|
/* virtual methods from class Mixer */
|
||||||
@ -162,24 +162,24 @@ alsa_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned mask)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
AlsaMixer::Configure(const config_param ¶m)
|
AlsaMixer::Configure(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
device = param.GetBlockValue("mixer_device",
|
device = block.GetBlockValue("mixer_device",
|
||||||
VOLUME_MIXER_ALSA_DEFAULT);
|
VOLUME_MIXER_ALSA_DEFAULT);
|
||||||
control = param.GetBlockValue("mixer_control",
|
control = block.GetBlockValue("mixer_control",
|
||||||
VOLUME_MIXER_ALSA_CONTROL_DEFAULT);
|
VOLUME_MIXER_ALSA_CONTROL_DEFAULT);
|
||||||
index = param.GetBlockValue("mixer_index",
|
index = block.GetBlockValue("mixer_index",
|
||||||
VOLUME_MIXER_ALSA_INDEX_DEFAULT);
|
VOLUME_MIXER_ALSA_INDEX_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Mixer *
|
static Mixer *
|
||||||
alsa_mixer_init(EventLoop &event_loop, gcc_unused AudioOutput &ao,
|
alsa_mixer_init(EventLoop &event_loop, gcc_unused AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
AlsaMixer *am = new AlsaMixer(event_loop, listener);
|
AlsaMixer *am = new AlsaMixer(event_loop, listener);
|
||||||
am->Configure(param);
|
am->Configure(block);
|
||||||
|
|
||||||
return am;
|
return am;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ static Mixer *
|
|||||||
null_mixer_init(gcc_unused EventLoop &event_loop,
|
null_mixer_init(gcc_unused EventLoop &event_loop,
|
||||||
gcc_unused AudioOutput &ao,
|
gcc_unused AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new NullMixer(listener);
|
return new NullMixer(listener);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "mixer/MixerInternal.hxx"
|
#include "mixer/MixerInternal.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "system/fd_util.h"
|
#include "system/fd_util.h"
|
||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
OssMixer(MixerListener &_listener)
|
OssMixer(MixerListener &_listener)
|
||||||
:Mixer(oss_mixer_plugin, _listener) {}
|
:Mixer(oss_mixer_plugin, _listener) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
/* virtual methods from class Mixer */
|
/* virtual methods from class Mixer */
|
||||||
virtual bool Open(Error &error) override;
|
virtual bool Open(Error &error) override;
|
||||||
@ -79,10 +79,10 @@ oss_find_mixer(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
OssMixer::Configure(const config_param ¶m, Error &error)
|
OssMixer::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
device = param.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT);
|
device = block.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT);
|
||||||
control = param.GetBlockValue("mixer_control");
|
control = block.GetBlockValue("mixer_control");
|
||||||
|
|
||||||
if (control != NULL) {
|
if (control != NULL) {
|
||||||
volume_control = oss_find_mixer(control);
|
volume_control = oss_find_mixer(control);
|
||||||
@ -100,12 +100,12 @@ OssMixer::Configure(const config_param ¶m, Error &error)
|
|||||||
static Mixer *
|
static Mixer *
|
||||||
oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao,
|
oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
OssMixer *om = new OssMixer(listener);
|
OssMixer *om = new OssMixer(listener);
|
||||||
|
|
||||||
if (!om->Configure(param, error)) {
|
if (!om->Configure(block, error)) {
|
||||||
delete om;
|
delete om;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ pulse_mixer_on_change(PulseMixer &pm,
|
|||||||
static Mixer *
|
static Mixer *
|
||||||
pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
PulseOutput &po = (PulseOutput &)ao;
|
PulseOutput &po = (PulseOutput &)ao;
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
static Mixer *
|
static Mixer *
|
||||||
roar_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
roar_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new RoarMixer((RoarOutput &)ao, listener);
|
return new RoarMixer((RoarOutput &)ao, listener);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "filter/FilterInternal.hxx"
|
#include "filter/FilterInternal.hxx"
|
||||||
#include "filter/plugins/VolumeFilterPlugin.hxx"
|
#include "filter/plugins/VolumeFilterPlugin.hxx"
|
||||||
#include "pcm/Volume.hxx"
|
#include "pcm/Volume.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -34,7 +34,7 @@
|
|||||||
static Filter *
|
static Filter *
|
||||||
CreateVolumeFilter()
|
CreateVolumeFilter()
|
||||||
{
|
{
|
||||||
return filter_new(&volume_filter_plugin, config_param(),
|
return filter_new(&volume_filter_plugin, ConfigBlock(),
|
||||||
IgnoreError());
|
IgnoreError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ static Mixer *
|
|||||||
software_mixer_init(gcc_unused EventLoop &event_loop,
|
software_mixer_init(gcc_unused EventLoop &event_loop,
|
||||||
gcc_unused AudioOutput &ao,
|
gcc_unused AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new SoftwareMixer(listener);
|
return new SoftwareMixer(listener);
|
||||||
|
@ -69,7 +69,7 @@ winmm_volume_encode(int volume)
|
|||||||
static Mixer *
|
static Mixer *
|
||||||
winmm_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
winmm_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new WinmmMixer((WinmmOutput &)ao, listener);
|
return new WinmmMixer((WinmmOutput &)ao, listener);
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
#include "NeighborPlugin.hxx"
|
#include "NeighborPlugin.hxx"
|
||||||
#include "Info.hxx"
|
#include "Info.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/Param.hxx"
|
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
|
#include "config/Block.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
NeighborGlue::Explorer::~Explorer()
|
NeighborGlue::Explorer::~Explorer()
|
||||||
@ -37,9 +37,9 @@ NeighborGlue::~NeighborGlue() {}
|
|||||||
|
|
||||||
static NeighborExplorer *
|
static NeighborExplorer *
|
||||||
CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener,
|
CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener,
|
||||||
const config_param ¶m, Error &error)
|
const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *plugin_name = param.GetBlockValue("plugin");
|
const char *plugin_name = block.GetBlockValue("plugin");
|
||||||
if (plugin_name == nullptr) {
|
if (plugin_name == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"Missing \"plugin\" configuration");
|
"Missing \"plugin\" configuration");
|
||||||
@ -53,18 +53,18 @@ CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugin->create(loop, listener, param, error);
|
return plugin->create(loop, listener, block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
NeighborGlue::Init(EventLoop &loop, NeighborListener &listener, Error &error)
|
NeighborGlue::Init(EventLoop &loop, NeighborListener &listener, Error &error)
|
||||||
{
|
{
|
||||||
for (const auto *param = config_get_param(ConfigOption::NEIGHBORS);
|
for (const auto *block = config_get_block(ConfigBlockOption::NEIGHBORS);
|
||||||
param != nullptr; param = param->next) {
|
block != nullptr; block = block->next) {
|
||||||
NeighborExplorer *explorer =
|
NeighborExplorer *explorer =
|
||||||
CreateNeighborExplorer(loop, listener, *param, error);
|
CreateNeighborExplorer(loop, listener, *block, error);
|
||||||
if (explorer == nullptr) {
|
if (explorer == nullptr) {
|
||||||
error.FormatPrefix("Line %i: ", param->line);
|
error.FormatPrefix("Line %i: ", block->line);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#ifndef MPD_NEIGHBOR_PLUGIN_HXX
|
#ifndef MPD_NEIGHBOR_PLUGIN_HXX
|
||||||
#define MPD_NEIGHBOR_PLUGIN_HXX
|
#define MPD_NEIGHBOR_PLUGIN_HXX
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
class Error;
|
class Error;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
class NeighborListener;
|
class NeighborListener;
|
||||||
@ -33,7 +33,7 @@ struct NeighborPlugin {
|
|||||||
* Allocates and configures a #NeighborExplorer instance.
|
* Allocates and configures a #NeighborExplorer instance.
|
||||||
*/
|
*/
|
||||||
NeighborExplorer *(*create)(EventLoop &loop, NeighborListener &listener,
|
NeighborExplorer *(*create)(EventLoop &loop, NeighborListener &listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ SmbclientNeighborExplorer::ThreadFunc(void *ctx)
|
|||||||
static NeighborExplorer *
|
static NeighborExplorer *
|
||||||
smbclient_neighbor_create(gcc_unused EventLoop &loop,
|
smbclient_neighbor_create(gcc_unused EventLoop &loop,
|
||||||
NeighborListener &listener,
|
NeighborListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
if (!SmbclientInit(error))
|
if (!SmbclientInit(error))
|
||||||
|
@ -127,7 +127,7 @@ UpnpNeighborExplorer::LostUPnP(const ContentDirectoryService &service)
|
|||||||
static NeighborExplorer *
|
static NeighborExplorer *
|
||||||
upnp_neighbor_create(gcc_unused EventLoop &loop,
|
upnp_neighbor_create(gcc_unused EventLoop &loop,
|
||||||
NeighborListener &listener,
|
NeighborListener &listener,
|
||||||
gcc_unused const config_param ¶m,
|
gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
return new UpnpNeighborExplorer(listener);
|
return new UpnpNeighborExplorer(listener);
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "filter/plugins/ChainFilterPlugin.hxx"
|
#include "filter/plugins/ChainFilterPlugin.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
|
#include "config/Block.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -95,15 +96,15 @@ audio_output_detect(Error &error)
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static MixerType
|
static MixerType
|
||||||
audio_output_mixer_type(const config_param ¶m)
|
audio_output_mixer_type(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
/* read the local "mixer_type" setting */
|
/* read the local "mixer_type" setting */
|
||||||
const char *p = param.GetBlockValue("mixer_type");
|
const char *p = block.GetBlockValue("mixer_type");
|
||||||
if (p != nullptr)
|
if (p != nullptr)
|
||||||
return mixer_type_parse(p);
|
return mixer_type_parse(p);
|
||||||
|
|
||||||
/* try the local "mixer_enabled" setting next (deprecated) */
|
/* try the local "mixer_enabled" setting next (deprecated) */
|
||||||
if (!param.GetBlockValue("mixer_enabled", true))
|
if (!block.GetBlockValue("mixer_enabled", true))
|
||||||
return MixerType::NONE;
|
return MixerType::NONE;
|
||||||
|
|
||||||
/* fall back to the global "mixer_type" setting (also
|
/* fall back to the global "mixer_type" setting (also
|
||||||
@ -114,7 +115,7 @@ audio_output_mixer_type(const config_param ¶m)
|
|||||||
|
|
||||||
static Mixer *
|
static Mixer *
|
||||||
audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
|
audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
const MixerPlugin *plugin,
|
const MixerPlugin *plugin,
|
||||||
Filter &filter_chain,
|
Filter &filter_chain,
|
||||||
MixerListener &listener,
|
MixerListener &listener,
|
||||||
@ -122,26 +123,26 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
|
|||||||
{
|
{
|
||||||
Mixer *mixer;
|
Mixer *mixer;
|
||||||
|
|
||||||
switch (audio_output_mixer_type(param)) {
|
switch (audio_output_mixer_type(block)) {
|
||||||
case MixerType::NONE:
|
case MixerType::NONE:
|
||||||
case MixerType::UNKNOWN:
|
case MixerType::UNKNOWN:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
case MixerType::NULL_:
|
case MixerType::NULL_:
|
||||||
return mixer_new(event_loop, null_mixer_plugin, ao, listener,
|
return mixer_new(event_loop, null_mixer_plugin, ao, listener,
|
||||||
param, error);
|
block, error);
|
||||||
|
|
||||||
case MixerType::HARDWARE:
|
case MixerType::HARDWARE:
|
||||||
if (plugin == nullptr)
|
if (plugin == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return mixer_new(event_loop, *plugin, ao, listener,
|
return mixer_new(event_loop, *plugin, ao, listener,
|
||||||
param, error);
|
block, error);
|
||||||
|
|
||||||
case MixerType::SOFTWARE:
|
case MixerType::SOFTWARE:
|
||||||
mixer = mixer_new(event_loop, software_mixer_plugin, ao,
|
mixer = mixer_new(event_loop, software_mixer_plugin, ao,
|
||||||
listener,
|
listener,
|
||||||
config_param(),
|
ConfigBlock(),
|
||||||
IgnoreError());
|
IgnoreError());
|
||||||
assert(mixer != nullptr);
|
assert(mixer != nullptr);
|
||||||
|
|
||||||
@ -155,17 +156,17 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioOutput::Configure(const config_param ¶m, Error &error)
|
AudioOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!param.IsNull()) {
|
if (!block.IsNull()) {
|
||||||
name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
|
name = block.GetBlockValue(AUDIO_OUTPUT_NAME);
|
||||||
if (name == nullptr) {
|
if (name == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"Missing \"name\" configuration");
|
"Missing \"name\" configuration");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT);
|
const char *p = block.GetBlockValue(AUDIO_OUTPUT_FORMAT);
|
||||||
if (p != nullptr) {
|
if (p != nullptr) {
|
||||||
bool success =
|
bool success =
|
||||||
audio_format_parse(config_audio_format,
|
audio_format_parse(config_audio_format,
|
||||||
@ -180,9 +181,9 @@ AudioOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
config_audio_format.Clear();
|
config_audio_format.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
tags = param.GetBlockValue("tags", true);
|
tags = block.GetBlockValue("tags", true);
|
||||||
always_on = param.GetBlockValue("always_on", false);
|
always_on = block.GetBlockValue("always_on", false);
|
||||||
enabled = param.GetBlockValue("enabled", true);
|
enabled = block.GetBlockValue("enabled", true);
|
||||||
|
|
||||||
/* set up the filter chain */
|
/* set up the filter chain */
|
||||||
|
|
||||||
@ -193,7 +194,7 @@ AudioOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
if (config_get_bool(ConfigOption::VOLUME_NORMALIZATION, false)) {
|
if (config_get_bool(ConfigOption::VOLUME_NORMALIZATION, false)) {
|
||||||
Filter *normalize_filter =
|
Filter *normalize_filter =
|
||||||
filter_new(&normalize_filter_plugin, config_param(),
|
filter_new(&normalize_filter_plugin, ConfigBlock(),
|
||||||
IgnoreError());
|
IgnoreError());
|
||||||
assert(normalize_filter != nullptr);
|
assert(normalize_filter != nullptr);
|
||||||
|
|
||||||
@ -203,7 +204,7 @@ AudioOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
Error filter_error;
|
Error filter_error;
|
||||||
filter_chain_parse(*filter,
|
filter_chain_parse(*filter,
|
||||||
param.GetBlockValue(AUDIO_FILTERS, ""),
|
block.GetBlockValue(AUDIO_FILTERS, ""),
|
||||||
filter_error);
|
filter_error);
|
||||||
|
|
||||||
// It's not really fatal - Part of the filter chain has been set up already
|
// It's not really fatal - Part of the filter chain has been set up already
|
||||||
@ -221,24 +222,24 @@ AudioOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
static bool
|
static bool
|
||||||
audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
|
audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
|
||||||
MixerListener &mixer_listener,
|
MixerListener &mixer_listener,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* create the replay_gain filter */
|
/* create the replay_gain filter */
|
||||||
|
|
||||||
const char *replay_gain_handler =
|
const char *replay_gain_handler =
|
||||||
param.GetBlockValue("replay_gain_handler", "software");
|
block.GetBlockValue("replay_gain_handler", "software");
|
||||||
|
|
||||||
if (strcmp(replay_gain_handler, "none") != 0) {
|
if (strcmp(replay_gain_handler, "none") != 0) {
|
||||||
ao.replay_gain_filter = filter_new(&replay_gain_filter_plugin,
|
ao.replay_gain_filter = filter_new(&replay_gain_filter_plugin,
|
||||||
param, IgnoreError());
|
block, IgnoreError());
|
||||||
assert(ao.replay_gain_filter != nullptr);
|
assert(ao.replay_gain_filter != nullptr);
|
||||||
|
|
||||||
ao.replay_gain_serial = 0;
|
ao.replay_gain_serial = 0;
|
||||||
|
|
||||||
ao.other_replay_gain_filter = filter_new(&replay_gain_filter_plugin,
|
ao.other_replay_gain_filter = filter_new(&replay_gain_filter_plugin,
|
||||||
param,
|
block,
|
||||||
IgnoreError());
|
IgnoreError());
|
||||||
assert(ao.other_replay_gain_filter != nullptr);
|
assert(ao.other_replay_gain_filter != nullptr);
|
||||||
|
|
||||||
@ -251,7 +252,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
|
|||||||
/* set up the mixer */
|
/* set up the mixer */
|
||||||
|
|
||||||
Error mixer_error;
|
Error mixer_error;
|
||||||
ao.mixer = audio_output_load_mixer(event_loop, ao, param,
|
ao.mixer = audio_output_load_mixer(event_loop, ao, block,
|
||||||
ao.plugin.mixer_plugin,
|
ao.plugin.mixer_plugin,
|
||||||
*ao.filter,
|
*ao.filter,
|
||||||
mixer_listener,
|
mixer_listener,
|
||||||
@ -279,7 +280,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
|
|||||||
|
|
||||||
/* the "convert" filter must be the last one in the chain */
|
/* the "convert" filter must be the last one in the chain */
|
||||||
|
|
||||||
ao.convert_filter = filter_new(&convert_filter_plugin, config_param(),
|
ao.convert_filter = filter_new(&convert_filter_plugin, ConfigBlock(),
|
||||||
IgnoreError());
|
IgnoreError());
|
||||||
assert(ao.convert_filter != nullptr);
|
assert(ao.convert_filter != nullptr);
|
||||||
|
|
||||||
@ -289,17 +290,17 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioOutput *
|
AudioOutput *
|
||||||
audio_output_new(EventLoop &event_loop, const config_param ¶m,
|
audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
|
||||||
MixerListener &mixer_listener,
|
MixerListener &mixer_listener,
|
||||||
PlayerControl &pc,
|
PlayerControl &pc,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
const AudioOutputPlugin *plugin;
|
const AudioOutputPlugin *plugin;
|
||||||
|
|
||||||
if (!param.IsNull()) {
|
if (!block.IsNull()) {
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
p = param.GetBlockValue(AUDIO_OUTPUT_TYPE);
|
p = block.GetBlockValue(AUDIO_OUTPUT_TYPE);
|
||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"Missing \"type\" configuration");
|
"Missing \"type\" configuration");
|
||||||
@ -325,12 +326,12 @@ audio_output_new(EventLoop &event_loop, const config_param ¶m,
|
|||||||
plugin->name);
|
plugin->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioOutput *ao = ao_plugin_init(plugin, param, error);
|
AudioOutput *ao = ao_plugin_init(plugin, block, error);
|
||||||
if (ao == nullptr)
|
if (ao == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!audio_output_setup(event_loop, *ao, mixer_listener,
|
if (!audio_output_setup(event_loop, *ao, mixer_listener,
|
||||||
param, error)) {
|
block, error)) {
|
||||||
ao_plugin_finish(ao);
|
ao_plugin_finish(ao);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ class EventLoop;
|
|||||||
class Mixer;
|
class Mixer;
|
||||||
class MixerListener;
|
class MixerListener;
|
||||||
struct MusicChunk;
|
struct MusicChunk;
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
struct PlayerControl;
|
struct PlayerControl;
|
||||||
struct AudioOutputPlugin;
|
struct AudioOutputPlugin;
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ struct AudioOutput {
|
|||||||
AudioOutput(const AudioOutputPlugin &_plugin);
|
AudioOutput(const AudioOutputPlugin &_plugin);
|
||||||
~AudioOutput();
|
~AudioOutput();
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
void StartThread();
|
void StartThread();
|
||||||
void StopThread();
|
void StopThread();
|
||||||
@ -430,7 +430,7 @@ private:
|
|||||||
extern struct notify audio_output_client_notify;
|
extern struct notify audio_output_client_notify;
|
||||||
|
|
||||||
AudioOutput *
|
AudioOutput *
|
||||||
audio_output_new(EventLoop &event_loop, const config_param ¶m,
|
audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
|
||||||
MixerListener &mixer_listener,
|
MixerListener &mixer_listener,
|
||||||
PlayerControl &pc,
|
PlayerControl &pc,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "system/FatalError.hxx"
|
#include "system/FatalError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "notify.hxx"
|
#include "notify.hxx"
|
||||||
@ -53,16 +53,16 @@ MultipleOutputs::~MultipleOutputs()
|
|||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
|
LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
|
||||||
PlayerControl &pc, const config_param ¶m)
|
PlayerControl &pc, const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
Error error;
|
Error error;
|
||||||
AudioOutput *output = audio_output_new(event_loop, param,
|
AudioOutput *output = audio_output_new(event_loop, block,
|
||||||
mixer_listener,
|
mixer_listener,
|
||||||
pc, error);
|
pc, error);
|
||||||
if (output == nullptr) {
|
if (output == nullptr) {
|
||||||
if (param.line > 0)
|
if (block.line > 0)
|
||||||
FormatFatalError("line %i: %s",
|
FormatFatalError("line %i: %s",
|
||||||
param.line,
|
block.line,
|
||||||
error.GetMessage());
|
error.GetMessage());
|
||||||
else
|
else
|
||||||
FatalError(error);
|
FatalError(error);
|
||||||
@ -74,7 +74,7 @@ LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
|
|||||||
void
|
void
|
||||||
MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
|
MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
|
||||||
{
|
{
|
||||||
for (const auto *param = config_get_param(ConfigOption::AUDIO_OUTPUT);
|
for (const auto *param = config_get_block(ConfigBlockOption::AUDIO_OUTPUT);
|
||||||
param != nullptr; param = param->next) {
|
param != nullptr; param = param->next) {
|
||||||
auto output = LoadOutput(event_loop, mixer_listener,
|
auto output = LoadOutput(event_loop, mixer_listener,
|
||||||
pc, *param);
|
pc, *param);
|
||||||
@ -87,7 +87,7 @@ MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
|
|||||||
|
|
||||||
if (outputs.empty()) {
|
if (outputs.empty()) {
|
||||||
/* auto-detect device */
|
/* auto-detect device */
|
||||||
const config_param empty;
|
const ConfigBlock empty;
|
||||||
auto output = LoadOutput(event_loop, mixer_listener,
|
auto output = LoadOutput(event_loop, mixer_listener,
|
||||||
pc, empty);
|
pc, empty);
|
||||||
outputs.push_back(output);
|
outputs.push_back(output);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include "Internal.hxx"
|
#include "Internal.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Block.hxx"
|
||||||
|
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
|
|
||||||
AudioOutput *
|
AudioOutput *
|
||||||
ao_plugin_init(const AudioOutputPlugin *plugin,
|
ao_plugin_init(const AudioOutputPlugin *plugin,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
assert(plugin != nullptr);
|
assert(plugin != nullptr);
|
||||||
assert(plugin->init != nullptr);
|
assert(plugin->init != nullptr);
|
||||||
|
|
||||||
return plugin->init(param, error);
|
return plugin->init(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct config_param;
|
struct ConfigBlock;
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
struct AudioOutput;
|
struct AudioOutput;
|
||||||
@ -55,8 +55,7 @@ struct AudioOutputPlugin {
|
|||||||
* @return nullptr on error, or an opaque pointer to the plugin's
|
* @return nullptr on error, or an opaque pointer to the plugin's
|
||||||
* data
|
* data
|
||||||
*/
|
*/
|
||||||
AudioOutput *(*init)(const config_param ¶m,
|
AudioOutput *(*init)(const ConfigBlock &block, Error &error);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free resources allocated by this device.
|
* Free resources allocated by this device.
|
||||||
@ -162,7 +161,7 @@ ao_plugin_test_default_device(const AudioOutputPlugin *plugin)
|
|||||||
gcc_malloc
|
gcc_malloc
|
||||||
AudioOutput *
|
AudioOutput *
|
||||||
ao_plugin_init(const AudioOutputPlugin *plugin,
|
ao_plugin_init(const AudioOutputPlugin *plugin,
|
||||||
const config_param ¶m,
|
const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -22,14 +22,16 @@
|
|||||||
|
|
||||||
#include "util/Cast.hxx"
|
#include "util/Cast.hxx"
|
||||||
|
|
||||||
|
struct ConfigBlock;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct AudioOutputWrapper {
|
struct AudioOutputWrapper {
|
||||||
static T &Cast(AudioOutput &ao) {
|
static T &Cast(AudioOutput &ao) {
|
||||||
return ContainerCast(ao, &T::base);
|
return ContainerCast(ao, &T::base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *Init(const config_param ¶m, Error &error) {
|
static AudioOutput *Init(const ConfigBlock &block, Error &error) {
|
||||||
T *t = T::Create(param, error);
|
T *t = T::Create(block, error);
|
||||||
return t != nullptr
|
return t != nullptr
|
||||||
? &t->base
|
? &t->base
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
@ -142,8 +142,8 @@ struct AlsaOutput {
|
|||||||
return device.empty() ? default_device : device.c_str();
|
return device.empty() ? default_device : device.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
static AlsaOutput *Create(const config_param ¶m, Error &error);
|
static AlsaOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Enable(Error &error);
|
bool Enable(Error &error);
|
||||||
void Disable();
|
void Disable();
|
||||||
@ -175,35 +175,35 @@ private:
|
|||||||
static constexpr Domain alsa_output_domain("alsa_output");
|
static constexpr Domain alsa_output_domain("alsa_output");
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
AlsaOutput::Configure(const config_param ¶m, Error &error)
|
AlsaOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!base.Configure(param, error))
|
if (!base.Configure(block, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
device = param.GetBlockValue("device", "");
|
device = block.GetBlockValue("device", "");
|
||||||
|
|
||||||
use_mmap = param.GetBlockValue("use_mmap", false);
|
use_mmap = block.GetBlockValue("use_mmap", false);
|
||||||
|
|
||||||
dop = param.GetBlockValue("dop", false) ||
|
dop = block.GetBlockValue("dop", false) ||
|
||||||
/* legacy name from MPD 0.18 and older: */
|
/* legacy name from MPD 0.18 and older: */
|
||||||
param.GetBlockValue("dsd_usb", false);
|
block.GetBlockValue("dsd_usb", false);
|
||||||
|
|
||||||
buffer_time = param.GetBlockValue("buffer_time",
|
buffer_time = block.GetBlockValue("buffer_time",
|
||||||
MPD_ALSA_BUFFER_TIME_US);
|
MPD_ALSA_BUFFER_TIME_US);
|
||||||
period_time = param.GetBlockValue("period_time", 0u);
|
period_time = block.GetBlockValue("period_time", 0u);
|
||||||
|
|
||||||
#ifdef SND_PCM_NO_AUTO_RESAMPLE
|
#ifdef SND_PCM_NO_AUTO_RESAMPLE
|
||||||
if (!param.GetBlockValue("auto_resample", true))
|
if (!block.GetBlockValue("auto_resample", true))
|
||||||
mode |= SND_PCM_NO_AUTO_RESAMPLE;
|
mode |= SND_PCM_NO_AUTO_RESAMPLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SND_PCM_NO_AUTO_CHANNELS
|
#ifdef SND_PCM_NO_AUTO_CHANNELS
|
||||||
if (!param.GetBlockValue("auto_channels", true))
|
if (!block.GetBlockValue("auto_channels", true))
|
||||||
mode |= SND_PCM_NO_AUTO_CHANNELS;
|
mode |= SND_PCM_NO_AUTO_CHANNELS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SND_PCM_NO_AUTO_FORMAT
|
#ifdef SND_PCM_NO_AUTO_FORMAT
|
||||||
if (!param.GetBlockValue("auto_format", true))
|
if (!block.GetBlockValue("auto_format", true))
|
||||||
mode |= SND_PCM_NO_AUTO_FORMAT;
|
mode |= SND_PCM_NO_AUTO_FORMAT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -211,11 +211,11 @@ AlsaOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline AlsaOutput *
|
inline AlsaOutput *
|
||||||
AlsaOutput::Create(const config_param ¶m, Error &error)
|
AlsaOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
AlsaOutput *ad = new AlsaOutput();
|
AlsaOutput *ad = new AlsaOutput();
|
||||||
|
|
||||||
if (!ad->Configure(param, error)) {
|
if (!ad->Configure(block, error)) {
|
||||||
delete ad;
|
delete ad;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ struct AoOutput {
|
|||||||
AoOutput()
|
AoOutput()
|
||||||
:base(ao_output_plugin) {}
|
:base(ao_output_plugin) {}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error) {
|
bool Initialize(const ConfigBlock &block, Error &error) {
|
||||||
return base.Configure(param, error);
|
return base.Configure(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain ao_output_domain("ao_output");
|
static constexpr Domain ao_output_domain("ao_output");
|
||||||
@ -90,20 +90,20 @@ ao_output_error(Error &error_r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
AoOutput::Configure(const config_param ¶m, Error &error)
|
AoOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
options = nullptr;
|
options = nullptr;
|
||||||
|
|
||||||
write_size = param.GetBlockValue("write_size", 1024u);
|
write_size = block.GetBlockValue("write_size", 1024u);
|
||||||
|
|
||||||
if (ao_output_ref == 0) {
|
if (ao_output_ref == 0) {
|
||||||
ao_initialize();
|
ao_initialize();
|
||||||
}
|
}
|
||||||
ao_output_ref++;
|
ao_output_ref++;
|
||||||
|
|
||||||
value = param.GetBlockValue("driver", "default");
|
value = block.GetBlockValue("driver", "default");
|
||||||
if (0 == strcmp(value, "default"))
|
if (0 == strcmp(value, "default"))
|
||||||
driver = ao_default_driver_id();
|
driver = ao_default_driver_id();
|
||||||
else
|
else
|
||||||
@ -123,9 +123,9 @@ AoOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n",
|
FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n",
|
||||||
ai->short_name, param.GetBlockValue("name", nullptr));
|
ai->short_name, block.GetBlockValue("name", nullptr));
|
||||||
|
|
||||||
value = param.GetBlockValue("options", nullptr);
|
value = block.GetBlockValue("options", nullptr);
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
for (const auto &i : SplitString(value, ';')) {
|
for (const auto &i : SplitString(value, ';')) {
|
||||||
const DivideString ss(i.c_str(), '=', true);
|
const DivideString ss(i.c_str(), '=', true);
|
||||||
@ -145,16 +145,16 @@ AoOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
ao_output_init(const config_param ¶m, Error &error)
|
ao_output_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
AoOutput *ad = new AoOutput();
|
AoOutput *ad = new AoOutput();
|
||||||
|
|
||||||
if (!ad->Initialize(param, error)) {
|
if (!ad->Initialize(block, error)) {
|
||||||
delete ad;
|
delete ad;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ad->Configure(param, error)) {
|
if (!ad->Configure(block, error)) {
|
||||||
delete ad;
|
delete ad;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ struct FifoOutput {
|
|||||||
path(AllocatedPath::Null()), input(-1), output(-1),
|
path(AllocatedPath::Null()), input(-1), output(-1),
|
||||||
created(false) {}
|
created(false) {}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error) {
|
bool Initialize(const ConfigBlock &block, Error &error) {
|
||||||
return base.Configure(param, error);
|
return base.Configure(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Create(Error &error);
|
bool Create(Error &error);
|
||||||
@ -169,11 +169,11 @@ fifo_open(FifoOutput *fd, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
fifo_output_init(const config_param ¶m, Error &error)
|
fifo_output_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
FifoOutput *fd = new FifoOutput();
|
FifoOutput *fd = new FifoOutput();
|
||||||
|
|
||||||
fd->path = param.GetBlockPath("path", error);
|
fd->path = block.GetBlockPath("path", error);
|
||||||
if (fd->path.IsNull()) {
|
if (fd->path.IsNull()) {
|
||||||
delete fd;
|
delete fd;
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ fifo_output_init(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
fd->path_utf8 = fd->path.ToUTF8();
|
fd->path_utf8 = fd->path.ToUTF8();
|
||||||
|
|
||||||
if (!fd->Initialize(param, error)) {
|
if (!fd->Initialize(block, error)) {
|
||||||
delete fd;
|
delete fd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ struct JackOutput {
|
|||||||
JackOutput()
|
JackOutput()
|
||||||
:base(jack_output_plugin) {}
|
:base(jack_output_plugin) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Connect(Error &error);
|
bool Connect(Error &error);
|
||||||
|
|
||||||
@ -376,14 +376,14 @@ parse_port_list(const char *source, std::string dest[], Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JackOutput::Configure(const config_param ¶m, Error &error)
|
JackOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!base.Configure(param, error))
|
if (!base.Configure(block, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
options = JackNullOption;
|
options = JackNullOption;
|
||||||
|
|
||||||
name = param.GetBlockValue("client_name", nullptr);
|
name = block.GetBlockValue("client_name", nullptr);
|
||||||
if (name != nullptr)
|
if (name != nullptr)
|
||||||
options = jack_options_t(options | JackUseExactName);
|
options = jack_options_t(options | JackUseExactName);
|
||||||
else
|
else
|
||||||
@ -391,30 +391,30 @@ JackOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
care about the JackUseExactName option */
|
care about the JackUseExactName option */
|
||||||
name = "Music Player Daemon";
|
name = "Music Player Daemon";
|
||||||
|
|
||||||
server_name = param.GetBlockValue("server_name", nullptr);
|
server_name = block.GetBlockValue("server_name", nullptr);
|
||||||
if (server_name != nullptr)
|
if (server_name != nullptr)
|
||||||
options = jack_options_t(options | JackServerName);
|
options = jack_options_t(options | JackServerName);
|
||||||
|
|
||||||
if (!param.GetBlockValue("autostart", false))
|
if (!block.GetBlockValue("autostart", false))
|
||||||
options = jack_options_t(options | JackNoStartServer);
|
options = jack_options_t(options | JackNoStartServer);
|
||||||
|
|
||||||
/* configure the source ports */
|
/* configure the source ports */
|
||||||
|
|
||||||
const char *value = param.GetBlockValue("source_ports", "left,right");
|
const char *value = block.GetBlockValue("source_ports", "left,right");
|
||||||
num_source_ports = parse_port_list(value, source_ports, error);
|
num_source_ports = parse_port_list(value, source_ports, error);
|
||||||
if (num_source_ports == 0)
|
if (num_source_ports == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* configure the destination ports */
|
/* configure the destination ports */
|
||||||
|
|
||||||
value = param.GetBlockValue("destination_ports", nullptr);
|
value = block.GetBlockValue("destination_ports", nullptr);
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
/* compatibility with MPD < 0.16 */
|
/* compatibility with MPD < 0.16 */
|
||||||
value = param.GetBlockValue("ports", nullptr);
|
value = block.GetBlockValue("ports", nullptr);
|
||||||
if (value != nullptr)
|
if (value != nullptr)
|
||||||
FormatWarning(jack_output_domain,
|
FormatWarning(jack_output_domain,
|
||||||
"deprecated option 'ports' in line %d",
|
"deprecated option 'ports' in line %d",
|
||||||
param.line);
|
block.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
@ -432,9 +432,9 @@ JackOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
"number of source ports (%u) mismatches the "
|
"number of source ports (%u) mismatches the "
|
||||||
"number of destination ports (%u) in line %d",
|
"number of destination ports (%u) in line %d",
|
||||||
num_source_ports, num_destination_ports,
|
num_source_ports, num_destination_ports,
|
||||||
param.line);
|
block.line);
|
||||||
|
|
||||||
ringbuffer_size = param.GetBlockValue("ringbuffer_size", 32768u);
|
ringbuffer_size = block.GetBlockValue("ringbuffer_size", 32768u);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -463,11 +463,11 @@ JackOutput::Disable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
mpd_jack_init(const config_param ¶m, Error &error)
|
mpd_jack_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
JackOutput *jd = new JackOutput();
|
JackOutput *jd = new JackOutput();
|
||||||
|
|
||||||
if (!jd->Configure(param, error)) {
|
if (!jd->Configure(block, error)) {
|
||||||
delete jd;
|
delete jd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,11 @@ public:
|
|||||||
NullOutput()
|
NullOutput()
|
||||||
:base(null_output_plugin) {}
|
:base(null_output_plugin) {}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error) {
|
bool Initialize(const ConfigBlock &block, Error &error) {
|
||||||
return base.Configure(param, error);
|
return base.Configure(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NullOutput *Create(const config_param ¶m, Error &error);
|
static NullOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Open(AudioFormat &audio_format, gcc_unused Error &error) {
|
bool Open(AudioFormat &audio_format, gcc_unused Error &error) {
|
||||||
if (sync)
|
if (sync)
|
||||||
@ -78,16 +78,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline NullOutput *
|
inline NullOutput *
|
||||||
NullOutput::Create(const config_param ¶m, Error &error)
|
NullOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
NullOutput *nd = new NullOutput();
|
NullOutput *nd = new NullOutput();
|
||||||
|
|
||||||
if (!nd->Initialize(param, error)) {
|
if (!nd->Initialize(block, error)) {
|
||||||
delete nd;
|
delete nd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nd->sync = param.GetBlockValue("sync", true);
|
nd->sync = block.GetBlockValue("sync", true);
|
||||||
|
|
||||||
return nd;
|
return nd;
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ osx_output_test_default_device(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
osx_output_configure(OSXOutput *oo, const config_param ¶m)
|
osx_output_configure(OSXOutput *oo, const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
const char *device = param.GetBlockValue("device");
|
const char *device = block.GetBlockValue("device");
|
||||||
|
|
||||||
if (device == nullptr || 0 == strcmp(device, "default")) {
|
if (device == nullptr || 0 == strcmp(device, "default")) {
|
||||||
oo->component_subtype = kAudioUnitSubType_DefaultOutput;
|
oo->component_subtype = kAudioUnitSubType_DefaultOutput;
|
||||||
@ -81,15 +81,15 @@ osx_output_configure(OSXOutput *oo, const config_param ¶m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
osx_output_init(const config_param ¶m, Error &error)
|
osx_output_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
OSXOutput *oo = new OSXOutput();
|
OSXOutput *oo = new OSXOutput();
|
||||||
if (!oo->base.Configure(param, error)) {
|
if (!oo->base.Configure(block, error)) {
|
||||||
delete oo;
|
delete oo;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
osx_output_configure(oo, param);
|
osx_output_configure(oo, block);
|
||||||
|
|
||||||
return &oo->base;
|
return &oo->base;
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,9 @@ class OpenALOutput {
|
|||||||
OpenALOutput()
|
OpenALOutput()
|
||||||
:base(openal_output_plugin) {}
|
:base(openal_output_plugin) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
static OpenALOutput *Create(const config_param ¶m, Error &error);
|
static OpenALOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Open(AudioFormat &audio_format, Error &error);
|
bool Open(AudioFormat &audio_format, Error &error);
|
||||||
|
|
||||||
@ -150,12 +150,12 @@ OpenALOutput::SetupContext(Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
OpenALOutput::Configure(const config_param ¶m, Error &error)
|
OpenALOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!base.Configure(param, error))
|
if (!base.Configure(block, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
device_name = param.GetBlockValue("device");
|
device_name = block.GetBlockValue("device");
|
||||||
if (device_name == nullptr)
|
if (device_name == nullptr)
|
||||||
device_name = alcGetString(nullptr,
|
device_name = alcGetString(nullptr,
|
||||||
ALC_DEFAULT_DEVICE_SPECIFIER);
|
ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||||
@ -164,11 +164,11 @@ OpenALOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline OpenALOutput *
|
inline OpenALOutput *
|
||||||
OpenALOutput::Create(const config_param ¶m, Error &error)
|
OpenALOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
OpenALOutput *oo = new OpenALOutput();
|
OpenALOutput *oo = new OpenALOutput();
|
||||||
|
|
||||||
if (!oo->Configure(param, error)) {
|
if (!oo->Configure(block, error)) {
|
||||||
delete oo;
|
delete oo;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -87,11 +87,11 @@ public:
|
|||||||
:base(oss_output_plugin),
|
:base(oss_output_plugin),
|
||||||
fd(-1), device(_device) {}
|
fd(-1), device(_device) {}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error_r) {
|
bool Initialize(const ConfigBlock &block, Error &error_r) {
|
||||||
return base.Configure(param, error_r);
|
return base.Configure(block, error_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static OssOutput *Create(const config_param ¶m, Error &error);
|
static OssOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
bool Enable(gcc_unused Error &error) {
|
bool Enable(gcc_unused Error &error) {
|
||||||
@ -192,7 +192,7 @@ oss_open_default(Error &error)
|
|||||||
int err[ARRAY_SIZE(default_devices)];
|
int err[ARRAY_SIZE(default_devices)];
|
||||||
enum oss_stat ret[ARRAY_SIZE(default_devices)];
|
enum oss_stat ret[ARRAY_SIZE(default_devices)];
|
||||||
|
|
||||||
const config_param empty;
|
const ConfigBlock empty;
|
||||||
for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) {
|
for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) {
|
||||||
ret[i] = oss_stat_device(default_devices[i], &err[i]);
|
ret[i] = oss_stat_device(default_devices[i], &err[i]);
|
||||||
if (ret[i] == OSS_STAT_NO_ERROR) {
|
if (ret[i] == OSS_STAT_NO_ERROR) {
|
||||||
@ -236,12 +236,12 @@ oss_open_default(Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline OssOutput *
|
inline OssOutput *
|
||||||
OssOutput::Create(const config_param ¶m, Error &error)
|
OssOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
const char *device = param.GetBlockValue("device");
|
const char *device = block.GetBlockValue("device");
|
||||||
if (device != nullptr) {
|
if (device != nullptr) {
|
||||||
OssOutput *od = new OssOutput();
|
OssOutput *od = new OssOutput();
|
||||||
if (!od->Initialize(param, error)) {
|
if (!od->Initialize(block, error)) {
|
||||||
delete od;
|
delete od;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,10 @@ class PipeOutput {
|
|||||||
PipeOutput()
|
PipeOutput()
|
||||||
:base(pipe_output_plugin) {}
|
:base(pipe_output_plugin) {}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static PipeOutput *Create(const config_param ¶m, Error &error);
|
static PipeOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Open(AudioFormat &audio_format, Error &error);
|
bool Open(AudioFormat &audio_format, Error &error);
|
||||||
|
|
||||||
@ -58,12 +58,12 @@ public:
|
|||||||
static constexpr Domain pipe_output_domain("pipe_output");
|
static constexpr Domain pipe_output_domain("pipe_output");
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
PipeOutput::Configure(const config_param ¶m, Error &error)
|
PipeOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!base.Configure(param, error))
|
if (!base.Configure(block, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cmd = param.GetBlockValue("command", "");
|
cmd = block.GetBlockValue("command", "");
|
||||||
if (cmd.empty()) {
|
if (cmd.empty()) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"No \"command\" parameter specified");
|
"No \"command\" parameter specified");
|
||||||
@ -74,11 +74,11 @@ PipeOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline PipeOutput *
|
inline PipeOutput *
|
||||||
PipeOutput::Create(const config_param ¶m, Error &error)
|
PipeOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
PipeOutput *po = new PipeOutput();
|
PipeOutput *po = new PipeOutput();
|
||||||
|
|
||||||
if (!po->Configure(param, error)) {
|
if (!po->Configure(block, error)) {
|
||||||
delete po;
|
delete po;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -98,8 +98,8 @@ public:
|
|||||||
gcc_const
|
gcc_const
|
||||||
static bool TestDefaultDevice();
|
static bool TestDefaultDevice();
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
static PulseOutput *Create(const config_param ¶m, Error &error);
|
static PulseOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Enable(Error &error);
|
bool Enable(Error &error);
|
||||||
void Disable();
|
void Disable();
|
||||||
@ -430,26 +430,26 @@ PulseOutput::SetupContext(Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
PulseOutput::Configure(const config_param ¶m, Error &error)
|
PulseOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
if (!base.Configure(param, error))
|
if (!base.Configure(block, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
name = param.GetBlockValue("name", "mpd_pulse");
|
name = block.GetBlockValue("name", "mpd_pulse");
|
||||||
server = param.GetBlockValue("server");
|
server = block.GetBlockValue("server");
|
||||||
sink = param.GetBlockValue("sink");
|
sink = block.GetBlockValue("sink");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PulseOutput *
|
PulseOutput *
|
||||||
PulseOutput::Create(const config_param ¶m, Error &error)
|
PulseOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
setenv("PULSE_PROP_media.role", "music", true);
|
setenv("PULSE_PROP_media.role", "music", true);
|
||||||
setenv("PULSE_PROP_application.icon_name", "mpd", true);
|
setenv("PULSE_PROP_application.icon_name", "mpd", true);
|
||||||
|
|
||||||
auto *po = new PulseOutput();
|
auto *po = new PulseOutput();
|
||||||
if (!po->Configure(param, error)) {
|
if (!po->Configure(block, error)) {
|
||||||
delete po;
|
delete po;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -926,7 +926,7 @@ PulseOutput::Pause()
|
|||||||
inline bool
|
inline bool
|
||||||
PulseOutput::TestDefaultDevice()
|
PulseOutput::TestDefaultDevice()
|
||||||
{
|
{
|
||||||
const config_param empty;
|
const ConfigBlock empty;
|
||||||
PulseOutput *po = PulseOutput::Create(empty, IgnoreError());
|
PulseOutput *po = PulseOutput::Create(empty, IgnoreError());
|
||||||
if (po == nullptr)
|
if (po == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -81,13 +81,13 @@ class RecorderOutput {
|
|||||||
encoder->Dispose();
|
encoder->Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error_r) {
|
bool Initialize(const ConfigBlock &block, Error &error_r) {
|
||||||
return base.Configure(param, error_r);
|
return base.Configure(block, error_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RecorderOutput *Create(const config_param ¶m, Error &error);
|
static RecorderOutput *Create(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Open(AudioFormat &audio_format, Error &error);
|
bool Open(AudioFormat &audio_format, Error &error);
|
||||||
void Close();
|
void Close();
|
||||||
@ -117,12 +117,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
RecorderOutput::Configure(const config_param ¶m, Error &error)
|
RecorderOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
/* read configuration */
|
/* read configuration */
|
||||||
|
|
||||||
const char *encoder_name =
|
const char *encoder_name =
|
||||||
param.GetBlockValue("encoder", "vorbis");
|
block.GetBlockValue("encoder", "vorbis");
|
||||||
const auto encoder_plugin = encoder_plugin_get(encoder_name);
|
const auto encoder_plugin = encoder_plugin_get(encoder_name);
|
||||||
if (encoder_plugin == nullptr) {
|
if (encoder_plugin == nullptr) {
|
||||||
error.Format(config_domain,
|
error.Format(config_domain,
|
||||||
@ -130,11 +130,11 @@ RecorderOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = param.GetBlockPath("path", error);
|
path = block.GetBlockPath("path", error);
|
||||||
if (error.IsDefined())
|
if (error.IsDefined())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char *fmt = param.GetBlockValue("format_path", nullptr);
|
const char *fmt = block.GetBlockValue("format_path", nullptr);
|
||||||
if (fmt != nullptr)
|
if (fmt != nullptr)
|
||||||
format_path = fmt;
|
format_path = fmt;
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ RecorderOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
|
|
||||||
/* initialize encoder */
|
/* initialize encoder */
|
||||||
|
|
||||||
encoder = encoder_init(*encoder_plugin, param, error);
|
encoder = encoder_init(*encoder_plugin, block, error);
|
||||||
if (encoder == nullptr)
|
if (encoder == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -158,16 +158,16 @@ RecorderOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecorderOutput *
|
RecorderOutput *
|
||||||
RecorderOutput::Create(const config_param ¶m, Error &error)
|
RecorderOutput::Create(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
RecorderOutput *recorder = new RecorderOutput();
|
RecorderOutput *recorder = new RecorderOutput();
|
||||||
|
|
||||||
if (!recorder->Initialize(param, error)) {
|
if (!recorder->Initialize(block, error)) {
|
||||||
delete recorder;
|
delete recorder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recorder->Configure(param, error)) {
|
if (!recorder->Configure(block, error)) {
|
||||||
delete recorder;
|
delete recorder;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -60,11 +60,11 @@ public:
|
|||||||
return &base;
|
return &base;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error) {
|
bool Initialize(const ConfigBlock &block, Error &error) {
|
||||||
return base.Configure(param, error);
|
return base.Configure(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configure(const config_param ¶m);
|
void Configure(const ConfigBlock &block);
|
||||||
|
|
||||||
bool Open(AudioFormat &audio_format, Error &error);
|
bool Open(AudioFormat &audio_format, Error &error);
|
||||||
void Close();
|
void Close();
|
||||||
@ -124,28 +124,28 @@ roar_output_set_volume(RoarOutput &roar, unsigned volume)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
RoarOutput::Configure(const config_param ¶m)
|
RoarOutput::Configure(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
host = param.GetBlockValue("server", "");
|
host = block.GetBlockValue("server", "");
|
||||||
name = param.GetBlockValue("name", "MPD");
|
name = block.GetBlockValue("name", "MPD");
|
||||||
|
|
||||||
const char *_role = param.GetBlockValue("role", "music");
|
const char *_role = block.GetBlockValue("role", "music");
|
||||||
role = _role != nullptr
|
role = _role != nullptr
|
||||||
? roar_str2role(_role)
|
? roar_str2role(_role)
|
||||||
: ROAR_ROLE_MUSIC;
|
: ROAR_ROLE_MUSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
roar_init(const config_param ¶m, Error &error)
|
roar_init(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
RoarOutput *self = new RoarOutput();
|
RoarOutput *self = new RoarOutput();
|
||||||
|
|
||||||
if (!self->Initialize(param, error)) {
|
if (!self->Initialize(block, error)) {
|
||||||
delete self;
|
delete self;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->Configure(param);
|
self->Configure(block);
|
||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ struct ShoutOutput final {
|
|||||||
shout_free(shout_conn);
|
shout_free(shout_conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(const config_param ¶m, Error &error) {
|
bool Initialize(const ConfigBlock &block, Error &error) {
|
||||||
return base.Configure(param, error);
|
return base.Configure(block, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Configure(const config_param ¶m, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int shout_init_count;
|
static int shout_init_count;
|
||||||
@ -92,18 +92,18 @@ shout_encoder_plugin_get(const char *name)
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static const char *
|
static const char *
|
||||||
require_block_string(const config_param ¶m, const char *name)
|
require_block_string(const ConfigBlock &block, const char *name)
|
||||||
{
|
{
|
||||||
const char *value = param.GetBlockValue(name);
|
const char *value = block.GetBlockValue(name);
|
||||||
if (value == nullptr)
|
if (value == nullptr)
|
||||||
FormatFatalError("no \"%s\" defined for shout device defined "
|
FormatFatalError("no \"%s\" defined for shout device defined "
|
||||||
"at line %d\n", name, param.line);
|
"at line %d\n", name, block.line);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ShoutOutput::Configure(const config_param ¶m, Error &error)
|
ShoutOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
|
|
||||||
const AudioFormat audio_format = base.config_audio_format;
|
const AudioFormat audio_format = base.config_audio_format;
|
||||||
@ -113,22 +113,22 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *host = require_block_string(param, "host");
|
const char *host = require_block_string(block, "host");
|
||||||
const char *mount = require_block_string(param, "mount");
|
const char *mount = require_block_string(block, "mount");
|
||||||
unsigned port = param.GetBlockValue("port", 0u);
|
unsigned port = block.GetBlockValue("port", 0u);
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
error.Set(config_domain, "shout port must be configured");
|
error.Set(config_domain, "shout port must be configured");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *passwd = require_block_string(param, "password");
|
const char *passwd = require_block_string(block, "password");
|
||||||
const char *name = require_block_string(param, "name");
|
const char *name = require_block_string(block, "name");
|
||||||
|
|
||||||
bool is_public = param.GetBlockValue("public", false);
|
bool is_public = block.GetBlockValue("public", false);
|
||||||
|
|
||||||
const char *user = param.GetBlockValue("user", "source");
|
const char *user = block.GetBlockValue("user", "source");
|
||||||
|
|
||||||
const char *value = param.GetBlockValue("quality");
|
const char *value = block.GetBlockValue("quality");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
char *test;
|
char *test;
|
||||||
quality = strtod(value, &test);
|
quality = strtod(value, &test);
|
||||||
@ -141,14 +141,14 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"quality and bitrate are "
|
"quality and bitrate are "
|
||||||
"both defined");
|
"both defined");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = param.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
error.Set(config_domain,
|
error.Set(config_domain,
|
||||||
"neither bitrate nor quality defined");
|
"neither bitrate nor quality defined");
|
||||||
@ -165,7 +165,7 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *encoding = param.GetBlockValue("encoding", "ogg");
|
const char *encoding = block.GetBlockValue("encoding", "ogg");
|
||||||
const auto encoder_plugin = shout_encoder_plugin_get(encoding);
|
const auto encoder_plugin = shout_encoder_plugin_get(encoding);
|
||||||
if (encoder_plugin == nullptr) {
|
if (encoder_plugin == nullptr) {
|
||||||
error.Format(config_domain,
|
error.Format(config_domain,
|
||||||
@ -174,7 +174,7 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder = encoder_init(*encoder_plugin, param, error);
|
encoder = encoder_init(*encoder_plugin, block, error);
|
||||||
if (encoder == nullptr)
|
if (encoder == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
shout_format = SHOUT_FORMAT_OGG;
|
shout_format = SHOUT_FORMAT_OGG;
|
||||||
|
|
||||||
unsigned protocol;
|
unsigned protocol;
|
||||||
value = param.GetBlockValue("protocol");
|
value = block.GetBlockValue("protocol");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
if (0 == strcmp(value, "shoutcast") &&
|
if (0 == strcmp(value, "shoutcast") &&
|
||||||
0 != strcmp(encoding, "mp3")) {
|
0 != strcmp(encoding, "mp3")) {
|
||||||
@ -226,21 +226,21 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* optional paramters */
|
/* optional paramters */
|
||||||
timeout = param.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT);
|
timeout = block.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT);
|
||||||
|
|
||||||
value = param.GetBlockValue("genre");
|
value = block.GetBlockValue("genre");
|
||||||
if (value != nullptr && shout_set_genre(shout_conn, value)) {
|
if (value != nullptr && shout_set_genre(shout_conn, value)) {
|
||||||
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = param.GetBlockValue("description");
|
value = block.GetBlockValue("description");
|
||||||
if (value != nullptr && shout_set_description(shout_conn, value)) {
|
if (value != nullptr && shout_set_description(shout_conn, value)) {
|
||||||
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = param.GetBlockValue("url");
|
value = block.GetBlockValue("url");
|
||||||
if (value != nullptr && shout_set_url(shout_conn, value)) {
|
if (value != nullptr && shout_set_url(shout_conn, value)) {
|
||||||
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
error.Set(shout_output_domain, shout_get_error(shout_conn));
|
||||||
return false;
|
return false;
|
||||||
@ -272,15 +272,15 @@ ShoutOutput::Configure(const config_param ¶m, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static AudioOutput *
|
static AudioOutput *
|
||||||
my_shout_init_driver(const config_param ¶m, Error &error)
|
my_shout_init_driver(const ConfigBlock &block, Error &error)
|
||||||
{
|
{
|
||||||
ShoutOutput *sd = new ShoutOutput();
|
ShoutOutput *sd = new ShoutOutput();
|
||||||
if (!sd->Initialize(param, error)) {
|
if (!sd->Initialize(block, error)) {
|
||||||
delete sd;
|
delete sd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sd->Configure(param, error)) {
|
if (!sd->Configure(block, error)) {
|
||||||
delete sd;
|
delete sd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user