decoder_control.c 3.21 KB
Newer Older
1 2 3
/*
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 * 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

24 25
#include <assert.h>

26 27
void
dc_init(struct decoder_control *dc)
28
{
29 30 31 32
	dc->thread = NULL;

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

34 35
	dc->state = DECODE_STATE_STOP;
	dc->command = DECODE_COMMAND_NONE;
36 37
}

38 39
void
dc_deinit(struct decoder_control *dc)
40
{
41 42
	g_cond_free(dc->cond);
	g_mutex_free(dc->mutex);
43 44
}

45
static void
46
dc_command_wait_locked(struct decoder_control *dc)
Max Kellermann's avatar
Max Kellermann committed
47
{
48
	while (dc->command != DECODE_COMMAND_NONE)
49
		player_wait_decoder(dc);
Max Kellermann's avatar
Max Kellermann committed
50 51
}

52
void
53
dc_command_wait(struct decoder_control *dc)
54
{
55 56 57
	decoder_lock(dc);
	dc_command_wait_locked(dc);
	decoder_unlock(dc);
58 59
}

60
static void
61
dc_command_locked(struct decoder_control *dc, enum decoder_command cmd)
Max Kellermann's avatar
Max Kellermann committed
62
{
63
	dc->command = cmd;
64
	decoder_signal(dc);
65
	dc_command_wait_locked(dc);
66 67 68
}

static void
69
dc_command(struct decoder_control *dc, enum decoder_command cmd)
70
{
71 72 73
	decoder_lock(dc);
	dc_command_locked(dc, cmd);
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
74 75
}

76 77
static void
dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
Max Kellermann's avatar
Max Kellermann committed
78
{
79
	decoder_lock(dc);
80

81 82
	dc->command = cmd;
	decoder_signal(dc);
83

84
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
85 86
}

87
void
88 89
dc_start(struct decoder_control *dc, struct song *song,
	 struct music_buffer *buffer, struct music_pipe *pipe)
Max Kellermann's avatar
Max Kellermann committed
90 91
{
	assert(song != NULL);
92 93
	assert(buffer != NULL);
	assert(pipe != NULL);
Max Kellermann's avatar
Max Kellermann committed
94

95
	dc->song = song;
96 97
	dc->buffer = buffer;
	dc->pipe = pipe;
98
	dc_command(dc, DECODE_COMMAND_START);
Max Kellermann's avatar
Max Kellermann committed
99 100
}

101
void
102
dc_stop(struct decoder_control *dc)
Max Kellermann's avatar
Max Kellermann committed
103
{
104
	decoder_lock(dc);
105

106
	if (dc->command != DECODE_COMMAND_NONE)
107 108 109 110
		/* 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). */
111
		dc_command_locked(dc, DECODE_COMMAND_STOP);
112

113 114
	if (dc->state != DECODE_STATE_STOP && dc->state != DECODE_STATE_ERROR)
		dc_command_locked(dc, DECODE_COMMAND_STOP);
115

116
	decoder_unlock(dc);
Max Kellermann's avatar
Max Kellermann committed
117 118
}

119
bool
120
dc_seek(struct decoder_control *dc, double where)
Max Kellermann's avatar
Max Kellermann committed
121
{
122
	assert(dc->state != DECODE_STATE_START);
Max Kellermann's avatar
Max Kellermann committed
123 124
	assert(where >= 0.0);

125 126
	if (dc->state == DECODE_STATE_STOP ||
	    dc->state == DECODE_STATE_ERROR || !dc->seekable)
127
		return false;
Max Kellermann's avatar
Max Kellermann committed
128

129 130 131
	dc->seek_where = where;
	dc->seek_error = false;
	dc_command(dc, DECODE_COMMAND_SEEK);
Max Kellermann's avatar
Max Kellermann committed
132

133
	if (dc->seek_error)
134
		return false;
Max Kellermann's avatar
Max Kellermann committed
135

136
	return true;
Max Kellermann's avatar
Max Kellermann committed
137
}
138 139

void
140
dc_quit(struct decoder_control *dc)
141
{
142
	assert(dc->thread != NULL);
143

144 145
	dc->quit = true;
	dc_command_async(dc, DECODE_COMMAND_STOP);
146

147 148
	g_thread_join(dc->thread);
	dc->thread = NULL;
149
}