Commit cc7f6682 authored by Max Kellermann's avatar Max Kellermann

command/partition: add command "delpartition"

parent 9cbfa668
......@@ -4,6 +4,7 @@ ver 0.22 (not yet released)
"window" parameters
- add command "readpicture" to download embedded pictures
- command "moveoutput" moves an output between partitions
- command "delpartition" deletes a partition
- show partition name in "status" response
* tags
- new tags "Grouping" (for ID3 "TIT1"), "Work" and "Conductor"
......
......@@ -1262,6 +1262,10 @@ client is assigned to one partition at a time.
:command:`newpartition {NAME}`
Create a new partition.
:command:`delpartition {NAME}`
Delete a partition. The partition must be empty (no connected
clients and no outputs).
:command:`moveoutput {OUTPUTNAME}`
Move an output to the current partition.
......
......@@ -87,6 +87,20 @@ Instance::FindPartition(const char *name) noexcept
return nullptr;
}
void
Instance::DeletePartition(Partition &partition) noexcept
{
// TODO: use boost::intrusive::list to avoid this loop
for (auto i = partitions.begin();; ++i) {
assert(i != partitions.end());
if (&*i == &partition) {
partitions.erase(i);
break;
}
}
}
#ifdef ENABLE_DATABASE
const Database &
......
......@@ -171,6 +171,8 @@ struct Instance final
gcc_pure
Partition *FindPartition(const char *name) noexcept;
void DeletePartition(Partition &partition) noexcept;
void BeginShutdownPartitions() noexcept;
#ifdef ENABLE_DATABASE
......
......@@ -103,6 +103,7 @@ static constexpr struct command commands[] = {
{ "decoders", PERMISSION_READ, 0, 0, handle_decoders },
{ "delete", PERMISSION_CONTROL, 1, 1, handle_delete },
{ "deleteid", PERMISSION_CONTROL, 1, 1, handle_deleteid },
{ "delpartition", PERMISSION_ADMIN, 1, 1, handle_delpartition },
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
#ifdef ENABLE_DATABASE
......
......@@ -113,6 +113,48 @@ handle_newpartition(Client &client, Request request, Response &response)
}
CommandResult
handle_delpartition(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.GetInstance();
auto *partition = instance.FindPartition(name);
if (partition == nullptr) {
response.Error(ACK_ERROR_NO_EXIST, "no such partition");
return CommandResult::ERROR;
}
if (partition == &instance.partitions.front()) {
response.Error(ACK_ERROR_UNKNOWN,
"cannot delete the default partition");
return CommandResult::ERROR;
}
if (!partition->clients.empty()) {
response.Error(ACK_ERROR_UNKNOWN,
"partition still has clients");
return CommandResult::ERROR;
}
if (!partition->outputs.IsDummy()) {
response.Error(ACK_ERROR_UNKNOWN,
"partition still has outputs");
return CommandResult::ERROR;
}
partition->BeginShutdown();
instance.DeletePartition(*partition);
instance.EmitIdle(IDLE_PARTITION);
return CommandResult::OK;
}
CommandResult
handle_moveoutput(Client &client, Request request, Response &response)
{
const char *output_name = request[0];
......
......@@ -36,6 +36,9 @@ CommandResult
handle_newpartition(Client &client, Request request, Response &response);
CommandResult
handle_delpartition(Client &client, Request request, Response &response);
CommandResult
handle_moveoutput(Client &client, Request request, Response &response);
#endif
......@@ -103,6 +103,18 @@ public:
}
/**
* Are all outputs dummy?
*/
gcc_pure
bool IsDummy() const noexcept {
for (const auto &i : outputs)
if (!i->IsDummy())
return false;
return true;
}
/**
* Returns the audio output device with the specified name.
* Returns nullptr if the name does not exist.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment