diff options
Diffstat (limited to 'src/output/HttpdInternal.hxx')
-rw-r--r-- | src/output/HttpdInternal.hxx | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/src/output/HttpdInternal.hxx b/src/output/HttpdInternal.hxx index b76493a44..8d35d35e9 100644 --- a/src/output/HttpdInternal.hxx +++ b/src/output/HttpdInternal.hxx @@ -29,6 +29,8 @@ #include "Timer.hxx" #include "thread/Mutex.hxx" #include "event/ServerSocket.hxx" +#include "event/DeferredMonitor.hxx" +#include "util/Cast.hxx" #ifdef _LIBCPP_VERSION /* can't use incomplete template arguments with libc++ */ @@ -36,6 +38,8 @@ #endif #include <forward_list> +#include <queue> +#include <list> struct config_param; class Error; @@ -46,7 +50,7 @@ class Page; struct Encoder; struct Tag; -struct HttpdOutput final : private ServerSocket { +class HttpdOutput final : ServerSocket, DeferredMonitor { struct audio_output base; /** @@ -68,6 +72,7 @@ struct HttpdOutput final : private ServerSocket { */ size_t unflushed_input; +public: /** * The MIME type produced by the #encoder. */ @@ -80,6 +85,13 @@ struct HttpdOutput final : private ServerSocket { mutable Mutex mutex; /** + * This condition gets signalled when an item is removed from + * #pages. + */ + Cond cond; + +private: + /** * A #Timer object to synchronize this output with the * wallclock. */ @@ -96,6 +108,15 @@ struct HttpdOutput final : private ServerSocket { Page *metadata; /** + * The page queue, i.e. pages from the encoder to be + * broadcasted to all clients. This container is necessary to + * pass pages from the OutputThread to the IOThread. It is + * protected by #mutex, and removing signals #cond. + */ + std::queue<Page *, std::list<Page *>> pages; + + public: + /** * The configured name. */ char const *name; @@ -108,6 +129,7 @@ struct HttpdOutput final : private ServerSocket { */ char const *website; +private: /** * A linked list containing all clients which are currently * connected. @@ -126,11 +148,46 @@ struct HttpdOutput final : private ServerSocket { */ unsigned clients_max, clients_cnt; +public: HttpdOutput(EventLoop &_loop); ~HttpdOutput(); +#if GCC_CHECK_VERSION(4,6) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + + static constexpr HttpdOutput *Cast(audio_output *ao) { + return ContainerCast(ao, HttpdOutput, base); + } + +#if GCC_CHECK_VERSION(4,6) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + + using DeferredMonitor::GetEventLoop; + + bool Init(const config_param ¶m, Error &error); + + void Finish() { + ao_base_finish(&base); + } + bool Configure(const config_param ¶m, Error &error); + audio_output *InitAndConfigure(const config_param ¶m, + Error &error) { + if (!Init(param, error)) + return nullptr; + + if (!Configure(param, error)) { + Finish(); + return nullptr; + } + + return &base; + } + bool Bind(Error &error); void Unbind(); @@ -181,6 +238,9 @@ struct HttpdOutput final : private ServerSocket { */ void SendHeader(HttpdClient &client) const; + gcc_pure + unsigned Delay() const; + /** * Reads data from the encoder (as much as available) and * returns it as a new #page object. @@ -203,7 +263,13 @@ struct HttpdOutput final : private ServerSocket { void SendTag(const Tag *tag); + size_t Play(const void *chunk, size_t size, Error &error); + + void CancelAllClients(); + private: + virtual void RunDeferred() override; + virtual void OnAccept(int fd, const sockaddr &address, size_t address_length, int uid) override; }; |