DecoderControl.cxx 3.25 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2013 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 "DecoderControl.hxx"
22
#include "MusicPipe.hxx"
23
#include "Song.hxx"
24

25 26
#include <glib.h>

27
#include <assert.h>
28

29
decoder_control::decoder_control()
30
	:state(DecoderState::STOP),
31
	 command(DecoderCommand::NONE),
32 33 34 35 36 37
	 song(nullptr),
	 replay_gain_db(0), replay_gain_prev_db(0),
	 mixramp_start(nullptr), mixramp_end(nullptr),
	 mixramp_prev_end(nullptr) {}

decoder_control::~decoder_control()
38
{
39
	ClearError();
40

41
	if (song != nullptr)
42
		song->Free();
43

44 45 46
	g_free(mixramp_start);
	g_free(mixramp_end);
	g_free(mixramp_prev_end);
47 48
}

49
bool
50
decoder_control::IsCurrentSong(const Song *_song) const
51
{
52
	assert(_song != nullptr);
53

54
	switch (state) {
55 56
	case DecoderState::STOP:
	case DecoderState::ERROR:
57 58
		return false;

59 60
	case DecoderState::START:
	case DecoderState::DECODE:
61
		return song_equals(song, _song);
62 63 64
	}

	assert(false);
65
	gcc_unreachable();
66 67
}

68
void
69
decoder_control::Start(Song *_song,
70
		       unsigned _start_ms, unsigned _end_ms,
71
		       MusicBuffer &_buffer, MusicPipe &_pipe)
Max Kellermann's avatar
Max Kellermann committed
72
{
73
	assert(_song != nullptr);
74
	assert(_pipe.IsEmpty());
Max Kellermann's avatar
Max Kellermann committed
75

76
	if (song != nullptr)
77
		song->Free();
78 79 80 81

	song = _song;
	start_ms = _start_ms;
	end_ms = _end_ms;
82
	buffer = &_buffer;
83
	pipe = &_pipe;
84

85
	LockSynchronousCommand(DecoderCommand::START);
Max Kellermann's avatar
Max Kellermann committed
86 87
}

88
void
89
decoder_control::Stop()
Max Kellermann's avatar
Max Kellermann committed
90
{
91
	Lock();
92

93
	if (command != DecoderCommand::NONE)
94 95 96 97
		/* 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). */
98
		SynchronousCommandLocked(DecoderCommand::STOP);
99

100
	if (state != DecoderState::STOP && state != DecoderState::ERROR)
101
		SynchronousCommandLocked(DecoderCommand::STOP);
102

103
	Unlock();
Max Kellermann's avatar
Max Kellermann committed
104 105
}

106
bool
107
decoder_control::Seek(double where)
Max Kellermann's avatar
Max Kellermann committed
108
{
109
	assert(state != DecoderState::START);
Max Kellermann's avatar
Max Kellermann committed
110 111
	assert(where >= 0.0);

112 113
	if (state == DecoderState::STOP ||
	    state == DecoderState::ERROR || !seekable)
114
		return false;
Max Kellermann's avatar
Max Kellermann committed
115

116 117
	seek_where = where;
	seek_error = false;
118
	LockSynchronousCommand(DecoderCommand::SEEK);
Max Kellermann's avatar
Max Kellermann committed
119

120
	return !seek_error;
Max Kellermann's avatar
Max Kellermann committed
121
}
122 123

void
124
decoder_control::Quit()
125
{
126
	assert(thread.IsDefined());
127

128
	quit = true;
129
	LockAsynchronousCommand(DecoderCommand::STOP);
130

131
	thread.Join();
132
}
133 134

void
135
decoder_control::MixRampStart(char *_mixramp_start)
136
{
137 138
	g_free(mixramp_start);
	mixramp_start = _mixramp_start;
139 140 141
}

void
142
decoder_control::MixRampEnd(char *_mixramp_end)
143
{
144 145
	g_free(mixramp_end);
	mixramp_end = _mixramp_end;
146 147 148
}

void
149
decoder_control::MixRampPrevEnd(char *_mixramp_prev_end)
150
{
151 152
	g_free(mixramp_prev_end);
	mixramp_prev_end = _mixramp_prev_end;
153
}