InputStream.cxx 3.33 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3
 * http://www.musicpd.org
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.
18 19
 */

Max Kellermann's avatar
Max Kellermann committed
20
#include "config.h"
21
#include "InputStream.hxx"
22
#include "InputRegistry.hxx"
23
#include "InputPlugin.hxx"
24
#include "input/RewindInputPlugin.hxx"
Max Kellermann's avatar
Max Kellermann committed
25
#include "util/UriUtil.hxx"
26 27
#include "util/Error.hxx"
#include "util/Domain.hxx"
28

29
#include <assert.h>
30

31
static constexpr Domain input_domain("input");
32

33
struct input_stream *
34 35 36
input_stream::Open(const char *url,
		   Mutex &mutex, Cond &cond,
		   Error &error)
Avuton Olrich's avatar
Avuton Olrich committed
37
{
38
	input_plugins_for_each_enabled(plugin) {
39
		struct input_stream *is;
Max Kellermann's avatar
Max Kellermann committed
40

41
		is = plugin->open(url, mutex, cond, error);
42
		if (is != NULL) {
43 44 45 46
			assert(is->plugin.close != NULL);
			assert(is->plugin.read != NULL);
			assert(is->plugin.eof != NULL);
			assert(!is->seekable || is->plugin.seek != NULL);
47

48
			is = input_rewind_open(is);
49

50
			return is;
51
		} else if (error.IsDefined())
52
			return NULL;
53
	}
54

55
	error.Set(input_domain, "Unrecognized URI");
56
	return NULL;
57 58
}

59
bool
60
input_stream::Check(Error &error)
61
{
62
	return plugin.check == nullptr || plugin.check(this, error);
63 64
}

65
void
66
input_stream::Update()
67
{
68 69
	if (plugin.update != nullptr)
		plugin.update(this);
70 71
}

72
void
73
input_stream::WaitReady()
74 75
{
	while (true) {
76 77
		Update();
		if (ready)
78 79
			break;

80
		cond.wait(mutex);
81 82 83 84
	}
}

void
85
input_stream::LockWaitReady()
86
{
87 88
	const ScopeLock protect(mutex);
	WaitReady();
89 90
}

91
bool
92
input_stream::CheapSeeking() const
93
{
94
	return IsSeekable() && !uri_has_scheme(uri.c_str());
95 96
}

97
bool
98
input_stream::Seek(goffset _offset, int whence, Error &error)
Avuton Olrich's avatar
Avuton Olrich committed
99
{
100
	if (plugin.seek == nullptr)
101 102
		return false;

103
	return plugin.seek(this, _offset, whence, error);
104 105
}

106
bool
107
input_stream::LockSeek(goffset _offset, int whence, Error &error)
108
{
109
	if (plugin.seek == nullptr)
110 111
		return false;

112 113
	const ScopeLock protect(mutex);
	return Seek(_offset, whence, error);
114 115
}

Max Kellermann's avatar
Max Kellermann committed
116
Tag *
117
input_stream::ReadTag()
118
{
119 120 121
	return plugin.tag != nullptr
		? plugin.tag(this)
		: nullptr;
122 123
}

Max Kellermann's avatar
Max Kellermann committed
124
Tag *
125
input_stream::LockReadTag()
126
{
127
	if (plugin.tag == nullptr)
128
		return nullptr;
129

130 131
	const ScopeLock protect(mutex);
	return ReadTag();
132 133 134
}

bool
135
input_stream::IsAvailable()
136
{
137 138
	return plugin.available != nullptr
		? plugin.available(this)
139 140 141
		: true;
}

142
size_t
143
input_stream::Read(void *ptr, size_t _size, Error &error)
144
{
145
	assert(ptr != NULL);
146
	assert(_size > 0);
147

148
	return plugin.read(this, ptr, _size, error);
149 150
}

151
size_t
152
input_stream::LockRead(void *ptr, size_t _size, Error &error)
153 154
{
	assert(ptr != NULL);
155
	assert(_size > 0);
156

157 158
	const ScopeLock protect(mutex);
	return Read(ptr, _size, error);
159 160
}

161 162
void
input_stream::Close()
Avuton Olrich's avatar
Avuton Olrich committed
163
{
164
	plugin.close(this);
165
}
166

167 168
bool
input_stream::IsEOF()
Avuton Olrich's avatar
Avuton Olrich committed
169
{
170
	return plugin.eof(this);
171
}
172

173
bool
174
input_stream::LockIsEOF()
Avuton Olrich's avatar
Avuton Olrich committed
175
{
176 177
	const ScopeLock protect(mutex);
	return IsEOF();
178
}
179