1 /*
2  * Copyright 2003-2021 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "config.h"
21 #include "Main.hxx"
22 #include "Instance.hxx"
23 #include "CommandLine.hxx"
24 #include "PlaylistFile.hxx"
25 #include "MusicChunk.hxx"
26 #include "StateFile.hxx"
27 #include "Mapper.hxx"
28 #include "Permission.hxx"
29 #include "Listen.hxx"
30 #include "client/Config.hxx"
31 #include "client/List.hxx"
32 #include "command/AllCommands.hxx"
33 #include "Partition.hxx"
34 #include "tag/Config.hxx"
35 #include "ReplayGainGlobal.hxx"
36 #include "IdleFlags.hxx"
37 #include "Log.hxx"
38 #include "LogInit.hxx"
39 #include "input/Init.hxx"
40 #include "input/cache/Config.hxx"
41 #include "input/cache/Manager.hxx"
42 #include "event/Loop.hxx"
43 #include "event/Call.hxx"
44 #include "fs/AllocatedPath.hxx"
45 #include "fs/Config.hxx"
46 #include "playlist/PlaylistRegistry.hxx"
47 #include "zeroconf/Glue.hxx"
48 #include "decoder/DecoderList.hxx"
49 #include "pcm/AudioParser.hxx"
50 #include "pcm/Convert.hxx"
51 #include "unix/SignalHandlers.hxx"
52 #include "thread/Slack.hxx"
53 #include "net/Init.hxx"
54 #include "lib/icu/Init.hxx"
55 #include "config/Check.hxx"
56 #include "config/Data.hxx"
57 #include "config/Param.hxx"
58 #include "config/Path.hxx"
59 #include "config/Defaults.hxx"
60 #include "config/Option.hxx"
61 #include "config/Domain.hxx"
62 #include "config/Parser.hxx"
63 #include "util/RuntimeError.hxx"
64 #include "util/ScopeExit.hxx"
65 
66 #ifdef ENABLE_DAEMON
67 #include "unix/Daemon.hxx"
68 #endif
69 
70 #ifdef ENABLE_DATABASE
71 #include "db/update/Service.hxx"
72 #include "db/Configured.hxx"
73 #include "db/DatabasePlugin.hxx"
74 #include "db/plugins/simple/SimpleDatabasePlugin.hxx"
75 #include "storage/Configured.hxx"
76 #include "storage/CompositeStorage.hxx"
77 #ifdef ENABLE_INOTIFY
78 #include "db/update/InotifyUpdate.hxx"
79 #endif
80 #endif
81 
82 #ifdef ENABLE_NEIGHBOR_PLUGINS
83 #include "neighbor/Glue.hxx"
84 #endif
85 
86 #ifdef ENABLE_SQLITE
87 #include "sticker/Database.hxx"
88 #endif
89 
90 #ifdef ENABLE_ARCHIVE
91 #include "archive/ArchiveList.hxx"
92 #endif
93 
94 #ifdef ANDROID
95 #include "java/Global.hxx"
96 #include "java/File.hxx"
97 #include "android/Environment.hxx"
98 #include "android/Context.hxx"
99 #include "android/LogListener.hxx"
100 #include "config/File.hxx"
101 #include "fs/FileSystem.hxx"
102 #include "org_musicpd_Bridge.h"
103 #endif
104 
105 #ifdef ENABLE_DBUS
106 #include "lib/dbus/Init.hxx"
107 #endif
108 
109 #ifdef ENABLE_SYSTEMD_DAEMON
110 #include <systemd/sd-daemon.h>
111 #endif
112 
113 #include <climits>
114 
115 #ifndef ANDROID
116 #include <clocale>
117 #endif
118 
119 static constexpr size_t KILOBYTE = 1024;
120 static constexpr size_t MEGABYTE = 1024 * KILOBYTE;
121 
122 static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE;
123 
124 static constexpr
125 size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32,
126 				  64 * KILOBYTE);
127 
128 #ifdef ANDROID
129 Context *context;
130 LogListener *logListener;
131 #endif
132 
133 Instance *global_instance;
134 
135 struct Config {
136 	ReplayGainConfig replay_gain;
137 
ConfigConfig138 	explicit Config(const ConfigData &raw)
139 		:replay_gain(LoadReplayGainConfig(raw)) {}
140 };
141 
142 #ifdef ENABLE_DAEMON
143 
144 static void
glue_daemonize_init(const CommandLineOptions & options,const ConfigData & config)145 glue_daemonize_init(const CommandLineOptions &options,
146 		    const ConfigData &config)
147 {
148 	auto pid_file = config.GetPath(ConfigOption::PID_FILE);
149 
150 #ifdef __linux__
151 	if (options.systemd && pid_file != nullptr) {
152 		pid_file = nullptr;
153 		fprintf(stderr,
154 			"Ignoring the 'pid_file' setting in systemd mode\n");
155 	}
156 #endif
157 
158 	daemonize_init(config.GetString(ConfigOption::USER),
159 		       config.GetString(ConfigOption::GROUP),
160 		       std::move(pid_file));
161 
162 	if (options.kill)
163 		daemonize_kill();
164 }
165 
166 #endif
167 
168 static void
glue_mapper_init(const ConfigData & config)169 glue_mapper_init(const ConfigData &config)
170 {
171 	auto playlist_directory = config.GetPath(ConfigOption::PLAYLIST_DIR);
172 
173 #ifdef ANDROID
174 	/* if there is no explicit configuration, store playlists in
175 	   "/sdcard/Android/data/org.musicpd/files/playlists" */
176 	if (playlist_directory.IsNull())
177 		playlist_directory = context->GetExternalFilesDir(Java::GetEnv(),
178 								  "playlists");
179 #endif
180 
181 	mapper_init(std::move(playlist_directory));
182 }
183 
184 #ifdef ENABLE_DATABASE
185 
186 static void
InitStorage(Instance & instance,EventLoop & event_loop,const ConfigData & config)187 InitStorage(Instance &instance, EventLoop &event_loop,
188 	    const ConfigData &config)
189 {
190 	auto storage = CreateConfiguredStorage(config, event_loop);
191 	if (storage == nullptr)
192 		return;
193 
194 	auto *composite = new CompositeStorage();
195 	instance.storage = composite;
196 	composite->Mount("", std::move(storage));
197 }
198 
199 /**
200  * Returns the database.  If this function returns false, this has not
201  * succeeded, and the caller should create the database after the
202  * process has been daemonized.
203  */
204 static bool
glue_db_init_and_load(Instance & instance,const ConfigData & config)205 glue_db_init_and_load(Instance &instance, const ConfigData &config)
206 {
207 	auto db = CreateConfiguredDatabase(config, instance.event_loop,
208 					   instance.io_thread.GetEventLoop(),
209 					   instance);
210 	if (!db)
211 		return true;
212 
213 	if (db->GetPlugin().RequireStorage()) {
214 		InitStorage(instance, instance.io_thread.GetEventLoop(),
215 			    config);
216 
217 		if (instance.storage == nullptr) {
218 			LogNotice(config_domain,
219 				  "Found database setting without "
220 				  "music_directory - disabling database");
221 			return true;
222 		}
223 	} else {
224 		if (IsStorageConfigured(config))
225 			LogNotice(config_domain,
226 				  "Ignoring the storage configuration "
227 				  "because the database does not need it");
228 	}
229 
230 	try {
231 		db->Open();
232 	} catch (...) {
233 		std::throw_with_nested(std::runtime_error("Failed to open database plugin"));
234 	}
235 
236 	instance.database = std::move(db);
237 
238 	auto *sdb = dynamic_cast<SimpleDatabase *>(instance.database.get());
239 	if (sdb == nullptr)
240 		return true;
241 
242 	instance.update = new UpdateService(config,
243 					    instance.event_loop, *sdb,
244 					    static_cast<CompositeStorage &>(*instance.storage),
245 					    instance);
246 
247 	/* run database update after daemonization? */
248 	return sdb->FileExists();
249 }
250 
251 static bool
InitDatabaseAndStorage(Instance & instance,const ConfigData & config)252 InitDatabaseAndStorage(Instance &instance, const ConfigData &config)
253 {
254 	const bool create_db = !glue_db_init_and_load(instance, config);
255 	return create_db;
256 }
257 
258 #endif
259 
260 #ifdef ENABLE_SQLITE
261 
262 /**
263  * Configure and initialize the sticker subsystem.
264  */
265 static std::unique_ptr<StickerDatabase>
LoadStickerDatabase(const ConfigData & config)266 LoadStickerDatabase(const ConfigData &config)
267 {
268 	auto sticker_file = config.GetPath(ConfigOption::STICKER_FILE);
269 	if (sticker_file.IsNull())
270 		return nullptr;
271 
272 	return std::make_unique<StickerDatabase>(std::move(sticker_file));
273 }
274 
275 #endif
276 
277 static void
glue_state_file_init(Instance & instance,const ConfigData & raw_config)278 glue_state_file_init(Instance &instance, const ConfigData &raw_config)
279 {
280 	StateFileConfig config(raw_config);
281 	if (!config.IsEnabled())
282 		return;
283 
284 	instance.state_file = std::make_unique< StateFile>(std::move(config),
285 							   instance.partitions.front(),
286 							   instance.event_loop);
287 	instance.state_file->Read();
288 }
289 
290 /**
291  * Initialize the decoder and player core, including the music pipe.
292  */
293 static void
initialize_decoder_and_player(Instance & instance,const ConfigData & config,const ReplayGainConfig & replay_gain_config)294 initialize_decoder_and_player(Instance &instance,
295 			      const ConfigData &config,
296 			      const ReplayGainConfig &replay_gain_config)
297 {
298 	const ConfigParam *param;
299 
300 	size_t buffer_size;
301 	param = config.GetParam(ConfigOption::AUDIO_BUFFER_SIZE);
302 	if (param != nullptr) {
303 		buffer_size = param->With([](const char *s){
304 			size_t result = ParseSize(s, KILOBYTE);
305 			if (result <= 0)
306 				throw FormatRuntimeError("buffer size \"%s\" is not a "
307 							 "positive integer", s);
308 
309 			if (result < MIN_BUFFER_SIZE) {
310 				FmtWarning(config_domain, "buffer size {} is too small, using {} bytes instead",
311 					   result, MIN_BUFFER_SIZE);
312 				result = MIN_BUFFER_SIZE;
313 			}
314 
315 			return result;
316 		});
317 	} else
318 		buffer_size = DEFAULT_BUFFER_SIZE;
319 
320 	const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
321 
322 	if (buffered_chunks >= 1 << 15)
323 		throw FormatRuntimeError("buffer size \"%lu\" is too big",
324 					 (unsigned long)buffer_size);
325 
326 	const unsigned max_length =
327 		config.GetPositive(ConfigOption::MAX_PLAYLIST_LENGTH,
328 				   DEFAULT_PLAYLIST_MAX_LENGTH);
329 
330 	AudioFormat configured_audio_format = config.With(ConfigOption::AUDIO_OUTPUT_FORMAT, [](const char *s){
331 		if (s == nullptr)
332 			return AudioFormat::Undefined();
333 
334 		return ParseAudioFormat(s, true);
335 	});
336 
337 	instance.partitions.emplace_back(instance,
338 					 "default",
339 					 max_length,
340 					 buffered_chunks,
341 					 configured_audio_format,
342 					 replay_gain_config);
343 	auto &partition = instance.partitions.back();
344 
345 	partition.replay_gain_mode = config.With(ConfigOption::REPLAYGAIN, [](const char *s){
346 		return s != nullptr
347 			? FromString(s)
348 			: ReplayGainMode::OFF;
349 	});
350 }
351 
352 inline void
BeginShutdownUpdate()353 Instance::BeginShutdownUpdate() noexcept
354 {
355 #ifdef ENABLE_DATABASE
356 #ifdef ENABLE_INOTIFY
357 	inotify_update.reset();
358 #endif
359 
360 	if (update != nullptr)
361 		update->CancelAllAsync();
362 #endif
363 }
364 
365 inline void
BeginShutdownPartitions()366 Instance::BeginShutdownPartitions() noexcept
367 {
368 	for (auto &partition : partitions) {
369 		partition.BeginShutdown();
370 	}
371 }
372 
373 static inline void
MainConfigured(const CommandLineOptions & options,const ConfigData & raw_config)374 MainConfigured(const CommandLineOptions &options,
375 	       const ConfigData &raw_config)
376 {
377 #ifdef ENABLE_DAEMON
378 	daemonize_close_stdin();
379 #endif
380 
381 #ifndef ANDROID
382 	/* initialize locale */
383 	std::setlocale(LC_CTYPE,"");
384 	std::setlocale(LC_COLLATE, "");
385 #endif
386 
387 	const ScopeIcuInit icu_init;
388 	const ScopeNetInit net_init;
389 
390 #ifdef ENABLE_DBUS
391 	const ODBus::ScopeInit dbus_init;
392 #endif
393 
394 	InitPathParser(raw_config);
395 	const Config config(raw_config);
396 
397 #ifdef ENABLE_DAEMON
398 	glue_daemonize_init(options, raw_config);
399 #endif
400 
401 	TagLoadConfig(raw_config);
402 
403 	log_init(raw_config, options.verbose, options.log_stderr);
404 
405 	Instance instance;
406 	global_instance = &instance;
407 
408 #ifdef ENABLE_NEIGHBOR_PLUGINS
409 	instance.neighbors = std::make_unique<NeighborGlue>();
410 	instance.neighbors->Init(raw_config,
411 				 instance.io_thread.GetEventLoop(),
412 				 instance);
413 
414 	if (instance.neighbors->IsEmpty())
415 		instance.neighbors.reset();
416 #endif
417 
418 	const unsigned max_clients =
419 		raw_config.GetPositive(ConfigOption::MAX_CONN, 100);
420 	instance.client_list = std::make_unique<ClientList>(max_clients);
421 
422 	const auto *input_cache_config = raw_config.GetBlock(ConfigBlockOption::INPUT_CACHE);
423 	if (input_cache_config != nullptr) {
424 		const InputCacheConfig c(*input_cache_config);
425 		instance.input_cache = std::make_unique<InputCacheManager>(c);
426 	}
427 
428 	initialize_decoder_and_player(instance,
429 				      raw_config, config.replay_gain);
430 
431 	listen_global_init(raw_config, *instance.partitions.front().listener);
432 
433 #ifdef ENABLE_DAEMON
434 	daemonize_set_user();
435 	daemonize_begin(options.daemon);
436 	AtScopeExit() { daemonize_finish(); };
437 #endif
438 
439 	ConfigureFS(raw_config);
440 	AtScopeExit() { DeinitFS(); };
441 
442 	glue_mapper_init(raw_config);
443 
444 	initPermissions(raw_config);
445 	spl_global_init(raw_config);
446 #ifdef ENABLE_ARCHIVE
447 	const ScopeArchivePluginsInit archive_plugins_init;
448 #endif
449 
450 	pcm_convert_global_init(raw_config);
451 
452 	const ScopeDecoderPluginsInit decoder_plugins_init(raw_config);
453 
454 #ifdef ENABLE_DATABASE
455 	const bool create_db = InitDatabaseAndStorage(instance, raw_config);
456 #endif
457 
458 #ifdef ENABLE_SQLITE
459 	instance.sticker_database = LoadStickerDatabase(raw_config);
460 #endif
461 
462 	command_init();
463 
464 	for (auto &partition : instance.partitions) {
465 		partition.outputs.Configure(instance.io_thread.GetEventLoop(),
466 					    instance.rtio_thread.GetEventLoop(),
467 					    raw_config,
468 					    config.replay_gain);
469 		partition.UpdateEffectiveReplayGainMode();
470 	}
471 
472 	client_manager_init(raw_config);
473 	const ScopeInputPluginsInit input_plugins_init(raw_config,
474 						       instance.io_thread.GetEventLoop());
475 
476 	const ScopePlaylistPluginsInit playlist_plugins_init(raw_config);
477 
478 #ifdef ENABLE_DAEMON
479 	daemonize_commit();
480 #endif
481 
482 #ifndef ANDROID
483 	setup_log_output();
484 
485 	const ScopeSignalHandlersInit signal_handlers_init(instance);
486 #endif
487 
488 	instance.io_thread.Start();
489 	instance.rtio_thread.Start();
490 
491 #ifdef ENABLE_NEIGHBOR_PLUGINS
492 	if (instance.neighbors != nullptr)
493 		instance.neighbors->Open();
494 
495 	AtScopeExit(&instance) {
496 		if (instance.neighbors != nullptr)
497 			instance.neighbors->Close();
498 	};
499 #endif
500 
501 #ifdef HAVE_ZEROCONF
502 	std::unique_ptr<ZeroconfHelper> zeroconf;
503 	try {
504 		auto &event_loop = instance.io_thread.GetEventLoop();
505 		BlockingCall(event_loop, [&](){
506 			zeroconf = ZeroconfInit(raw_config, event_loop);
507 		});
508 	} catch (...) {
509 		LogError(std::current_exception(),
510 			 "Zeroconf initialization failed");
511 	}
512 
513 	AtScopeExit(&zeroconf, &instance) {
514 		if (zeroconf) {
515 			auto &event_loop = instance.io_thread.GetEventLoop();
516 			BlockingCall(event_loop, [&](){
517 				zeroconf.reset();
518 			});
519 		}
520 	};
521 #endif
522 
523 #ifdef ENABLE_DATABASE
524 	if (create_db) {
525 		/* the database failed to load: recreate the
526 		   database */
527 		instance.update->Enqueue("", true);
528 	}
529 #endif
530 
531 	glue_state_file_init(instance, raw_config);
532 
533 #ifdef ENABLE_DATABASE
534 	if (raw_config.GetBool(ConfigOption::AUTO_UPDATE, false)) {
535 #ifdef ENABLE_INOTIFY
536 		if (instance.storage != nullptr &&
537 		    instance.update != nullptr) {
538 			try {
539 				instance.inotify_update =
540 					mpd_inotify_init(instance.event_loop,
541 							 *instance.storage,
542 							 *instance.update,
543 							 raw_config.GetUnsigned(ConfigOption::AUTO_UPDATE_DEPTH,
544 										INT_MAX));
545 			} catch (...) {
546 				LogError(std::current_exception());
547 			}
548 		}
549 #else
550 		LogWarning(config_domain,
551 			   "inotify: auto_update was disabled. enable during compilation phase");
552 #endif
553 	}
554 #endif
555 
556 	Check(raw_config);
557 
558 	/* enable all audio outputs (if not already done by
559 	   playlist_state_restore() */
560 	for (auto &partition : instance.partitions)
561 		partition.pc.LockUpdateAudio();
562 
563 #ifdef _WIN32
564 	win32_app_started();
565 #endif
566 
567 	/* the MPD frontend does not care about timer slack; set it to
568 	   a huge value to allow the kernel to reduce CPU wakeups */
569 	SetThreadTimerSlack(std::chrono::milliseconds(100));
570 
571 #ifdef ENABLE_SYSTEMD_DAEMON
572 	sd_notify(0, "READY=1");
573 #endif
574 
575 	/* run the main loop */
576 	instance.event_loop.Run();
577 
578 #ifdef _WIN32
579 	win32_app_stopping();
580 #endif
581 
582 	/* cleanup */
583 
584 	if (instance.state_file)
585 		instance.state_file->Write();
586 
587 	instance.BeginShutdownUpdate();
588 	instance.BeginShutdownPartitions();
589 }
590 
591 #ifdef ANDROID
592 
593 static void
AndroidMain()594 AndroidMain()
595 {
596 	CommandLineOptions options;
597 	ConfigData raw_config;
598 
599 	const auto sdcard = Environment::getExternalStorageDirectory();
600 	if (!sdcard.IsNull()) {
601 		const auto config_path =
602 			sdcard / Path::FromFS("mpd.conf");
603 		if (FileExists(config_path))
604 			ReadConfigFile(raw_config, config_path);
605 	}
606 
607 	MainConfigured(options, raw_config);
608 }
609 
610 gcc_visibility_default
611 JNIEXPORT void JNICALL
Java_org_musicpd_Bridge_run(JNIEnv * env,jclass,jobject _context,jobject _logListener)612 Java_org_musicpd_Bridge_run(JNIEnv *env, jclass, jobject _context, jobject _logListener)
613 {
614 	Java::Init(env);
615 	Java::Object::Initialise(env);
616 	Java::File::Initialise(env);
617 	Environment::Initialise(env);
618 	AtScopeExit(env) { Environment::Deinitialise(env); };
619 
620 	context = new Context(env, _context);
621 	AtScopeExit() { delete context; };
622 
623 	if (_logListener != nullptr)
624 		logListener = new LogListener(env, _logListener);
625 	AtScopeExit() { delete logListener; };
626 
627 	try {
628 		AndroidMain();
629 	} catch (...) {
630 		LogError(std::current_exception());
631 	}
632 }
633 
634 gcc_visibility_default
635 JNIEXPORT void JNICALL
Java_org_musicpd_Bridge_shutdown(JNIEnv *,jclass)636 Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass)
637 {
638 	if (global_instance != nullptr)
639 		global_instance->Break();
640 }
641 
642 gcc_visibility_default
643 JNIEXPORT void JNICALL
Java_org_musicpd_Bridge_pause(JNIEnv *,jclass)644 Java_org_musicpd_Bridge_pause(JNIEnv *, jclass)
645 {
646 	if (global_instance != nullptr)
647 		for (auto &partition : global_instance->partitions)
648 			partition.pc.LockSetPause(true);
649 }
650 
651 #else
652 
653 static inline void
MainOrThrow(int argc,char * argv[])654 MainOrThrow(int argc, char *argv[])
655 {
656 	CommandLineOptions options;
657 	ConfigData raw_config;
658 
659 	ParseCommandLine(argc, argv, options, raw_config);
660 
661 	MainConfigured(options, raw_config);
662 }
663 
664 int
mpd_main(int argc,char * argv[])665 mpd_main(int argc, char *argv[])
666 {
667 	MainOrThrow(argc, argv);
668 	return EXIT_SUCCESS;
669 }
670 
671 int
main(int argc,char * argv[])672 main(int argc, char *argv[]) noexcept
673 try {
674 	AtScopeExit() { log_deinit(); };
675 
676 #ifdef _WIN32
677 	return win32_main(argc, argv);
678 #else
679 	return mpd_main(argc, argv);
680 #endif
681 } catch (...) {
682 	LogError(std::current_exception());
683 	return EXIT_FAILURE;
684 }
685 
686 #endif
687