aboutsummaryrefslogtreecommitdiff
path: root/src/decoder_control.h
blob: 703ea256cca05219fae8003cf32de2b59f4d2909 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Copyright (C) 2003-2009 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_DECODER_CONTROL_H
#define MPD_DECODER_CONTROL_H

#include "decoder_command.h"
#include "audio_format.h"
#include "notify.h"

#include <assert.h>

#define DECODE_TYPE_FILE	0
#define DECODE_TYPE_URL		1

enum decoder_state {
	DECODE_STATE_STOP = 0,
	DECODE_STATE_START,
	DECODE_STATE_DECODE,

	/**
	 * The last "START" command failed, because there was an I/O
	 * error or because no decoder was able to decode the file.
	 * This state will only come after START; once the state has
	 * turned to DECODE, by definition no such error can occur.
	 */
	DECODE_STATE_ERROR,
};

struct decoder_control {
	/** the handle of the decoder thread, or NULL if the decoder
	    thread isn't running */
	GThread *thread;

	struct notify notify;

	volatile enum decoder_state state;
	volatile enum decoder_command command;
	bool quit;
	bool seek_error;
	bool seekable;
	volatile double seek_where;

	/** the format of the song file */
	struct audio_format in_audio_format;

	/** the format being sent to the music pipe */
	struct audio_format out_audio_format;

	struct song *current_song;
	struct song *next_song;
	float total_time;

	/** the #music_chunk allocator */
	struct music_buffer *buffer;

	/** the destination pipe for decoded chunks */
	struct music_pipe *pipe;
};

extern struct decoder_control dc;

void dc_init(void);

void dc_deinit(void);

static inline bool decoder_is_idle(void)
{
	return (dc.state == DECODE_STATE_STOP ||
		dc.state == DECODE_STATE_ERROR) &&
		dc.command != DECODE_COMMAND_START;
}

static inline bool decoder_is_starting(void)
{
	return dc.command == DECODE_COMMAND_START ||
		dc.state == DECODE_STATE_START;
}

static inline bool decoder_has_failed(void)
{
	assert(dc.command == DECODE_COMMAND_NONE);

	return dc.state == DECODE_STATE_ERROR;
}

static inline struct song *
decoder_current_song(void)
{
	switch (dc.state) {
	case DECODE_STATE_STOP:
	case DECODE_STATE_ERROR:
		return NULL;

	case DECODE_STATE_START:
	case DECODE_STATE_DECODE:
		return dc.current_song;
	}

	assert(false);
	return NULL;
}

void
dc_command_wait(struct notify *notify);

void
dc_start(struct notify *notify, struct song *song);

void
dc_start_async(struct song *song);

void
dc_stop(struct notify *notify);

bool
dc_seek(struct notify *notify, double where);

void
dc_quit(void);

#endif