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:
Max Kellermann 2022-03-14 18:58:47 +01:00
commit 407fa2720a
11 changed files with 114 additions and 49 deletions

9
NEWS
View File

@ -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

View File

@ -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):

View File

@ -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',
) )

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
no_sprintf_s

View File

@ -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()

View File

@ -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

View File

@ -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);