command/Partition: add command "newpartition"

This commit is contained in:
Max Kellermann 2017-02-17 23:38:30 +01:00
parent 1e972174a6
commit 1786f9b1bb
4 changed files with 88 additions and 0 deletions

View File

@ -2376,6 +2376,20 @@ OK
</para>
</listitem>
</varlistentry>
<varlistentry id="command_newpartition">
<term>
<cmdsynopsis>
<command>newpartition</command>
<arg choice="req"><replaceable>NAME</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Create a new partition.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>

View File

@ -133,6 +133,7 @@ static constexpr struct command commands[] = {
#endif
{ "move", PERMISSION_CONTROL, 2, 2, handle_move },
{ "moveid", PERMISSION_CONTROL, 2, 2, handle_moveid },
{ "newpartition", PERMISSION_ADMIN, 1, 1, handle_newpartition },
{ "next", PERMISSION_CONTROL, 0, 0, handle_next },
{ "notcommands", PERMISSION_NONE, 0, 0, handle_not_commands },
{ "outputs", PERMISSION_READ, 0, 0, handle_devices },

View File

@ -24,6 +24,8 @@
#include "Partition.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "player/Thread.hxx"
#include "util/CharUtil.hxx"
CommandResult
handle_listpartitions(Client &client, Request, Response &r)
@ -34,3 +36,71 @@ handle_listpartitions(Client &client, Request, Response &r)
return CommandResult::OK;
}
static constexpr bool
IsValidPartitionChar(char ch)
{
return IsAlphaNumericASCII(ch) || ch == '-' || ch == '_';
}
gcc_pure
static bool
IsValidPartitionName(const char *name)
{
do {
if (!IsValidPartitionChar(*name))
return false;
} while (*++name != 0);
return true;
}
gcc_pure
static bool
HasPartitionNamed(const Instance &instance, const char *name)
{
for (const auto &partition : instance.partitions)
if (partition.name == name)
return true;
return false;
}
CommandResult
handle_newpartition(Client &client, Request request, Response &response)
{
const char *name = request.front();
if (!IsValidPartitionName(name)) {
response.Error(ACK_ERROR_ARG, "bad name");
return CommandResult::ERROR;
}
auto &instance = client.partition.instance;
if (HasPartitionNamed(instance, name)) {
response.Error(ACK_ERROR_EXIST, "name already exists");
return CommandResult::ERROR;
}
if (instance.partitions.size() >= 16) {
/* arbitrary limit for now */
response.Error(ACK_ERROR_UNKNOWN, "too many partitions");
return CommandResult::ERROR;
}
instance.partitions.emplace_back(instance, name,
// TODO: use real configuration
16384,
1024,
128,
AudioFormat::Undefined(),
ReplayGainConfig());
auto &partition = instance.partitions.back();
partition.outputs.AddNullOutput(instance.io_thread.GetEventLoop(),
ReplayGainConfig(),
partition.pc);
partition.UpdateEffectiveReplayGainMode();
StartPlayerThread(partition.pc);
partition.pc.LockUpdateAudio();
return CommandResult::OK;
}

View File

@ -29,4 +29,7 @@ class Response;
CommandResult
handle_listpartitions(Client &client, Request request, Response &response);
CommandResult
handle_newpartition(Client &client, Request request, Response &response);
#endif