summaryrefslogtreecommitdiff
path: root/src/Instance.hxx
blob: 5aa2209d97e5c0f23101bd7208a73f5a18e3bc2d (plain)
1
2
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Copyright 2003-2018 The Music Player Daemon Project
 * 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.
 */

#ifndef MPD_INSTANCE_HXX
#define MPD_INSTANCE_HXX

#include "config.h"
#include "event/Loop.hxx"
#include "event/Thread.hxx"
#include "event/MaskMonitor.hxx"
#include "util/Compiler.h"

#ifdef ENABLE_SYSTEMD_DAEMON
#include "lib/systemd/Watchdog.hxx"
#endif

#ifdef ENABLE_CURL
#include "RemoteTagCacheHandler.hxx"
#endif

#ifdef ENABLE_NEIGHBOR_PLUGINS
#include "neighbor/Listener.hxx"
class NeighborGlue;
#endif

#ifdef ENABLE_DATABASE
#include "db/DatabaseListener.hxx"
#include "db/Ptr.hxx"
class Storage;
class UpdateService;
#endif

#include <memory>
#include <list>

class ClientList;
struct Partition;
class StateFile;
class RemoteTagCache;

/**
 * A utility class which, when used as the first base class, ensures
 * that the #EventLoop gets initialized before the other base classes.
 */
struct EventLoopHolder {
	EventLoop event_loop;
};

struct Instance final
	: EventLoopHolder
#if defined(ENABLE_DATABASE) || defined(ENABLE_NEIGHBOR_PLUGINS)
	,
#endif
#ifdef ENABLE_DATABASE
	public DatabaseListener
#ifdef ENABLE_NEIGHBOR_PLUGINS
	,
#endif
#endif
#ifdef ENABLE_NEIGHBOR_PLUGINS
	public NeighborListener
#endif
#ifdef ENABLE_CURL
	, public RemoteTagCacheHandler
#endif
{
	/**
	 * A thread running an #EventLoop for non-blocking (bulk) I/O.
	 */
	EventThread io_thread;

	/**
	 * Another thread running an #EventLoop for non-blocking
	 * (real-time) I/O.  This is used instead of #io_thread for
	 * events which require low latency, e.g. for filling hardware
	 * ring buffers.
	 */
	EventThread rtio_thread;

#ifdef ENABLE_SYSTEMD_DAEMON
	Systemd::Watchdog systemd_watchdog;
#endif

	MaskMonitor idle_monitor;

#ifdef ENABLE_NEIGHBOR_PLUGINS
	NeighborGlue *neighbors;
#endif

#ifdef ENABLE_DATABASE
	DatabasePtr database;

	/**
	 * This is really a #CompositeStorage.  To avoid heavy include
	 * dependencies, we declare it as just #Storage.
	 */
	Storage *storage = nullptr;

	UpdateService *update = nullptr;
#endif

#ifdef ENABLE_CURL
	std::unique_ptr<RemoteTagCache> remote_tag_cache;
#endif

	ClientList *client_list;

	std::list<Partition> partitions;

	StateFile *state_file = nullptr;

	Instance();
	~Instance() noexcept;

	/**
	 * Wrapper for EventLoop::Break().  Call to initiate shutdown.
	 */
	void Break() {
		event_loop.Break();
	}

	void EmitIdle(unsigned mask) {
		idle_monitor.OrMask(mask);
	}

	/**
	 * Find a #Partition with the given name.  Returns nullptr if
	 * no such partition was found.
	 */
	gcc_pure
	Partition *FindPartition(const char *name) noexcept;

	void BeginShutdownPartitions() noexcept;

#ifdef ENABLE_DATABASE
	/**
	 * Returns the global #Database instance.  May return nullptr
	 * if this MPD configuration has no database (no
	 * music_directory was configured).
	 */
	Database *GetDatabase() {
		return database.get();
	}

	/**
	 * Returns the global #Database instance.  Throws
	 * DatabaseError if this MPD configuration has no database (no
	 * music_directory was configured).
	 */
	const Database &GetDatabaseOrThrow() const;
#endif

	void BeginShutdownUpdate() noexcept;

#ifdef ENABLE_CURL
	void LookupRemoteTag(const char *uri) noexcept;
#else
	void LookupRemoteTag(const char *) noexcept {
		/* no-op */
	}
#endif

private:
#ifdef ENABLE_DATABASE
	void OnDatabaseModified() override;
	void OnDatabaseSongRemoved(const char *uri) override;
#endif

#ifdef ENABLE_NEIGHBOR_PLUGINS
	/* virtual methods from class NeighborListener */
	void FoundNeighbor(const NeighborInfo &info) noexcept override;
	void LostNeighbor(const NeighborInfo &info) noexcept override;
#endif

#ifdef ENABLE_CURL
	/* virtual methods from class RemoteTagCacheHandler */
	void OnRemoteTag(const char *uri, const Tag &tag) noexcept override;
#endif

	/* callback for #idle_monitor */
	void OnIdle(unsigned mask);
};

#endif