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.
This commit is contained in:
parent
1a8ef3cdab
commit
d536944beb
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
34
src/Main.cxx
34
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();
|
||||
|
@ -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.
|
||||
|
47
src/Partition.hxx
Normal file
47
src/Partition.hxx
Normal file
@ -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
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 <glib.h>
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user