diff options
author | Max Kellermann <max@musicpd.org> | 2020-01-20 09:10:02 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-01-20 14:56:31 +0100 |
commit | cc7f66822ed4e4f673255f3094bdc123831d8c56 (patch) | |
tree | 41dde0044002890840204898c21db53c364669b7 | |
parent | 9cbfa66886257d0df4c677c01e37be05bbf6f266 (diff) |
command/partition: add command "delpartition"
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/protocol.rst | 4 | ||||
-rw-r--r-- | src/Instance.cxx | 14 | ||||
-rw-r--r-- | src/Instance.hxx | 2 | ||||
-rw-r--r-- | src/command/AllCommands.cxx | 1 | ||||
-rw-r--r-- | src/command/PartitionCommands.cxx | 42 | ||||
-rw-r--r-- | src/command/PartitionCommands.hxx | 3 | ||||
-rw-r--r-- | src/output/MultipleOutputs.hxx | 12 |
8 files changed, 79 insertions, 0 deletions
@@ -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" diff --git a/doc/protocol.rst b/doc/protocol.rst index 88742f9d2..a51a3b6b5 100644 --- a/doc/protocol.rst +++ b/doc/protocol.rst @@ -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. diff --git a/src/Instance.cxx b/src/Instance.cxx index bcb8502f9..2d8003f42 100644 --- a/src/Instance.cxx +++ b/src/Instance.cxx @@ -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 & diff --git a/src/Instance.hxx b/src/Instance.hxx index 2b72c4521..0baebcc26 100644 --- a/src/Instance.hxx +++ b/src/Instance.hxx @@ -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 diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx index 73ae9b4e7..8943f44e0 100644 --- a/src/command/AllCommands.cxx +++ b/src/command/AllCommands.cxx @@ -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 diff --git a/src/command/PartitionCommands.cxx b/src/command/PartitionCommands.cxx index bbb0e0143..fbcb8a754 100644 --- a/src/command/PartitionCommands.cxx +++ b/src/command/PartitionCommands.cxx @@ -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]; diff --git a/src/command/PartitionCommands.hxx b/src/command/PartitionCommands.hxx index c840c0a82..22ce5df8c 100644 --- a/src/command/PartitionCommands.hxx +++ b/src/command/PartitionCommands.hxx @@ -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 diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx index fc65e8460..885f5f522 100644 --- a/src/output/MultipleOutputs.hxx +++ b/src/output/MultipleOutputs.hxx @@ -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. */ |