From 77178e0590c428a551b58052c472a7a0cf9e554d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 17 Feb 2017 23:21:20 +0100 Subject: [PATCH] Instance: make "partition" a std::list With this commit, multi-player support becomes possible... it's just not wired to the frontend yet. This is based on massive amounts of refactoring work I did over the past 9 years. --- src/Instance.cxx | 13 +++++++--- src/Instance.hxx | 4 ++- src/Main.cxx | 43 ++++++++++++++++++------------- src/command/PartitionCommands.cxx | 6 ++++- 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/Instance.cxx b/src/Instance.cxx index 53cb00a33..5d7584e41 100644 --- a/src/Instance.cxx +++ b/src/Instance.cxx @@ -59,7 +59,9 @@ Instance::OnDatabaseModified() /* propagate the change to all subsystems */ stats_invalidate(); - partition->DatabaseModified(*database); + + for (auto &partition : partitions) + partition.DatabaseModified(*database); } void @@ -77,7 +79,8 @@ Instance::OnDatabaseSongRemoved(const char *uri) } #endif - partition->StaleSong(uri); + for (auto &partition : partitions) + partition.StaleSong(uri); } #endif @@ -87,13 +90,15 @@ Instance::OnDatabaseSongRemoved(const char *uri) void Instance::FoundNeighbor(gcc_unused const NeighborInfo &info) { - partition->EmitIdle(IDLE_NEIGHBOR); + for (auto &partition : partitions) + partition.EmitIdle(IDLE_NEIGHBOR); } void Instance::LostNeighbor(gcc_unused const NeighborInfo &info) { - partition->EmitIdle(IDLE_NEIGHBOR); + for (auto &partition : partitions) + partition.EmitIdle(IDLE_NEIGHBOR); } #endif diff --git a/src/Instance.hxx b/src/Instance.hxx index 13cacc28b..45e81cf81 100644 --- a/src/Instance.hxx +++ b/src/Instance.hxx @@ -38,6 +38,8 @@ class Storage; class UpdateService; #endif +#include + class ClientList; struct Partition; class StateFile; @@ -87,7 +89,7 @@ struct Instance final ClientList *client_list; - Partition *partition; + std::list partitions; StateFile *state_file = nullptr; diff --git a/src/Main.cxx b/src/Main.cxx index d2deff4c8..be6d0ea7f 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -265,7 +265,7 @@ glue_state_file_init() StateFile::DEFAULT_INTERVAL); instance->state_file = new StateFile(std::move(path_fs), interval, - *instance->partition, + instance->partitions.front(), instance->event_loop); instance->state_file->Read(); } @@ -352,18 +352,19 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config) } } - instance->partition = new Partition(*instance, - "default", - max_length, - buffered_chunks, - buffered_before_play, - configured_audio_format, - replay_gain_config); + instance->partitions.emplace_back(*instance, + "default", + max_length, + buffered_chunks, + buffered_before_play, + configured_audio_format, + replay_gain_config); + auto &partition = instance->partitions.back(); try { param = config_get_param(ConfigOption::REPLAYGAIN); if (param != nullptr) - instance->partition->replay_gain_mode = + partition.replay_gain_mode = FromString(param->value.c_str()); } catch (...) { std::throw_with_nested(FormatRuntimeError("Failed to parse line %i", @@ -467,7 +468,7 @@ try { initialize_decoder_and_player(config.replay_gain); - listen_global_init(instance->event_loop, *instance->partition); + listen_global_init(instance->event_loop, instance->partitions.front()); #ifdef ENABLE_DAEMON daemonize_set_user(); @@ -519,10 +520,12 @@ try { command_init(); - instance->partition->outputs.Configure(instance->io_thread.GetEventLoop(), - config.replay_gain, - instance->partition->pc); - instance->partition->UpdateEffectiveReplayGainMode(); + for (auto &partition : instance->partitions) { + partition.outputs.Configure(instance->io_thread.GetEventLoop(), + config.replay_gain, + partition.pc); + partition.UpdateEffectiveReplayGainMode(); + } client_manager_init(); input_stream_global_init(instance->io_thread.GetEventLoop()); @@ -547,7 +550,8 @@ try { ZeroconfInit(instance->event_loop); - StartPlayerThread(instance->partition->pc); + for (auto &partition : instance->partitions) + StartPlayerThread(partition.pc); #ifdef ENABLE_DATABASE if (create_db) { @@ -582,7 +586,8 @@ try { /* enable all audio outputs (if not already done by playlist_state_restore() */ - instance->partition->pc.LockUpdateAudio(); + for (auto &partition : instance->partitions) + partition.pc.LockUpdateAudio(); #ifdef WIN32 win32_app_started(); @@ -617,7 +622,9 @@ try { delete instance->state_file; } - instance->partition->pc.Kill(); + for (auto &partition : instance->partitions) + partition.pc.Kill(); + ZeroconfDeinit(); listen_global_finish(); delete instance->client_list; @@ -653,7 +660,7 @@ try { DeinitFS(); - delete instance->partition; + instance->partitions.clear(); command_finish(); decoder_plugin_deinit_all(); #ifdef ENABLE_ARCHIVE diff --git a/src/command/PartitionCommands.cxx b/src/command/PartitionCommands.cxx index e3064ad98..1ccf5f85a 100644 --- a/src/command/PartitionCommands.cxx +++ b/src/command/PartitionCommands.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "PartitionCommands.hxx" #include "Request.hxx" +#include "Instance.hxx" #include "Partition.hxx" #include "client/Client.hxx" #include "client/Response.hxx" @@ -27,6 +28,9 @@ CommandResult handle_listpartitions(Client &client, Request, Response &r) { - r.Format("partition: %s\n", client.partition.name.c_str()); + for (const auto &partition : client.partition.instance.partitions) { + r.Format("partition: %s\n", partition.name.c_str()); + } + return CommandResult::OK; }