From d536944beb783ec098aa6215fc94d8e60cfd310d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 4 Jan 2013 22:42:05 +0100 Subject: [PATCH] Partition: new class, container for Playlist and PlayerControl This is the beginning of multi-player support. There will be support for multiple Partition objects in one MPD process. --- Makefile.am | 1 + src/Listen.cxx | 4 ++-- src/Main.cxx | 34 ++++++++++++++++-------------- src/Main.hxx | 2 +- src/Partition.hxx | 47 ++++++++++++++++++++++++++++++++++++++++++ src/Playlist.hxx | 8 +------ src/PlaylistGlobal.cxx | 18 +++++----------- src/StateFile.cxx | 34 ++++++++++++++++-------------- src/StateFile.hxx | 6 +++--- src/UpdateGlue.cxx | 4 ++-- src/UpdateRemove.cxx | 5 ++++- 11 files changed, 103 insertions(+), 60 deletions(-) create mode 100644 src/Partition.hxx diff --git a/Makefile.am b/Makefile.am index ebb7fdf2d..d4761c950 100644 --- a/Makefile.am +++ b/Makefile.am @@ -262,6 +262,7 @@ src_mpd_SOURCES = \ src/path.c \ src/Mapper.cxx src/Mapper.hxx \ src/page.c \ + src/Partition.hxx \ src/Permission.cxx src/Permission.hxx \ src/PlayerThread.cxx src/PlayerThread.hxx \ src/PlayerControl.cxx src/PlayerControl.hxx \ diff --git a/src/Listen.cxx b/src/Listen.cxx index 8741da9c2..3ea9bae9a 100644 --- a/src/Listen.cxx +++ b/src/Listen.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "Listen.hxx" #include "Main.hxx" -#include "Playlist.hxx" +#include "Partition.hxx" #include "Client.hxx" extern "C" { @@ -47,7 +47,7 @@ static void listen_callback(int fd, const struct sockaddr *address, size_t address_length, int uid, G_GNUC_UNUSED void *ctx) { - client_new(g_playlist, global_player_control, + client_new(global_partition->playlist, &global_partition->pc, fd, address, address_length, uid); } diff --git a/src/Main.cxx b/src/Main.cxx index a8f6d55ee..371602247 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -20,9 +20,7 @@ #include "config.h" #include "Main.hxx" #include "CommandLine.hxx" -#include "Playlist.hxx" #include "PlaylistFile.hxx" -#include "PlayerControl.hxx" #include "UpdateGlue.hxx" #include "MusicChunk.hxx" #include "StateFile.hxx" @@ -35,6 +33,7 @@ #include "ClientIdle.hxx" #include "Client.hxx" #include "AllCommands.hxx" +#include "Partition.hxx" extern "C" { #include "daemon.h" @@ -100,7 +99,7 @@ GMainLoop *main_loop; GCond *main_cond; -struct player_control *global_player_control; +Partition *global_partition; static bool glue_daemonize_init(const struct options *options, GError **error_r) @@ -231,7 +230,7 @@ glue_state_file_init(GError **error_r) return false; } - state_file_init(path, global_player_control); + state_file_init(path, *global_partition); g_free(path); return true; @@ -306,8 +305,13 @@ initialize_decoder_and_player(void) if (buffered_before_play > buffered_chunks) buffered_before_play = buffered_chunks; - global_player_control = new player_control(buffered_chunks, - buffered_before_play); + const unsigned max_length = + config_get_positive(CONF_MAX_PLAYLIST_LENGTH, + DEFAULT_PLAYLIST_MAX_LENGTH); + + global_partition = new Partition(max_length, + buffered_chunks, + buffered_before_play); } /** @@ -414,8 +418,7 @@ int mpd_main(int argc, char *argv[]) } initPermissions(); - playlist_global_init(config_get_positive(CONF_MAX_PLAYLIST_LENGTH, - DEFAULT_PLAYLIST_MAX_LENGTH)); + playlist_global_init(); spl_global_init(); #ifdef ENABLE_ARCHIVE archive_plugin_init_all(); @@ -438,7 +441,7 @@ int mpd_main(int argc, char *argv[]) initialize_decoder_and_player(); volume_init(); initAudioConfig(); - audio_output_all_init(global_player_control); + audio_output_all_init(&global_partition->pc); client_manager_init(); replay_gain_global_init(); @@ -464,7 +467,7 @@ int mpd_main(int argc, char *argv[]) initZeroconf(); - player_create(global_player_control); + player_create(&global_partition->pc); if (create_db) { /* the database failed to load: recreate the @@ -480,7 +483,7 @@ int mpd_main(int argc, char *argv[]) return EXIT_FAILURE; } - audio_output_all_set_replay_gain_mode(replay_gain_get_real_mode(g_playlist.queue.random)); + audio_output_all_set_replay_gain_mode(replay_gain_get_real_mode(global_partition->playlist.queue.random)); success = config_get_bool(CONF_AUTO_UPDATE, false); #ifdef ENABLE_INOTIFY @@ -496,7 +499,7 @@ int mpd_main(int argc, char *argv[]) /* enable all audio outputs (if not already done by playlist_state_restore() */ - pc_update_audio(global_player_control); + pc_update_audio(&global_partition->pc); #ifdef WIN32 win32_app_started(); @@ -517,12 +520,11 @@ int mpd_main(int argc, char *argv[]) mpd_inotify_finish(); #endif - state_file_finish(global_player_control); - pc_kill(global_player_control); + state_file_finish(*global_partition); + pc_kill(&global_partition->pc); finishZeroconf(); client_manager_deinit(); listen_global_finish(); - playlist_global_finish(); start = clock(); DatabaseGlobalDeinit(); @@ -542,7 +544,7 @@ int mpd_main(int argc, char *argv[]) volume_finish(); mapper_finish(); path_global_finish(); - delete global_player_control; + delete global_partition; command_finish(); update_global_finish(); decoder_plugin_deinit_all(); diff --git a/src/Main.hxx b/src/Main.hxx index 54916ff4b..6d61843a8 100644 --- a/src/Main.hxx +++ b/src/Main.hxx @@ -28,7 +28,7 @@ extern GMainLoop *main_loop; extern GCond *main_cond; -extern struct player_control *global_player_control; +extern struct Partition *global_partition; /** * A entry point for application. diff --git a/src/Partition.hxx b/src/Partition.hxx new file mode 100644 index 000000000..b91a4b6f9 --- /dev/null +++ b/src/Partition.hxx @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2003-2013 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_PARTITION_HXX +#define MPD_PARTITION_HXX + +#include "Playlist.hxx" +#include "PlayerControl.hxx" + +/** + * A partition of the Music Player Daemon. It is a separate unit with + * a playlist, a player, outputs etc. + */ +struct Partition { + struct playlist playlist; + + player_control pc; + + Partition(unsigned max_length, + unsigned buffer_chunks, + unsigned buffered_before_play) + :pc(buffer_chunks, buffered_before_play) { + playlist_init(&playlist, max_length); + } + + ~Partition() { + playlist_finish(&playlist); + } +}; + +#endif diff --git a/src/Playlist.hxx b/src/Playlist.hxx index 3256f6422..163d17afe 100644 --- a/src/Playlist.hxx +++ b/src/Playlist.hxx @@ -70,14 +70,8 @@ struct playlist { int queued; }; -/** the global playlist object */ -extern struct playlist g_playlist; - void -playlist_global_init(unsigned max_length); - -void -playlist_global_finish(void); +playlist_global_init(); void playlist_init(struct playlist *playlist, unsigned max_length); diff --git a/src/PlaylistGlobal.cxx b/src/PlaylistGlobal.cxx index d9685a2be..92572cde9 100644 --- a/src/PlaylistGlobal.cxx +++ b/src/PlaylistGlobal.cxx @@ -25,36 +25,28 @@ #include "config.h" #include "Playlist.hxx" #include "Main.hxx" +#include "Partition.hxx" extern "C" { #include "event_pipe.h" } -struct playlist g_playlist; - static void playlist_tag_event(void) { - playlist_tag_changed(&g_playlist); + playlist_tag_changed(&global_partition->playlist); } static void playlist_event(void) { - playlist_sync(&g_playlist, global_player_control); + playlist_sync(&global_partition->playlist, + &global_partition->pc); } void -playlist_global_init(unsigned max_length) +playlist_global_init() { - playlist_init(&g_playlist, max_length); - event_pipe_register(PIPE_EVENT_TAG, playlist_tag_event); event_pipe_register(PIPE_EVENT_PLAYLIST, playlist_event); } - -void -playlist_global_finish(void) -{ - playlist_finish(&g_playlist); -} diff --git a/src/StateFile.cxx b/src/StateFile.cxx index db6635025..1d77b77de 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -20,9 +20,9 @@ #include "config.h" #include "StateFile.hxx" #include "OutputState.hxx" -#include "Playlist.hxx" #include "PlaylistState.hxx" #include "TextFile.hxx" +#include "Partition.hxx" extern "C" { #include "volume.h" @@ -49,7 +49,7 @@ static unsigned prev_volume_version, prev_output_version, prev_playlist_version; static void -state_file_write(struct player_control *pc) +state_file_write(Partition &partition) { FILE *fp; @@ -66,17 +66,18 @@ state_file_write(struct player_control *pc) save_sw_volume_state(fp); audio_output_state_save(fp); - playlist_state_save(fp, &g_playlist, pc); + playlist_state_save(fp, &partition.playlist, &partition.pc); fclose(fp); prev_volume_version = sw_volume_state_get_hash(); prev_output_version = audio_output_state_get_version(); - prev_playlist_version = playlist_state_get_hash(&g_playlist, pc); + prev_playlist_version = playlist_state_get_hash(&partition.playlist, + &partition.pc); } static void -state_file_read(struct player_control *pc) +state_file_read(Partition &partition) { bool success; @@ -95,14 +96,16 @@ state_file_read(struct player_control *pc) while ((line = file.ReadLine()) != NULL) { success = read_sw_volume_state(line) || audio_output_state_read(line) || - playlist_state_restore(line, file, &g_playlist, pc); + playlist_state_restore(line, file, &partition.playlist, + &partition.pc); if (!success) g_warning("Unrecognized line in state file: %s", line); } prev_volume_version = sw_volume_state_get_hash(); prev_output_version = audio_output_state_get_version(); - prev_playlist_version = playlist_state_get_hash(&g_playlist, pc); + prev_playlist_version = playlist_state_get_hash(&partition.playlist, + &partition.pc); } /** @@ -112,21 +115,22 @@ state_file_read(struct player_control *pc) static gboolean timer_save_state_file(gpointer data) { - struct player_control *pc = (struct player_control *)data; + Partition &partition = *(Partition *)data; if (prev_volume_version == sw_volume_state_get_hash() && prev_output_version == audio_output_state_get_version() && - prev_playlist_version == playlist_state_get_hash(&g_playlist, pc)) + prev_playlist_version == playlist_state_get_hash(&partition.playlist, + &partition.pc)) /* nothing has changed - don't save the state file, don't spin up the hard disk */ return true; - state_file_write(pc); + state_file_write(partition); return true; } void -state_file_init(const char *path, struct player_control *pc) +state_file_init(const char *path, Partition &partition) { assert(state_file_path == NULL); @@ -134,15 +138,15 @@ state_file_init(const char *path, struct player_control *pc) return; state_file_path = g_strdup(path); - state_file_read(pc); + state_file_read(partition); save_state_source_id = g_timeout_add_seconds(5 * 60, timer_save_state_file, - pc); + &partition); } void -state_file_finish(struct player_control *pc) +state_file_finish(Partition &partition) { if (state_file_path == NULL) /* no state file configured, no cleanup required */ @@ -151,7 +155,7 @@ state_file_finish(struct player_control *pc) if (save_state_source_id != 0) g_source_remove(save_state_source_id); - state_file_write(pc); + state_file_write(partition); g_free(state_file_path); } diff --git a/src/StateFile.hxx b/src/StateFile.hxx index 77629aba9..35269fe40 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -20,13 +20,13 @@ #ifndef MPD_STATE_FILE_HXX #define MPD_STATE_FILE_HXX -struct player_control; +struct Partition; void -state_file_init(const char *path, struct player_control *pc); +state_file_init(const char *path, Partition &partition); void -state_file_finish(struct player_control *pc); +state_file_finish(Partition &partition); void write_state_file(void); diff --git a/src/UpdateGlue.cxx b/src/UpdateGlue.cxx index cb1600d4f..2edd19cc2 100644 --- a/src/UpdateGlue.cxx +++ b/src/UpdateGlue.cxx @@ -24,7 +24,6 @@ #include "UpdateRemove.hxx" #include "Mapper.hxx" #include "DatabaseSimple.hxx" -#include "Playlist.hxx" extern "C" { #include "event_pipe.h" @@ -33,6 +32,7 @@ extern "C" { } #include "Main.hxx" +#include "Partition.hxx" #include "mpd_error.h" #include @@ -155,7 +155,7 @@ static void update_finished_event(void) if (modified) { /* send "idle" events */ - playlist_increment_version_all(&g_playlist); + playlist_increment_version_all(&global_partition->playlist); idle_add(IDLE_DATABASE); } diff --git a/src/UpdateRemove.cxx b/src/UpdateRemove.cxx index 814c803b2..c1a0cd32b 100644 --- a/src/UpdateRemove.cxx +++ b/src/UpdateRemove.cxx @@ -20,6 +20,7 @@ #include "config.h" /* must be first for large file support */ #include "UpdateRemove.hxx" #include "Playlist.hxx" +#include "Partition.hxx" extern "C" { #include "event_pipe.h" @@ -63,7 +64,9 @@ song_remove_event(void) sticker_song_delete(removed_song); #endif - playlist_delete_song(&g_playlist, global_player_control, removed_song); + playlist_delete_song(&global_partition->playlist, + &global_partition->pc, + removed_song); /* clear "removed_song" and send signal to update thread */ g_mutex_lock(remove_mutex);