Merge branch 'v0.21.x' into master
This commit is contained in:
commit
67c7116f05
11
NEWS
11
NEWS
|
@ -41,6 +41,17 @@ ver 0.22 (not yet released)
|
||||||
* switch to C++17
|
* switch to C++17
|
||||||
- GCC 7 or clang 4 (or newer) recommended
|
- GCC 7 or clang 4 (or newer) recommended
|
||||||
|
|
||||||
|
ver 0.21.26 (not yet released)
|
||||||
|
* output
|
||||||
|
- osx: fix crash bug
|
||||||
|
- sles: support floating point samples
|
||||||
|
* archive
|
||||||
|
- bzip2: fix crash on corrupt bzip2 file
|
||||||
|
- bzip2: flush output at end of input file
|
||||||
|
- zzip: fix crash on corrupt ZIP file
|
||||||
|
* decoder
|
||||||
|
- sndfile: fix lost samples at end of file
|
||||||
|
|
||||||
ver 0.21.25 (2020/07/06)
|
ver 0.21.25 (2020/07/06)
|
||||||
* protocol:
|
* protocol:
|
||||||
- fix crash when using "rangeid" while playing
|
- fix crash when using "rangeid" while playing
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.musicpd"
|
package="org.musicpd"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:versionCode="48"
|
android:versionCode="49"
|
||||||
android:versionName="0.21.25">
|
android:versionName="0.21.26">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
|
||||||
|
|
||||||
|
|
|
@ -1119,7 +1119,8 @@ sles
|
||||||
|
|
||||||
Plugin using the `OpenSL ES <https://www.khronos.org/opensles/>`__
|
Plugin using the `OpenSL ES <https://www.khronos.org/opensles/>`__
|
||||||
audio API. Its primary use is local playback on Android, where
|
audio API. Its primary use is local playback on Android, where
|
||||||
:ref:`ALSA <alsa_plugin>` is not available.
|
:ref:`ALSA <alsa_plugin>` is not available. It supports 16 bit and
|
||||||
|
floating point samples.
|
||||||
|
|
||||||
|
|
||||||
solaris
|
solaris
|
||||||
|
|
|
@ -10,8 +10,8 @@ from build.ffmpeg import FfmpegProject
|
||||||
from build.boost import BoostProject
|
from build.boost import BoostProject
|
||||||
|
|
||||||
libmpdclient = MesonProject(
|
libmpdclient = MesonProject(
|
||||||
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.18.tar.xz',
|
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.19.tar.xz',
|
||||||
'4cb01e1f567e0169aca94875fb6e1200e7f5ce35b63a4df768ec1591fb1081fa',
|
'158aad4c2278ab08e76a3f2b0166c99b39fae00ee17231bd225c5a36e977a189',
|
||||||
'lib/libmpdclient.a',
|
'lib/libmpdclient.a',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ libogg = AutotoolsProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
libvorbis = AutotoolsProject(
|
libvorbis = AutotoolsProject(
|
||||||
'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.tar.xz',
|
'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz',
|
||||||
'af00bb5a784e7c9e69f56823de4637c350643deedaf333d0fa86ecdba6fcb415',
|
'b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b',
|
||||||
'lib/libvorbis.a',
|
'lib/libvorbis.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -148,8 +148,8 @@ gme = CmakeProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-4.2.3.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-4.3.1.tar.xz',
|
||||||
'9df6c90aed1337634c1fb026fb01c154c29c82a64ea71291ff2da9aacb9aad31',
|
'ad009240d46e307b4e03a213a0f49c11b650e445b1f8be0dda2a9212b34d2ffb',
|
||||||
'lib/libavcodec.a',
|
'lib/libavcodec.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -377,8 +377,8 @@ ffmpeg = FfmpegProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
curl = AutotoolsProject(
|
curl = AutotoolsProject(
|
||||||
'http://curl.haxx.se/download/curl-7.70.0.tar.xz',
|
'http://curl.haxx.se/download/curl-7.72.0.tar.xz',
|
||||||
'032f43f2674008c761af19bf536374128c16241fb234699a55f9fb603fcfbae7',
|
'0ded0808c4d85f2ee0db86980ae610cc9d165e9ca9da466196cc73c346513713',
|
||||||
'lib/libcurl.a',
|
'lib/libcurl.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -433,7 +433,7 @@ libnfs = AutotoolsProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
boost = BoostProject(
|
boost = BoostProject(
|
||||||
'https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.bz2',
|
'https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2',
|
||||||
'4eb3b8d442b426dc35346235c8733b5ae35ba431690e38c6a8263dce9fcbb402',
|
'83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1',
|
||||||
'include/boost/version.hpp',
|
'include/boost/version.hpp',
|
||||||
)
|
)
|
||||||
|
|
|
@ -59,9 +59,9 @@ public:
|
||||||
class Bzip2InputStream final : public InputStream {
|
class Bzip2InputStream final : public InputStream {
|
||||||
std::shared_ptr<InputStream> input;
|
std::shared_ptr<InputStream> input;
|
||||||
|
|
||||||
bool eof = false;
|
bz_stream bzstream{};
|
||||||
|
|
||||||
bz_stream bzstream;
|
bool eof = false;
|
||||||
|
|
||||||
char buffer[5000];
|
char buffer[5000];
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
Bzip2InputStream(std::shared_ptr<InputStream> _input,
|
Bzip2InputStream(std::shared_ptr<InputStream> _input,
|
||||||
const char *uri,
|
const char *uri,
|
||||||
Mutex &mutex);
|
Mutex &mutex);
|
||||||
~Bzip2InputStream() override;
|
~Bzip2InputStream() noexcept override;
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
/* virtual methods from InputStream */
|
||||||
[[nodiscard]] bool IsEOF() const noexcept override;
|
[[nodiscard]] bool IsEOF() const noexcept override;
|
||||||
|
@ -81,25 +81,6 @@ private:
|
||||||
bool FillBuffer();
|
bool FillBuffer();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* single archive handling allocation helpers */
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Bzip2InputStream::Open()
|
|
||||||
{
|
|
||||||
bzstream.bzalloc = nullptr;
|
|
||||||
bzstream.bzfree = nullptr;
|
|
||||||
bzstream.opaque = nullptr;
|
|
||||||
|
|
||||||
bzstream.next_in = (char *)buffer;
|
|
||||||
bzstream.avail_in = 0;
|
|
||||||
|
|
||||||
int ret = BZ2_bzDecompressInit(&bzstream, 0, 0);
|
|
||||||
if (ret != BZ_OK)
|
|
||||||
throw std::runtime_error("BZ2_bzDecompressInit() has failed");
|
|
||||||
|
|
||||||
SetReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* archive open && listing routine */
|
/* archive open && listing routine */
|
||||||
|
|
||||||
static std::unique_ptr<ArchiveFile>
|
static std::unique_ptr<ArchiveFile>
|
||||||
|
@ -118,10 +99,16 @@ Bzip2InputStream::Bzip2InputStream(std::shared_ptr<InputStream> _input,
|
||||||
:InputStream(_uri, _mutex),
|
:InputStream(_uri, _mutex),
|
||||||
input(std::move(_input))
|
input(std::move(_input))
|
||||||
{
|
{
|
||||||
Open();
|
bzstream.next_in = (char *)buffer;
|
||||||
|
|
||||||
|
int ret = BZ2_bzDecompressInit(&bzstream, 0, 0);
|
||||||
|
if (ret != BZ_OK)
|
||||||
|
throw std::runtime_error("BZ2_bzDecompressInit() has failed");
|
||||||
|
|
||||||
|
SetReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
Bzip2InputStream::~Bzip2InputStream()
|
Bzip2InputStream::~Bzip2InputStream() noexcept
|
||||||
{
|
{
|
||||||
BZ2_bzDecompressEnd(&bzstream);
|
BZ2_bzDecompressEnd(&bzstream);
|
||||||
}
|
}
|
||||||
|
@ -151,22 +138,18 @@ Bzip2InputStream::FillBuffer()
|
||||||
size_t
|
size_t
|
||||||
Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length)
|
Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length)
|
||||||
{
|
{
|
||||||
const ScopeUnlock unlock(mutex);
|
|
||||||
|
|
||||||
int bz_result;
|
|
||||||
size_t nbytes = 0;
|
|
||||||
|
|
||||||
if (eof)
|
if (eof)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
const ScopeUnlock unlock(mutex);
|
||||||
|
|
||||||
bzstream.next_out = (char *)ptr;
|
bzstream.next_out = (char *)ptr;
|
||||||
bzstream.avail_out = length;
|
bzstream.avail_out = length;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!FillBuffer())
|
const bool had_input = FillBuffer();
|
||||||
return 0;
|
|
||||||
|
|
||||||
bz_result = BZ2_bzDecompress(&bzstream);
|
const int bz_result = BZ2_bzDecompress(&bzstream);
|
||||||
|
|
||||||
if (bz_result == BZ_STREAM_END) {
|
if (bz_result == BZ_STREAM_END) {
|
||||||
eof = true;
|
eof = true;
|
||||||
|
@ -175,9 +158,12 @@ Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length)
|
||||||
|
|
||||||
if (bz_result != BZ_OK)
|
if (bz_result != BZ_OK)
|
||||||
throw std::runtime_error("BZ2_bzDecompress() has failed");
|
throw std::runtime_error("BZ2_bzDecompress() has failed");
|
||||||
|
|
||||||
|
if (!had_input && bzstream.avail_out == length)
|
||||||
|
throw std::runtime_error("Unexpected end of bzip2 file");
|
||||||
} while (bzstream.avail_out == length);
|
} while (bzstream.avail_out == length);
|
||||||
|
|
||||||
nbytes = length - bzstream.avail_out;
|
const size_t nbytes = length - bzstream.avail_out;
|
||||||
offset += nbytes;
|
offset += nbytes;
|
||||||
|
|
||||||
return nbytes;
|
return nbytes;
|
||||||
|
|
|
@ -148,24 +148,22 @@ Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
|
||||||
class Iso9660InputStream final : public InputStream {
|
class Iso9660InputStream final : public InputStream {
|
||||||
std::shared_ptr<Iso9660> iso;
|
std::shared_ptr<Iso9660> iso;
|
||||||
|
|
||||||
iso9660_stat_t *statbuf;
|
const lsn_t lsn;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Iso9660InputStream(std::shared_ptr<Iso9660> _iso,
|
Iso9660InputStream(std::shared_ptr<Iso9660> _iso,
|
||||||
const char *_uri,
|
const char *_uri,
|
||||||
Mutex &_mutex,
|
Mutex &_mutex,
|
||||||
iso9660_stat_t *_statbuf)
|
lsn_t _lsn, offset_type _size)
|
||||||
:InputStream(_uri, _mutex),
|
:InputStream(_uri, _mutex),
|
||||||
iso(std::move(_iso)), statbuf(_statbuf) {
|
iso(std::move(_iso)),
|
||||||
size = statbuf->size;
|
lsn(_lsn)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
seekable = true;
|
seekable = true;
|
||||||
SetReady();
|
SetReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Iso9660InputStream() override {
|
|
||||||
free(statbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
/* virtual methods from InputStream */
|
||||||
[[nodiscard]] bool IsEOF() const noexcept override;
|
[[nodiscard]] bool IsEOF() const noexcept override;
|
||||||
size_t Read(std::unique_lock<Mutex> &lock,
|
size_t Read(std::unique_lock<Mutex> &lock,
|
||||||
|
@ -185,8 +183,12 @@ Iso9660ArchiveFile::OpenStream(const char *pathname,
|
||||||
throw FormatRuntimeError("not found in the ISO file: %s",
|
throw FormatRuntimeError("not found in the ISO file: %s",
|
||||||
pathname);
|
pathname);
|
||||||
|
|
||||||
|
const lsn_t lsn = statbuf->lsn;
|
||||||
|
const offset_type size = statbuf->size;
|
||||||
|
free(statbuf);
|
||||||
|
|
||||||
return std::make_unique<Iso9660InputStream>(iso, pathname, mutex,
|
return std::make_unique<Iso9660InputStream>(iso, pathname, mutex,
|
||||||
statbuf);
|
lsn, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -197,7 +199,7 @@ Iso9660InputStream::Read(std::unique_lock<Mutex> &,
|
||||||
|
|
||||||
int readed = 0;
|
int readed = 0;
|
||||||
int no_blocks, cur_block;
|
int no_blocks, cur_block;
|
||||||
size_t left_bytes = statbuf->size - offset;
|
size_t left_bytes = size - offset;
|
||||||
|
|
||||||
if (left_bytes < read_size) {
|
if (left_bytes < read_size) {
|
||||||
no_blocks = CEILING(left_bytes, ISO_BLOCKSIZE);
|
no_blocks = CEILING(left_bytes, ISO_BLOCKSIZE);
|
||||||
|
@ -210,7 +212,7 @@ Iso9660InputStream::Read(std::unique_lock<Mutex> &,
|
||||||
|
|
||||||
cur_block = offset / ISO_BLOCKSIZE;
|
cur_block = offset / ISO_BLOCKSIZE;
|
||||||
|
|
||||||
readed = iso->SeekRead(ptr, statbuf->lsn + cur_block, no_blocks);
|
readed = iso->SeekRead(ptr, lsn + cur_block, no_blocks);
|
||||||
|
|
||||||
if (readed != no_blocks * ISO_BLOCKSIZE)
|
if (readed != no_blocks * ISO_BLOCKSIZE)
|
||||||
throw FormatRuntimeError("error reading ISO file at lsn %lu",
|
throw FormatRuntimeError("error reading ISO file at lsn %lu",
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <inttypes.h> /* for PRIoffset (PRIu64) */
|
||||||
|
|
||||||
struct ZzipDir {
|
struct ZzipDir {
|
||||||
ZZIP_DIR *const dir;
|
ZZIP_DIR *const dir;
|
||||||
|
|
||||||
|
@ -56,8 +58,9 @@ class ZzipArchiveFile final : public ArchiveFile {
|
||||||
std::shared_ptr<ZzipDir> dir;
|
std::shared_ptr<ZzipDir> dir;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ZzipArchiveFile(std::shared_ptr<ZzipDir> &&_dir)
|
template<typename D>
|
||||||
:dir(std::move(_dir)) {}
|
explicit ZzipArchiveFile(D &&_dir) noexcept
|
||||||
|
:dir(std::forward<D>(_dir)) {}
|
||||||
|
|
||||||
void Visit(ArchiveVisitor &visitor) override;
|
void Visit(ArchiveVisitor &visitor) override;
|
||||||
|
|
||||||
|
@ -93,11 +96,12 @@ class ZzipInputStream final : public InputStream {
|
||||||
ZZIP_FILE *const file;
|
ZZIP_FILE *const file;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ZzipInputStream(std::shared_ptr<ZzipDir> _dir, const char *_uri,
|
template<typename D>
|
||||||
|
ZzipInputStream(D &&_dir, const char *_uri,
|
||||||
Mutex &_mutex,
|
Mutex &_mutex,
|
||||||
ZZIP_FILE *_file)
|
ZZIP_FILE *_file)
|
||||||
:InputStream(_uri, _mutex),
|
:InputStream(_uri, _mutex),
|
||||||
dir(std::move(_dir)), file(_file) {
|
dir(std::forward<D>(_dir)), file(_file) {
|
||||||
//we are seekable (but its not recommendent to do so)
|
//we are seekable (but its not recommendent to do so)
|
||||||
seekable = true;
|
seekable = true;
|
||||||
|
|
||||||
|
@ -108,7 +112,7 @@ public:
|
||||||
SetReady();
|
SetReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ZzipInputStream() override {
|
~ZzipInputStream() noexcept override {
|
||||||
zzip_file_close(file);
|
zzip_file_close(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,12 +152,17 @@ ZzipInputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t read_size)
|
||||||
{
|
{
|
||||||
const ScopeUnlock unlock(mutex);
|
const ScopeUnlock unlock(mutex);
|
||||||
|
|
||||||
int ret = zzip_file_read(file, ptr, read_size);
|
zzip_ssize_t nbytes = zzip_file_read(file, ptr, read_size);
|
||||||
if (ret < 0)
|
if (nbytes < 0)
|
||||||
throw std::runtime_error("zzip_file_read() has failed");
|
throw std::runtime_error("zzip_file_read() has failed");
|
||||||
|
|
||||||
|
if (nbytes == 0 && !IsEOF())
|
||||||
|
throw FormatRuntimeError("Unexpected end of file %s"
|
||||||
|
" at %" PRIoffset " of %" PRIoffset,
|
||||||
|
GetURI(), GetOffset(), GetSize());
|
||||||
|
|
||||||
offset = zzip_tell(file);
|
offset = zzip_tell(file);
|
||||||
return ret;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
size_t
|
size_t
|
||||||
decoder_read(DecoderClient *client,
|
decoder_read(DecoderClient *client,
|
||||||
InputStream &is,
|
InputStream &is,
|
||||||
void *buffer, size_t length)
|
void *buffer, size_t length) noexcept
|
||||||
{
|
{
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
|
|
||||||
|
@ -42,9 +42,30 @@ decoder_read(DecoderClient *client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
decoder_read_much(DecoderClient *client, InputStream &is,
|
||||||
|
void *_buffer, size_t size) noexcept
|
||||||
|
{
|
||||||
|
uint8_t *buffer = (uint8_t *)_buffer;
|
||||||
|
|
||||||
|
size_t total = 0;
|
||||||
|
|
||||||
|
while (size > 0 && !is.LockIsEOF()) {
|
||||||
|
size_t nbytes = decoder_read(client, is, buffer, size);
|
||||||
|
if (nbytes == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
total += nbytes;
|
||||||
|
buffer += nbytes;
|
||||||
|
size -= nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
decoder_read_full(DecoderClient *client, InputStream &is,
|
decoder_read_full(DecoderClient *client, InputStream &is,
|
||||||
void *_buffer, size_t size)
|
void *_buffer, size_t size) noexcept
|
||||||
{
|
{
|
||||||
auto *buffer = (uint8_t *)_buffer;
|
auto *buffer = (uint8_t *)_buffer;
|
||||||
|
|
||||||
|
@ -61,7 +82,7 @@ decoder_read_full(DecoderClient *client, InputStream &is,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
decoder_skip(DecoderClient *client, InputStream &is, size_t size)
|
decoder_skip(DecoderClient *client, InputStream &is, size_t size) noexcept
|
||||||
{
|
{
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
|
@ -63,15 +63,27 @@ class StopDecoder {};
|
||||||
*/
|
*/
|
||||||
size_t
|
size_t
|
||||||
decoder_read(DecoderClient *decoder, InputStream &is,
|
decoder_read(DecoderClient *decoder, InputStream &is,
|
||||||
void *buffer, size_t length);
|
void *buffer, size_t length) noexcept;
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
decoder_read(DecoderClient &decoder, InputStream &is,
|
decoder_read(DecoderClient &decoder, InputStream &is,
|
||||||
void *buffer, size_t length)
|
void *buffer, size_t length) noexcept
|
||||||
{
|
{
|
||||||
return decoder_read(&decoder, is, buffer, length);
|
return decoder_read(&decoder, is, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocking read from the input stream. Attempts to fill the buffer
|
||||||
|
* as much as possible, until either end-of-file is reached or an
|
||||||
|
* error occurs.
|
||||||
|
*
|
||||||
|
* @return the number of bytes read, or 0 if one of the following
|
||||||
|
* occurs: end of file; error; command (like SEEK or STOP).
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
decoder_read_much(DecoderClient *decoder, InputStream &is,
|
||||||
|
void *buffer, size_t size) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocking read from the input stream. Attempts to fill the buffer
|
* Blocking read from the input stream. Attempts to fill the buffer
|
||||||
* completely; there is no partial result.
|
* completely; there is no partial result.
|
||||||
|
@ -81,7 +93,7 @@ decoder_read(DecoderClient &decoder, InputStream &is,
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
decoder_read_full(DecoderClient *decoder, InputStream &is,
|
decoder_read_full(DecoderClient *decoder, InputStream &is,
|
||||||
void *buffer, size_t size);
|
void *buffer, size_t size) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip data on the #InputStream.
|
* Skip data on the #InputStream.
|
||||||
|
@ -89,6 +101,6 @@ decoder_read_full(DecoderClient *decoder, InputStream &is,
|
||||||
* @return true on success, false on error or command
|
* @return true on success, false on error or command
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
decoder_skip(DecoderClient *decoder, InputStream &is, size_t size);
|
decoder_skip(DecoderClient *decoder, InputStream &is, size_t size) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,9 +47,7 @@ struct SndfileInputStream {
|
||||||
size_t Read(void *buffer, size_t size) {
|
size_t Read(void *buffer, size_t size) {
|
||||||
/* libsndfile chokes on partial reads; therefore
|
/* libsndfile chokes on partial reads; therefore
|
||||||
always force full reads */
|
always force full reads */
|
||||||
return decoder_read_full(client, is, buffer, size)
|
return decoder_read_much(client, is, buffer, size);
|
||||||
? size
|
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ input_stream_global_init(const ConfigData &config, EventLoop &event_loop)
|
||||||
plugin->init(event_loop, *block);
|
plugin->init(event_loop, *block);
|
||||||
input_plugins_enabled[i] = true;
|
input_plugins_enabled[i] = true;
|
||||||
} catch (const PluginUnconfigured &e) {
|
} catch (const PluginUnconfigured &e) {
|
||||||
LogFormat(LogLevel::INFO, e,
|
LogFormat(LogLevel::DEBUG, e,
|
||||||
"Input plugin '%s' is not configured",
|
"Input plugin '%s' is not configured",
|
||||||
plugin->name);
|
plugin->name);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -18,7 +18,7 @@ if icu_dep.found()
|
||||||
'Init.cxx',
|
'Init.cxx',
|
||||||
]
|
]
|
||||||
elif not get_option('iconv').disabled()
|
elif not get_option('iconv').disabled()
|
||||||
have_iconv = compiler.has_function('iconv')
|
have_iconv = compiler.has_function('iconv', prefix : '#include <iconv.h>')
|
||||||
conf.set('HAVE_ICONV', have_iconv)
|
conf.set('HAVE_ICONV', have_iconv)
|
||||||
if not have_iconv and get_option('iconv').enabled()
|
if not have_iconv and get_option('iconv').enabled()
|
||||||
error('iconv() not available')
|
error('iconv() not available')
|
||||||
|
|
|
@ -109,11 +109,6 @@ NeighborExplorer::List
|
||||||
SmbclientNeighborExplorer::GetList() const noexcept
|
SmbclientNeighborExplorer::GetList() const noexcept
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
/*
|
|
||||||
List list;
|
|
||||||
for (const auto &i : servers)
|
|
||||||
list.emplace_front(i.Export());
|
|
||||||
*/
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
osx_output_hog_device(AudioDeviceID dev_id, bool hog)
|
osx_output_hog_device(AudioDeviceID dev_id, bool hog) noexcept
|
||||||
{
|
{
|
||||||
static constexpr AudioObjectPropertyAddress aopa = {
|
static constexpr AudioObjectPropertyAddress aopa = {
|
||||||
kAudioDevicePropertyHogMode,
|
kAudioDevicePropertyHogMode,
|
||||||
|
@ -485,8 +485,16 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
|
||||||
kAudioObjectPropertyElementMaster
|
kAudioObjectPropertyElementMaster
|
||||||
};
|
};
|
||||||
|
|
||||||
pid_t hog_pid = AudioObjectGetPropertyDataT<pid_t>(dev_id,
|
pid_t hog_pid;
|
||||||
aopa);
|
|
||||||
|
try {
|
||||||
|
hog_pid = AudioObjectGetPropertyDataT<pid_t>(dev_id, aopa);
|
||||||
|
} catch (...) {
|
||||||
|
Log(LogLevel::DEBUG, std::current_exception(),
|
||||||
|
"Failed to query HogMode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (hog) {
|
if (hog) {
|
||||||
if (hog_pid != -1) {
|
if (hog_pid != -1) {
|
||||||
FormatDebug(osx_output_domain,
|
FormatDebug(osx_output_domain,
|
||||||
|
|
|
@ -173,12 +173,12 @@ SlesOutput::Open(AudioFormat &audio_format)
|
||||||
if (audio_format.channels > 2)
|
if (audio_format.channels > 2)
|
||||||
audio_format.channels = 1;
|
audio_format.channels = 1;
|
||||||
|
|
||||||
SLDataFormat_PCM format_pcm;
|
SLAndroidDataFormat_PCM_EX format_pcm;
|
||||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||||
format_pcm.numChannels = audio_format.channels;
|
format_pcm.numChannels = audio_format.channels;
|
||||||
/* from the Android NDK docs: "Note that the field samplesPerSec is
|
/* from the Android NDK docs: "Note that the field samplesPerSec is
|
||||||
actually in units of milliHz, despite the misleading name." */
|
actually in units of milliHz, despite the misleading name." */
|
||||||
format_pcm.samplesPerSec = audio_format.sample_rate * 1000u;
|
format_pcm.sampleRate = audio_format.sample_rate * 1000u;
|
||||||
format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
|
format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
|
||||||
format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
|
format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
|
||||||
format_pcm.channelMask = audio_format.channels == 1
|
format_pcm.channelMask = audio_format.channels == 1
|
||||||
|
@ -187,6 +187,36 @@ SlesOutput::Open(AudioFormat &audio_format)
|
||||||
format_pcm.endianness = IsLittleEndian()
|
format_pcm.endianness = IsLittleEndian()
|
||||||
? SL_BYTEORDER_LITTLEENDIAN
|
? SL_BYTEORDER_LITTLEENDIAN
|
||||||
: SL_BYTEORDER_BIGENDIAN;
|
: SL_BYTEORDER_BIGENDIAN;
|
||||||
|
format_pcm.representation = SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT;
|
||||||
|
|
||||||
|
switch (audio_format.format) {
|
||||||
|
/* note: Android doesn't support
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_24 and
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_32, so let's not bother
|
||||||
|
implement it here; SL_PCMSAMPLEFORMAT_FIXED_8
|
||||||
|
appears to be unsigned, so not usable for us (and
|
||||||
|
converting S8 to U8 is not worth the trouble) */
|
||||||
|
|
||||||
|
case SampleFormat::S16:
|
||||||
|
/* bitsPerSample and containerSize already set for 16
|
||||||
|
bit */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SampleFormat::FLOAT:
|
||||||
|
/* Android has an OpenSLES extension for floating
|
||||||
|
point samples:
|
||||||
|
https://developer.android.com/ndk/guides/audio/opensl/android-extensions */
|
||||||
|
format_pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
|
||||||
|
format_pcm.bitsPerSample = format_pcm.containerSize =
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_32;
|
||||||
|
format_pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* fall back to 16 bit */
|
||||||
|
audio_format.format = SampleFormat::S16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SLDataSource audioSrc = { &loc_bufq, &format_pcm };
|
SLDataSource audioSrc = { &loc_bufq, &format_pcm };
|
||||||
|
|
||||||
|
@ -291,9 +321,6 @@ SlesOutput::Open(AudioFormat &audio_format)
|
||||||
n_queued = 0;
|
n_queued = 0;
|
||||||
next = 0;
|
next = 0;
|
||||||
filled = 0;
|
filled = 0;
|
||||||
|
|
||||||
// TODO: support other sample formats
|
|
||||||
audio_format.format = SampleFormat::S16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -74,39 +74,39 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr bool
|
constexpr bool
|
||||||
IsLittleEndian()
|
IsLittleEndian() noexcept
|
||||||
{
|
{
|
||||||
return IS_LITTLE_ENDIAN;
|
return IS_LITTLE_ENDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool
|
constexpr bool
|
||||||
IsBigEndian()
|
IsBigEndian() noexcept
|
||||||
{
|
{
|
||||||
return IS_BIG_ENDIAN;
|
return IS_BIG_ENDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
GenericByteSwap16(uint16_t value)
|
GenericByteSwap16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
return (value >> 8) | (value << 8);
|
return (value >> 8) | (value << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
GenericByteSwap32(uint32_t value)
|
GenericByteSwap32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
return (value >> 24) | ((value >> 8) & 0x0000ff00) |
|
return (value >> 24) | ((value >> 8) & 0x0000ff00) |
|
||||||
((value << 8) & 0x00ff0000) | (value << 24);
|
((value << 8) & 0x00ff0000) | (value << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
GenericByteSwap64(uint64_t value)
|
GenericByteSwap64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return uint64_t(GenericByteSwap32(uint32_t(value >> 32)))
|
return uint64_t(GenericByteSwap32(uint32_t(value >> 32)))
|
||||||
| (uint64_t(GenericByteSwap32(value)) << 32);
|
| (uint64_t(GenericByteSwap32(value)) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
ByteSwap16(uint16_t value)
|
ByteSwap16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
#if CLANG_OR_GCC_VERSION(4,8)
|
#if CLANG_OR_GCC_VERSION(4,8)
|
||||||
return __builtin_bswap16(value);
|
return __builtin_bswap16(value);
|
||||||
|
@ -116,7 +116,7 @@ ByteSwap16(uint16_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
ByteSwap32(uint32_t value)
|
ByteSwap32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
#if CLANG_OR_GCC_VERSION(4,3)
|
#if CLANG_OR_GCC_VERSION(4,3)
|
||||||
return __builtin_bswap32(value);
|
return __builtin_bswap32(value);
|
||||||
|
@ -126,7 +126,7 @@ ByteSwap32(uint32_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
ByteSwap64(uint64_t value)
|
ByteSwap64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
#if CLANG_OR_GCC_VERSION(4,3)
|
#if CLANG_OR_GCC_VERSION(4,3)
|
||||||
return __builtin_bswap64(value);
|
return __builtin_bswap64(value);
|
||||||
|
@ -139,7 +139,7 @@ ByteSwap64(uint64_t value)
|
||||||
* Converts a 16bit value from big endian to the system's byte order
|
* Converts a 16bit value from big endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
FromBE16(uint16_t value)
|
FromBE16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap16(value);
|
return IsBigEndian() ? value : ByteSwap16(value);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ FromBE16(uint16_t value)
|
||||||
* Converts a 32bit value from big endian to the system's byte order
|
* Converts a 32bit value from big endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
FromBE32(uint32_t value)
|
FromBE32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap32(value);
|
return IsBigEndian() ? value : ByteSwap32(value);
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ FromBE32(uint32_t value)
|
||||||
* Converts a 64bit value from big endian to the system's byte order
|
* Converts a 64bit value from big endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
FromBE64(uint64_t value)
|
FromBE64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap64(value);
|
return IsBigEndian() ? value : ByteSwap64(value);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ FromBE64(uint64_t value)
|
||||||
* Converts a 16bit value from little endian to the system's byte order
|
* Converts a 16bit value from little endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
FromLE16(uint16_t value)
|
FromLE16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap16(value);
|
return IsLittleEndian() ? value : ByteSwap16(value);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ FromLE16(uint16_t value)
|
||||||
* Converts a 32bit value from little endian to the system's byte order
|
* Converts a 32bit value from little endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
FromLE32(uint32_t value)
|
FromLE32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap32(value);
|
return IsLittleEndian() ? value : ByteSwap32(value);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ FromLE32(uint32_t value)
|
||||||
* Converts a 64bit value from little endian to the system's byte order
|
* Converts a 64bit value from little endian to the system's byte order
|
||||||
*/
|
*/
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
FromLE64(uint64_t value)
|
FromLE64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap64(value);
|
return IsLittleEndian() ? value : ByteSwap64(value);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ FromLE64(uint64_t value)
|
||||||
* Converts a 16bit value from the system's byte order to big endian
|
* Converts a 16bit value from the system's byte order to big endian
|
||||||
*/
|
*/
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
ToBE16(uint16_t value)
|
ToBE16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap16(value);
|
return IsBigEndian() ? value : ByteSwap16(value);
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ ToBE16(uint16_t value)
|
||||||
* Converts a 32bit value from the system's byte order to big endian
|
* Converts a 32bit value from the system's byte order to big endian
|
||||||
*/
|
*/
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
ToBE32(uint32_t value)
|
ToBE32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap32(value);
|
return IsBigEndian() ? value : ByteSwap32(value);
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ ToBE32(uint32_t value)
|
||||||
* Converts a 64bit value from the system's byte order to big endian
|
* Converts a 64bit value from the system's byte order to big endian
|
||||||
*/
|
*/
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
ToBE64(uint64_t value)
|
ToBE64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsBigEndian() ? value : ByteSwap64(value);
|
return IsBigEndian() ? value : ByteSwap64(value);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ ToBE64(uint64_t value)
|
||||||
* Converts a 16bit value from the system's byte order to little endian
|
* Converts a 16bit value from the system's byte order to little endian
|
||||||
*/
|
*/
|
||||||
constexpr uint16_t
|
constexpr uint16_t
|
||||||
ToLE16(uint16_t value)
|
ToLE16(uint16_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap16(value);
|
return IsLittleEndian() ? value : ByteSwap16(value);
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ ToLE16(uint16_t value)
|
||||||
* Converts a 32bit value from the system's byte order to little endian
|
* Converts a 32bit value from the system's byte order to little endian
|
||||||
*/
|
*/
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
ToLE32(uint32_t value)
|
ToLE32(uint32_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap32(value);
|
return IsLittleEndian() ? value : ByteSwap32(value);
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ ToLE32(uint32_t value)
|
||||||
* Converts a 64bit value from the system's byte order to little endian
|
* Converts a 64bit value from the system's byte order to little endian
|
||||||
*/
|
*/
|
||||||
constexpr uint64_t
|
constexpr uint64_t
|
||||||
ToLE64(uint64_t value)
|
ToLE64(uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return IsLittleEndian() ? value : ByteSwap64(value);
|
return IsLittleEndian() ? value : ByteSwap64(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,11 @@ class CrossGccToolchain:
|
||||||
' -static-libstdc++ -static-libgcc'
|
' -static-libstdc++ -static-libgcc'
|
||||||
self.libs = ''
|
self.libs = ''
|
||||||
|
|
||||||
|
# Explicitly disable _FORTIFY_SOURCE because it is broken with
|
||||||
|
# mingw. This prevents some libraries such as libFLAC to
|
||||||
|
# enable it.
|
||||||
|
self.cppflags += ' -D_FORTIFY_SOURCE=0'
|
||||||
|
|
||||||
self.is_arm = arch.startswith('arm')
|
self.is_arm = arch.startswith('arm')
|
||||||
self.is_armv7 = self.is_arm and 'armv7' in self.cflags
|
self.is_armv7 = self.is_arm and 'armv7' in self.cflags
|
||||||
self.is_aarch64 = arch == 'aarch64'
|
self.is_aarch64 = arch == 'aarch64'
|
||||||
|
|
Loading…
Reference in New Issue