InputStream.cxx 3.4 KB
Newer Older
1
/*
2
 * Copyright 2003-2018 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
 */

20
#include "InputStream.hxx"
21
#include "Handler.hxx"
22
#include "tag/Tag.hxx"
23
#include "util/ASCII.hxx"
24

25 26
#include <stdexcept>

27
#include <assert.h>
28

29
InputStream::~InputStream() noexcept
30 31 32
{
}

33 34
void
InputStream::Check()
35 36 37
{
}

38
void
39
InputStream::Update() noexcept
40 41 42
{
}

43
void
44
InputStream::SetReady() noexcept
45 46 47 48 49
{
	assert(!ready);

	ready = true;

50
	InvokeOnReady();
51 52
}

53 54 55 56 57 58 59
/**
 * Is seeking on resources behind this URI "expensive"?  For example,
 * seeking in a HTTP file requires opening a new connection with a new
 * HTTP request.
 */
gcc_pure
static bool
60
ExpensiveSeeking(const char *uri) noexcept
61
{
62
	return StringStartsWithCaseASCII(uri, "http://") ||
63 64
		StringStartsWithCaseASCII(uri, "tidal://") ||
		StringStartsWithCaseASCII(uri, "qobuz://") ||
65
		StringStartsWithCaseASCII(uri, "https://");
66 67
}

68
bool
69
InputStream::CheapSeeking() const noexcept
70
{
71
	return IsSeekable() && !ExpensiveSeeking(uri.c_str());
72 73
}

74 75
void
InputStream::Seek(gcc_unused offset_type new_offset)
Avuton Olrich's avatar
Avuton Olrich committed
76
{
77
	throw std::runtime_error("Seeking is not implemented");
78 79
}

80 81
void
InputStream::LockSeek(offset_type _offset)
82
{
83
	const std::lock_guard<Mutex> protect(mutex);
84
	Seek(_offset);
85 86
}

87 88
void
InputStream::LockSkip(offset_type _offset)
89
{
90
	const std::lock_guard<Mutex> protect(mutex);
91
	Skip(_offset);
92 93
}

94
std::unique_ptr<Tag>
95
InputStream::ReadTag()
96
{
97
	return nullptr;
98 99
}

100
std::unique_ptr<Tag>
101
InputStream::LockReadTag()
102
{
103
	const std::lock_guard<Mutex> protect(mutex);
104
	return ReadTag();
105 106 107
}

bool
108
InputStream::IsAvailable() noexcept
109
{
110
	return true;
111 112
}

113
size_t
114
InputStream::LockRead(void *ptr, size_t _size)
115
{
116 117
#if !CLANG_CHECK_VERSION(3,6)
	/* disabled on clang due to -Wtautological-pointer-compare */
118
	assert(ptr != nullptr);
119
#endif
120
	assert(_size > 0);
121

122
	const std::lock_guard<Mutex> protect(mutex);
123
	return Read(ptr, _size);
124 125
}

126 127
void
InputStream::ReadFull(void *_ptr, size_t _size)
128 129 130 131 132
{
	uint8_t *ptr = (uint8_t *)_ptr;

	size_t nbytes_total = 0;
	while (_size > 0) {
133
		size_t nbytes = Read(ptr + nbytes_total, _size);
134
		if (nbytes == 0)
135
			throw std::runtime_error("Unexpected end of file");
136 137 138 139 140 141

		nbytes_total += nbytes;
		_size -= nbytes;
	}
}

142 143
void
InputStream::LockReadFull(void *ptr, size_t _size)
144 145 146 147 148 149 150
{
#if !CLANG_CHECK_VERSION(3,6)
	/* disabled on clang due to -Wtautological-pointer-compare */
	assert(ptr != nullptr);
#endif
	assert(_size > 0);

151
	const std::lock_guard<Mutex> protect(mutex);
152
	ReadFull(ptr, _size);
153 154
}

155
bool
156
InputStream::LockIsEOF() noexcept
Avuton Olrich's avatar
Avuton Olrich committed
157
{
158
	const std::lock_guard<Mutex> protect(mutex);
159
	return IsEOF();
160
}
161 162 163 164 165 166 167 168 169 170 171 172 173 174

void
InputStream::InvokeOnReady() noexcept
{
	if (handler != nullptr)
		handler->OnInputStreamReady();
}

void
InputStream::InvokeOnAvailable() noexcept
{
	if (handler != nullptr)
		handler->OnInputStreamAvailable();
}