HttpdInternal.hxx 4.27 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2013 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/** \file
 *
 * Internal declarations for the "httpd" audio output plugin.
 */

#ifndef MPD_OUTPUT_HTTPD_INTERNAL_H
#define MPD_OUTPUT_HTTPD_INTERNAL_H

Max Kellermann's avatar
Max Kellermann committed
28
#include "OutputInternal.hxx"
29
#include "Timer.hxx"
30
#include "thread/Mutex.hxx"
31
#include "event/ServerSocket.hxx"
32

33 34
#include <forward_list>

35
struct config_param;
36
class Error;
37
class EventLoop;
38
class ServerSocket;
39
class HttpdClient;
40
class Page;
41
struct Encoder;
Max Kellermann's avatar
Max Kellermann committed
42
struct Tag;
43

44
struct HttpdOutput final : private ServerSocket {
45 46
	struct audio_output base;

47 48 49 50 51 52
	/**
	 * True if the audio output is open and accepts client
	 * connections.
	 */
	bool open;

53 54 55
	/**
	 * The configured encoder plugin.
	 */
56
	Encoder *encoder;
57

58 59 60 61 62 63 64 65
	/**
	 * Number of bytes which were fed into the encoder, without
	 * ever receiving new output.  This is used to estimate
	 * whether MPD should manually flush the encoder, to avoid
	 * buffer underruns in the client.
	 */
	size_t unflushed_input;

66 67 68 69 70 71 72 73 74
	/**
	 * The MIME type produced by the #encoder.
	 */
	const char *content_type;

	/**
	 * This mutex protects the listener socket and the client
	 * list.
	 */
75
	mutable Mutex mutex;
76 77

	/**
78
	 * A #Timer object to synchronize this output with the
79 80
	 * wallclock.
	 */
81
	Timer *timer;
82 83 84 85

	/**
	 * The header page, which is sent to every client on connect.
	 */
Max Kellermann's avatar
Max Kellermann committed
86
	Page *header;
87

88 89 90
	/**
	 * The metadata, which is sent to every client.
	 */
Max Kellermann's avatar
Max Kellermann committed
91
	Page *metadata;
92

93 94 95 96 97 98 99 100 101 102 103 104 105
	/**
	 * The configured name.
	 */
	char const *name;
	/**
	 * The configured genre.
	 */
	char const *genre;
	/**
	 * The configured website address.
	 */
	char const *website;

106 107 108 109
	/**
	 * A linked list containing all clients which are currently
	 * connected.
	 */
110
	std::forward_list<HttpdClient> clients;
111 112 113 114 115 116

	/**
	 * A temporary buffer for the httpd_output_read_page()
	 * function.
	 */
	char buffer[32768];
117 118

	/**
119
	 * The maximum and current number of clients connected
120 121
	 * at the same time.
	 */
122
	unsigned clients_max, clients_cnt;
123

124 125 126
	HttpdOutput(EventLoop &_loop);
	~HttpdOutput();

127
	bool Configure(const config_param &param, Error &error);
128

129
	bool Bind(Error &error);
130
	void Unbind();
131

132 133 134
	/**
	 * Caller must lock the mutex.
	 */
135
	bool OpenEncoder(AudioFormat &audio_format, Error &error);
136 137 138 139

	/**
	 * Caller must lock the mutex.
	 */
140
	bool Open(AudioFormat &audio_format, Error &error);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

	/**
	 * Caller must lock the mutex.
	 */
	void Close();

	/**
	 * Check whether there is at least one client.
	 *
	 * Caller must lock the mutex.
	 */
	gcc_pure
	bool HasClients() const {
		return !clients.empty();
	}

	/**
	 * Check whether there is at least one client.
	 */
	gcc_pure
	bool LockHasClients() const {
		const ScopeLock protect(mutex);
		return HasClients();
	}

	void AddClient(int fd);

	/**
	 * Removes a client from the httpd_output.clients linked list.
	 */
	void RemoveClient(HttpdClient &client);

	/**
	 * Sends the encoder header to the client.  This is called
	 * right after the response headers have been sent.
	 */
	void SendHeader(HttpdClient &client) const;

	/**
	 * Reads data from the encoder (as much as available) and
	 * returns it as a new #page object.
	 */
Max Kellermann's avatar
Max Kellermann committed
183
	Page *ReadPage();
184 185 186 187 188 189

	/**
	 * Broadcasts a page struct to all clients.
	 *
	 * Mutext must not be locked.
	 */
Max Kellermann's avatar
Max Kellermann committed
190
	void BroadcastPage(Page *page);
191 192 193 194 195 196

	/**
	 * Broadcasts data from the encoder to all clients.
	 */
	void BroadcastFromEncoder();

197
	bool EncodeAndPlay(const void *chunk, size_t size, Error &error);
198

Max Kellermann's avatar
Max Kellermann committed
199
	void SendTag(const Tag *tag);
200 201 202 203

private:
	virtual void OnAccept(int fd, const sockaddr &address,
			      size_t address_length, int uid) override;
204
};
205

206 207
extern const class Domain httpd_output_domain;

208
#endif