release v0.23.6
-----BEGIN PGP SIGNATURE----- iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmIvgaMQHG1heEBtdXNp Y3BkLm9yZwAKCRAjbopYxttFEpzhEACOJOyOjtmeuu7Uc147O4YzL/7g5PEZMKHI yB/H2QOWnbgAKh+8AFT2YudR89mIXslfuIILRg8/NYkEFgNCrkBQETWsATPyqrCr rYJxPtjlC2fAlKkl9XM+qL1WMATIhvRVD9SZajZKwa+9H1y5mZGlMBWdzdxaJoUY bhlu7fYvyRMXsStUncyYfsKsuHyibq3d4Pk/jegZhJeMI9/MOKdjc9GJE6Rzz0cT dWGqpfBJ/WMZ9aKXB3fh7WVtiIl/hr/5K1QizL10pwmJ5o/LBNKk7eEREbPUvNc6 S5BHBOyVYaqVTGZyaoF9XkMKv7qnKYNoD2g2H+J5cN87rMRI8DzY/MqUxmX0bCGc jOQinMcQuL7zMvYx0ypKdTiMas2OG/RlKluOgzhNIvzkWYCxh9iCozm7Wl3qsvY5 uJEsaeIb/zgSmUC2637ltBE37lW/8m7RYWpuq82M2CnFx9oL6W3ah8SMm5ToBzYB jHrN7h+YcKoIrFcZsYVTCbLzGQnQ2kmzsyGecDeCK9aP16gTkALZdpexn0oIzEKv fNtNSU7MgYXLs0knrcBoQw0nQnH9ICuswqFiyr4jcFfqxbIw9mvHyLRIWnyhL9zj XiYEr3SqnuVnmuLSgHlYk6g4zpYFLJEHo+/7IlEqTItXeAcsIhjn6B/NDyKVvYQa Pfb1ORoumQ== =jMu8 -----END PGP SIGNATURE----- Merge tag 'v0.23.6' release v0.23.6
This commit is contained in:
commit
407fa2720a
9
NEWS
9
NEWS
|
@ -9,9 +9,16 @@ ver 0.24 (not yet released)
|
||||||
* tags
|
* tags
|
||||||
- new tag "Mood"
|
- new tag "Mood"
|
||||||
|
|
||||||
ver 0.23.6 (not yet released)
|
ver 0.23.6 (2022/03/14)
|
||||||
|
* protocol
|
||||||
|
- support filename "cover.webp" for "albumart" command
|
||||||
|
- support "readcomments" and "readpicture" on CUE tracks
|
||||||
* decoder
|
* decoder
|
||||||
|
- ffmpeg: fix end-of-file check (update stuck at empty files)
|
||||||
- opus: fix "readpicture" on Opus files
|
- opus: fix "readpicture" on Opus files
|
||||||
|
* output
|
||||||
|
- pipewire: fix crash bug if setting volume before playback starts
|
||||||
|
- wasapi: fix resume after pause
|
||||||
|
|
||||||
ver 0.23.5 (2021/12/01)
|
ver 0.23.5 (2021/12/01)
|
||||||
* protocol
|
* protocol
|
||||||
|
|
|
@ -13,7 +13,7 @@ android_abi = sys.argv[3]
|
||||||
configure_args = sys.argv[4:]
|
configure_args = sys.argv[4:]
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(sdk_path, 'tools', 'android')):
|
if not os.path.isfile(os.path.join(sdk_path, 'tools', 'android')):
|
||||||
print("SDK not found in", ndk_path, file=sys.stderr)
|
print("SDK not found in", sdk_path, file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not os.path.isdir(ndk_path):
|
if not os.path.isdir(ndk_path):
|
||||||
|
|
|
@ -12,14 +12,14 @@ from build.boost import BoostProject
|
||||||
from build.jack import JackProject
|
from build.jack import JackProject
|
||||||
|
|
||||||
libmpdclient = MesonProject(
|
libmpdclient = MesonProject(
|
||||||
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.19.tar.xz',
|
'https://www.musicpd.org/download/libmpdclient/2/libmpdclient-2.20.tar.xz',
|
||||||
'158aad4c2278ab08e76a3f2b0166c99b39fae00ee17231bd225c5a36e977a189',
|
'18793f68e939c3301e34d8fcadea1f7daa24143941263cecadb80126194e277d',
|
||||||
'lib/libmpdclient.a',
|
'lib/libmpdclient.a',
|
||||||
)
|
)
|
||||||
|
|
||||||
libogg = CmakeProject(
|
libogg = CmakeProject(
|
||||||
'http://downloads.xiph.org/releases/ogg/libogg-1.3.4.tar.xz',
|
'http://downloads.xiph.org/releases/ogg/libogg-1.3.5.tar.xz',
|
||||||
'c163bc12bc300c401b6aa35907ac682671ea376f13ae0969a220f7ddf71893fe',
|
'c4d91be36fc8e54deae7575241e03f4211eb102afb3fc0775fbbc1b740016705',
|
||||||
'lib/libogg.a',
|
'lib/libogg.a',
|
||||||
[
|
[
|
||||||
'-DBUILD_SHARED_LIBS=OFF',
|
'-DBUILD_SHARED_LIBS=OFF',
|
||||||
|
@ -43,8 +43,8 @@ opus = AutotoolsProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
flac = AutotoolsProject(
|
flac = AutotoolsProject(
|
||||||
'http://downloads.xiph.org/releases/flac/flac-1.3.3.tar.xz',
|
'http://downloads.xiph.org/releases/flac/flac-1.3.4.tar.xz',
|
||||||
'213e82bd716c9de6db2f98bcadbc4c24c7e2efe8c75939a1a84e28539c4e1748',
|
'8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737',
|
||||||
'lib/libFLAC.a',
|
'lib/libFLAC.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -151,8 +151,8 @@ gme = CmakeProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-4.4.1.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-5.0.tar.xz',
|
||||||
'eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02',
|
'51e919f7d205062c0fd4fae6243a84850391115104ccf1efc451733bc0ac7298',
|
||||||
'lib/libavcodec.a',
|
'lib/libavcodec.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -380,14 +380,14 @@ ffmpeg = FfmpegProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
openssl = OpenSSLProject(
|
openssl = OpenSSLProject(
|
||||||
'https://www.openssl.org/source/openssl-3.0.0.tar.gz',
|
'https://www.openssl.org/source/openssl-3.0.1.tar.gz',
|
||||||
'59eedfcb46c25214c9bd37ed6078297b4df01d012267fe9e9eee31f61bc70536',
|
'c311ad853353bce796edad01a862c50a8a587f62e7e2100ef465ab53ec9b06d1',
|
||||||
'include/openssl/ossl_typ.h',
|
'include/openssl/ossl_typ.h',
|
||||||
)
|
)
|
||||||
|
|
||||||
curl = CmakeProject(
|
curl = CmakeProject(
|
||||||
'https://curl.se/download/curl-7.79.1.tar.xz',
|
'https://curl.se/download/curl-7.82.0.tar.xz',
|
||||||
'0606f74b1182ab732a17c11613cbbaf7084f2e6cca432642d0e3ad7c224c3689',
|
'0aaa12d7bd04b0966254f2703ce80dd5c38dbbd76af0297d3d690cdce58a583c',
|
||||||
'lib/libcurl.a',
|
'lib/libcurl.a',
|
||||||
[
|
[
|
||||||
'-DBUILD_CURL_EXE=OFF',
|
'-DBUILD_CURL_EXE=OFF',
|
||||||
|
@ -415,14 +415,14 @@ curl = CmakeProject(
|
||||||
'-DBUILD_TESTING=OFF',
|
'-DBUILD_TESTING=OFF',
|
||||||
],
|
],
|
||||||
windows_configure_args=[
|
windows_configure_args=[
|
||||||
'-DCMAKE_USE_SCHANNEL=ON',
|
'-DCURL_USE_SCHANNEL=ON',
|
||||||
],
|
],
|
||||||
patches='src/lib/curl/patches',
|
patches='src/lib/curl/patches',
|
||||||
)
|
)
|
||||||
|
|
||||||
libnfs = AutotoolsProject(
|
libnfs = AutotoolsProject(
|
||||||
'https://github.com/sahlberg/libnfs/archive/libnfs-4.0.0.tar.gz',
|
'https://github.com/sahlberg/libnfs/archive/libnfs-5.0.1.tar.gz',
|
||||||
'6ee77e9fe220e2d3e3b1f53cfea04fb319828cc7dbb97dd9df09e46e901d797d',
|
'7ef445410b42f36b9bad426608b53ccb9ccca4101e545c383f564c11db672ca8',
|
||||||
'lib/libnfs.a',
|
'lib/libnfs.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
@ -433,8 +433,7 @@ libnfs = AutotoolsProject(
|
||||||
|
|
||||||
'--disable-utils', '--disable-examples',
|
'--disable-utils', '--disable-examples',
|
||||||
],
|
],
|
||||||
base='libnfs-libnfs-4.0.0',
|
base='libnfs-libnfs-5.0.1',
|
||||||
patches='src/lib/nfs/patches',
|
|
||||||
autoreconf=True,
|
autoreconf=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -445,7 +444,7 @@ jack = JackProject(
|
||||||
)
|
)
|
||||||
|
|
||||||
boost = BoostProject(
|
boost = BoostProject(
|
||||||
'https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.bz2',
|
'https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.tar.bz2',
|
||||||
'fc9f85fc030e233142908241af7a846e60630aa7388de9a5fafb1f3a26840854',
|
'8681f175d4bdb26c52222665793eef08490d7758529330f98d3b29dd0735bccc',
|
||||||
'include/boost/version.hpp',
|
'include/boost/version.hpp',
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,12 +21,16 @@
|
||||||
#include "TagStream.hxx"
|
#include "TagStream.hxx"
|
||||||
#include "TagFile.hxx"
|
#include "TagFile.hxx"
|
||||||
#include "tag/Generic.hxx"
|
#include "tag/Generic.hxx"
|
||||||
|
#include "song/LightSong.hxx"
|
||||||
|
#include "db/Interface.hxx"
|
||||||
#include "storage/StorageInterface.hxx"
|
#include "storage/StorageInterface.hxx"
|
||||||
#include "client/Client.hxx"
|
#include "client/Client.hxx"
|
||||||
#include "protocol/Ack.hxx"
|
#include "protocol/Ack.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "input/InputStream.hxx"
|
#include "input/InputStream.hxx"
|
||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
#include "util/ScopeExit.hxx"
|
||||||
|
#include "util/StringCompare.hxx"
|
||||||
#include "util/UriExtract.hxx"
|
#include "util/UriExtract.hxx"
|
||||||
#include "LocateUri.hxx"
|
#include "LocateUri.hxx"
|
||||||
|
|
||||||
|
@ -51,10 +55,67 @@ TagScanFile(const Path path_fs, TagHandler &handler)
|
||||||
ScanGenericTags(path_fs, handler);
|
ScanGenericTags(path_fs, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collapse "../" prefixes in a URI relative to the specified base
|
||||||
|
* URI.
|
||||||
|
*/
|
||||||
|
static std::string
|
||||||
|
ResolveUri(std::string_view base, const char *relative)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
const char *rest = StringAfterPrefix(relative, "../");
|
||||||
|
if (rest == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (base == ".")
|
||||||
|
throw ProtocolError(ACK_ERROR_NO_EXIST, "Bad real URI");
|
||||||
|
|
||||||
|
base = PathTraitsUTF8::GetParent(base);
|
||||||
|
relative = rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PathTraitsUTF8::Build(base, relative);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the specified song in the database and return its
|
||||||
|
* (resolved) "real" URI.
|
||||||
|
*/
|
||||||
|
static std::string
|
||||||
|
GetRealSongUri(Client &client, std::string_view uri)
|
||||||
|
{
|
||||||
|
const auto &db = client.GetDatabaseOrThrow();
|
||||||
|
|
||||||
|
const auto *song = db.GetSong(uri);
|
||||||
|
if (song == nullptr)
|
||||||
|
throw ProtocolError(ACK_ERROR_NO_EXIST, "No such song");
|
||||||
|
|
||||||
|
AtScopeExit(&db, song) { db.ReturnSong(song); };
|
||||||
|
|
||||||
|
if (song->real_uri == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return ResolveUri(PathTraitsUTF8::GetParent(uri), song->real_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
TagScanDatabase(Client &client, const char *uri, TagHandler &handler)
|
TagScanDatabase(Client &client, const char *uri, TagHandler &handler)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
const auto real_uri = GetRealSongUri(client, uri);
|
||||||
|
|
||||||
|
if (!real_uri.empty()) {
|
||||||
|
uri = real_uri.c_str();
|
||||||
|
|
||||||
|
// TODO: support absolute paths?
|
||||||
|
if (uri_has_scheme(uri))
|
||||||
|
return TagScanStream(uri, handler);
|
||||||
|
}
|
||||||
|
|
||||||
const Storage *storage = client.GetStorage();
|
const Storage *storage = client.GetStorage();
|
||||||
if (storage == nullptr) {
|
if (storage == nullptr) {
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -160,8 +160,7 @@ find_stream_art(std::string_view directory, Mutex &mutex)
|
||||||
static constexpr auto art_names = std::array {
|
static constexpr auto art_names = std::array {
|
||||||
"cover.png",
|
"cover.png",
|
||||||
"cover.jpg",
|
"cover.jpg",
|
||||||
"cover.tiff",
|
"cover.webp",
|
||||||
"cover.bmp",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const auto name : art_names) {
|
for(const auto name : art_names) {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define __STDC_CONSTANT_MACROS
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
|
||||||
#include "FfmpegIo.hxx"
|
#include "FfmpegIo.hxx"
|
||||||
|
#include "libavutil/mem.h"
|
||||||
#include "../DecoderAPI.hxx"
|
#include "../DecoderAPI.hxx"
|
||||||
#include "input/InputStream.hxx"
|
#include "input/InputStream.hxx"
|
||||||
|
|
||||||
|
@ -35,7 +36,11 @@ AvioStream::~AvioStream()
|
||||||
inline int
|
inline int
|
||||||
AvioStream::Read(void *dest, int size)
|
AvioStream::Read(void *dest, int size)
|
||||||
{
|
{
|
||||||
return decoder_read(client, input, dest, size);
|
const auto nbytes = decoder_read(client, input, dest, size);
|
||||||
|
if (nbytes == 0)
|
||||||
|
return AVERROR_EOF;
|
||||||
|
|
||||||
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int64_t
|
inline int64_t
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
Index: libnfs-libnfs-4.0.0/include/win32/win32_compat.h
|
|
||||||
===================================================================
|
|
||||||
--- libnfs-libnfs-4.0.0.orig/include/win32/win32_compat.h
|
|
||||||
+++ libnfs-libnfs-4.0.0/include/win32/win32_compat.h
|
|
||||||
@@ -133,7 +133,9 @@ struct pollfd {
|
|
||||||
|
|
||||||
/* Wrapper macros to call misc. functions win32 is missing */
|
|
||||||
#define poll(x, y, z) win32_poll(x, y, z)
|
|
||||||
+#ifndef __MINGW32__
|
|
||||||
#define snprintf sprintf_s
|
|
||||||
+#endif
|
|
||||||
#define inet_pton(x,y,z) win32_inet_pton(x,y,z)
|
|
||||||
#define open(x, y, z) _open(x, y, z)
|
|
||||||
#ifndef lseek
|
|
|
@ -1 +0,0 @@
|
||||||
no_sprintf_s
|
|
|
@ -1,4 +1,11 @@
|
||||||
libflac_dep = dependency('flac', version: '>= 1.2', required: get_option('flac'))
|
libflac_dep = dependency('flac', version: '>= 1.2', required: get_option('flac'))
|
||||||
|
|
||||||
|
if is_windows
|
||||||
|
# Our Windows build generates a static libFLAC build
|
||||||
|
libflac_dep = declare_dependency(compile_args: '-DFLAC__NO_DLL',
|
||||||
|
dependencies: libflac_dep)
|
||||||
|
endif
|
||||||
|
|
||||||
libopus_dep = dependency('opus', required: get_option('opus'))
|
libopus_dep = dependency('opus', required: get_option('opus'))
|
||||||
|
|
||||||
if get_option('tremor').enabled()
|
if get_option('tremor').enabled()
|
||||||
|
|
|
@ -336,6 +336,8 @@ PipeWireOutput::Enable()
|
||||||
throw MakeErrno("pw_thread_loop_new() failed");
|
throw MakeErrno("pw_thread_loop_new() failed");
|
||||||
|
|
||||||
pw_thread_loop_start(thread_loop);
|
pw_thread_loop_start(thread_loop);
|
||||||
|
|
||||||
|
stream = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -471,6 +471,16 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 write_in_frames = buffer_size_in_frames;
|
UINT32 write_in_frames = buffer_size_in_frames;
|
||||||
|
DWORD mode = 0;
|
||||||
|
AtScopeExit(&) {
|
||||||
|
render_client->ReleaseBuffer(write_in_frames, mode);
|
||||||
|
|
||||||
|
if (!started) {
|
||||||
|
Start(client);
|
||||||
|
started = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!is_exclusive) {
|
if (!is_exclusive) {
|
||||||
UINT32 data_in_frames =
|
UINT32 data_in_frames =
|
||||||
GetCurrentPaddingFrames(client);
|
GetCurrentPaddingFrames(client);
|
||||||
|
@ -481,7 +491,6 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE *data;
|
BYTE *data;
|
||||||
DWORD mode = 0;
|
|
||||||
|
|
||||||
if (HRESULT result =
|
if (HRESULT result =
|
||||||
render_client->GetBuffer(write_in_frames, &data);
|
render_client->GetBuffer(write_in_frames, &data);
|
||||||
|
@ -489,15 +498,6 @@ try {
|
||||||
throw MakeHResultError(result, "Failed to get buffer");
|
throw MakeHResultError(result, "Failed to get buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
AtScopeExit(&) {
|
|
||||||
render_client->ReleaseBuffer(write_in_frames, mode);
|
|
||||||
|
|
||||||
if (!started) {
|
|
||||||
Start(client);
|
|
||||||
started = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const UINT32 write_size = write_in_frames * frame_size;
|
const UINT32 write_size = write_in_frames * frame_size;
|
||||||
UINT32 new_data_size = 0;
|
UINT32 new_data_size = 0;
|
||||||
new_data_size = spsc_buffer.pop(data, write_size);
|
new_data_size = spsc_buffer.pop(data, write_size);
|
||||||
|
|
Loading…
Reference in New Issue