decoder_control.c 4.31 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2010 The Music Player Daemon Project
3
 * http://www.musicpd.org
Max Kellermann's avatar
Max Kellermann committed
4 5 6 7 8 9 10 11 12 13
 *
 * 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.
14 15 16 17
 *
 * 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.
Max Kellermann's avatar
Max Kellermann committed
18 19
 */

20
#include "config.h"
21
#include "decoder_control.h"
22
#include "player_control.h"
23
#include "pipe.h"
24

25
#include <assert.h>
26 27 28

#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "decoder_control"
29

30 31
void
dc_init(struct decoder_control *dc)
32
{
33 34 35 36
	dc->thread = NULL;

	dc->mutex = g_mutex_new();
	dc->cond = g_cond_new();
37

38 39
	dc->state = DECODE_STATE_STOP;
	dc->command = DECODE_COMMAND_NONE;
40

41 42
	dc->replay_gain_db = 0;
	dc->replay_gain_prev_db = 0;
43 44 45
	dc->mixramp_start = NULL;
	dc->mixramp_end = NULL;
	dc->mixramp_prev_end = NULL;
46 47
}

48 49
void
dc_deinit(struct decoder_control *dc)
50
{
51 52
	g_cond_free(dc->cond);
	g_mutex_free(dc->mutex);
53 54 55
	g_free(dc->mixramp_start);
	g_free(dc->mixramp_end);
	g_free(dc->mixramp_prev_end);
56 57 58
	dc->mixramp_start = NULL;
	dc->mixramp_end = NULL;
	dc->mixramp_prev_end = NULL;
59 60
}

61
static void
62
dc_command_wait_locked(struct decoder_control *dc)
Max Kellermann's avatar
Max Kellermann committed
63
{
64
	while (dc->command != DECODE_COMMAND_NONE)
65
		player_wait_decoder(dc);
Max Kellermann's avatar
Max Kellermann committed
66 67
}

68
void
69
dc_command_wait(struct decoder_control *dc)
70
{
71 72 73
	decoder_lock(dc);
	dc_command_wait_locked(dc);
	decoder_unlock(dc);
74 75
}

76
static void
77
dc_command_locked(struct decoder_control *dc, enum decoder_command cmd)
Max Kellermann's avatar
Max Kellermann committed
78
{
79
	dc->command = cmd;
80
	decoder_signal(dc);
81
	dc_command_wait_locked(dc);
82 83 84
}

static void
85
dc_command(struct decoder_control *dc, enum decoder_command cmd)
86
{
87 88 89
	decoder_lock(dc);
	dc_command_locked(dc, cmd);
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
90 91
}

92 93
static void
dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
Max Kellermann's avatar
Max Kellermann committed
94
{
95
	decoder_lock(dc);
96

97 98
	dc->command = cmd;
	decoder_signal(dc);
99

100
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
101 102
}

103
void
104 105
dc_start(struct decoder_control *dc, struct song *song,
	 struct music_buffer *buffer, struct music_pipe *pipe)
Max Kellermann's avatar
Max Kellermann committed
106 107
{
	assert(song != NULL);
108 109
	assert(buffer != NULL);
	assert(pipe != NULL);
110
	assert(music_pipe_empty(pipe));
Max Kellermann's avatar
Max Kellermann committed
111

112
	dc->song = song;
113 114
	dc->buffer = buffer;
	dc->pipe = pipe;
115
	dc_command(dc, DECODE_COMMAND_START);
Max Kellermann's avatar
Max Kellermann committed
116 117
}

118
void
119
dc_stop(struct decoder_control *dc)
Max Kellermann's avatar
Max Kellermann committed
120
{
121
	decoder_lock(dc);
122

123
	if (dc->command != DECODE_COMMAND_NONE)
124 125 126 127
		/* Attempt to cancel the current command.  If it's too
		   late and the decoder thread is already executing
		   the old command, we'll call STOP again in this
		   function (see below). */
128
		dc_command_locked(dc, DECODE_COMMAND_STOP);
129

130 131
	if (dc->state != DECODE_STATE_STOP && dc->state != DECODE_STATE_ERROR)
		dc_command_locked(dc, DECODE_COMMAND_STOP);
132

133
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
134 135
}

136
bool
137
dc_seek(struct decoder_control *dc, double where)
Max Kellermann's avatar
Max Kellermann committed
138
{
139
	assert(dc->state != DECODE_STATE_START);
Max Kellermann's avatar
Max Kellermann committed
140 141
	assert(where >= 0.0);

142 143
	if (dc->state == DECODE_STATE_STOP ||
	    dc->state == DECODE_STATE_ERROR || !dc->seekable)
144
		return false;
Max Kellermann's avatar
Max Kellermann committed
145

146 147 148
	dc->seek_where = where;
	dc->seek_error = false;
	dc_command(dc, DECODE_COMMAND_SEEK);
Max Kellermann's avatar
Max Kellermann committed
149

150
	if (dc->seek_error)
151
		return false;
Max Kellermann's avatar
Max Kellermann committed
152

153
	return true;
Max Kellermann's avatar
Max Kellermann committed
154
}
155 156

void
157
dc_quit(struct decoder_control *dc)
158
{
159
	assert(dc->thread != NULL);
160

161 162
	dc->quit = true;
	dc_command_async(dc, DECODE_COMMAND_STOP);
163

164 165
	g_thread_join(dc->thread);
	dc->thread = NULL;
166
}
167 168 169 170 171 172

void
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start)
{
	assert(dc != NULL);

173
	g_free(dc->mixramp_start);
174 175 176 177 178 179 180 181 182
	dc->mixramp_start = mixramp_start;
	g_debug("mixramp_start = %s", mixramp_start ? mixramp_start : "NULL");
}

void
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end)
{
	assert(dc != NULL);

183
	g_free(dc->mixramp_end);
184 185 186 187 188 189 190 191 192
	dc->mixramp_end = mixramp_end;
	g_debug("mixramp_end = %s", mixramp_end ? mixramp_end : "NULL");
}

void
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end)
{
	assert(dc != NULL);

193
	g_free(dc->mixramp_prev_end);
194 195 196
	dc->mixramp_prev_end = mixramp_prev_end;
	g_debug("mixramp_prev_end = %s", mixramp_prev_end ? mixramp_prev_end : "NULL");
}