Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
8279cafd
Commit
8279cafd
authored
Jan 21, 2021
by
Max Kellermann
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'v0.22.4'
release v0.22.4
parents
014c2a82
a0d76c3b
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
353 additions
and
101 deletions
+353
-101
NEWS
NEWS
+7
-1
build.py
android/build.py
+2
-1
mpd.conf.5.rst
doc/mpd.conf.5.rst
+2
-1
mpdconf.example
doc/mpdconf.example
+2
-1
protocol.rst
doc/protocol.rst
+22
-7
user.rst
doc/user.rst
+1
-1
ffmpeg.py
python/build/ffmpeg.py
+2
-7
libs.py
python/build/libs.py
+12
-5
openssl.py
python/build/openssl.py
+55
-0
project.py
python/build/project.py
+1
-1
SongPrint.cxx
src/SongPrint.cxx
+8
-1
Client.hxx
src/client/Client.hxx
+7
-0
Response.cxx
src/client/Response.cxx
+1
-1
Response.hxx
src/client/Response.hxx
+2
-2
AllCommands.cxx
src/command/AllCommands.cxx
+1
-0
ClientCommands.cxx
src/command/ClientCommands.cxx
+15
-0
ClientCommands.hxx
src/command/ClientCommands.hxx
+3
-0
FileCommands.cxx
src/command/FileCommands.cxx
+20
-8
Request.hxx
src/command/Request.hxx
+2
-2
Directory.cxx
src/db/plugins/simple/Directory.cxx
+2
-2
ExportedSong.hxx
src/db/plugins/simple/ExportedSong.hxx
+42
-0
SimpleDatabasePlugin.cxx
src/db/plugins/simple/SimpleDatabasePlugin.cxx
+6
-6
SimpleDatabasePlugin.hxx
src/db/plugins/simple/SimpleDatabasePlugin.hxx
+2
-2
Song.cxx
src/db/plugins/simple/Song.cxx
+80
-6
Song.hxx
src/db/plugins/simple/Song.hxx
+2
-2
FullyBufferedSocket.hxx
src/event/FullyBufferedSocket.hxx
+4
-0
CurlInputPlugin.cxx
src/input/plugins/CurlInputPlugin.cxx
+9
-2
RegexPointer.hxx
src/lib/pcre/RegexPointer.hxx
+11
-0
SlesOutputPlugin.cxx
src/output/plugins/sles/SlesOutputPlugin.cxx
+1
-0
CurlStorage.cxx
src/storage/plugins/CurlStorage.cxx
+4
-20
ForeignFifoBuffer.hxx
src/util/ForeignFifoBuffer.hxx
+1
-1
PeakBuffer.cxx
src/util/PeakBuffer.cxx
+13
-13
PeakBuffer.hxx
src/util/PeakBuffer.hxx
+11
-8
No files found.
NEWS
View file @
8279cafd
...
...
@@ -2,7 +2,11 @@ ver 0.23 (not yet released)
* protocol
- new command "getvol"
ver 0.22.4 (not yet released)
ver 0.22.4 (2021/01/21)
* protocol
- add command "binarylimit" to allow larger chunk sizes
- fix "readpicture" on 32 bit machines
- show duration and tags of songs in virtual playlist (CUE) folders
* storage
- curl: fix several WebDAV protocol bugs
* decoder
...
...
@@ -11,6 +15,8 @@ ver 0.22.4 (not yet released)
- ffmpeg: detect the output sample format
* output
- moveoutput: fix always_on and tag lost on move
* Android
- enable https:// support (via OpenSSL)
ver 0.22.3 (2020/11/06)
* playlist
...
...
android/build.py
View file @
8279cafd
...
...
@@ -103,7 +103,7 @@ class AndroidNdkToolchain:
llvm_bin
=
os
.
path
.
join
(
llvm_path
,
'bin'
)
self
.
cc
=
os
.
path
.
join
(
llvm_bin
,
'clang'
)
self
.
cxx
=
os
.
path
.
join
(
llvm_bin
,
'clang++'
)
common_flags
+=
' -target '
+
llvm_triple
+
' -
integrated-as -
gcc-toolchain '
+
toolchain_path
common_flags
+=
' -target '
+
llvm_triple
+
' -gcc-toolchain '
+
toolchain_path
common_flags
+=
' -fvisibility=hidden -fdata-sections -ffunction-sections'
...
...
@@ -172,6 +172,7 @@ thirdparty_libs = [
wildmidi
,
gme
,
ffmpeg
,
openssl
,
curl
,
libexpat
,
libnfs
,
...
...
doc/mpd.conf.5.rst
View file @
8279cafd
...
...
@@ -130,7 +130,8 @@ audio_output
replaygain <off or album or track or auto>
If specified, mpd will adjust the volume of songs played using ReplayGain
tags (see http://www.replaygain.org/). Setting this to "album" will
tags (see https://wiki.hydrogenaud.io/index.php?title=Replaygain).
Setting this to "album" will
adjust volume using the album's ReplayGain tags, while setting it to "track"
will adjust it using the track ReplayGain tags. "auto" uses the track
ReplayGain tags if random play is activated otherwise the album ReplayGain
...
...
doc/mpdconf.example
View file @
8279cafd
...
...
@@ -372,7 +372,8 @@ input {
# the argument "off", "album", "track" or "auto". "auto" is a special mode that
# chooses between "track" and "album" depending on the current state of
# random playback. If random playback is enabled then "track" mode is used.
# See <http://www.replaygain.org> for more details about ReplayGain.
# See <https://wiki.hydrogenaud.io/index.php?title=Replaygain> for
# more details about ReplayGain.
# This setting is off by default.
#
#replaygain "album"
...
...
doc/protocol.rst
View file @
8279cafd
...
...
@@ -69,11 +69,14 @@ that, the specified number of bytes of binary data follows, then a
newline, and finally the ``OK`` line.
If the object to be transmitted is large, the server may choose a
reasonable chunk size and transmit only a portion. Usually, the
response also contains a ``size`` line which specifies the total
(uncropped) size, and the command usually has a way to specify an
offset into the object; this way, the client can copy the whole file
without blocking the connection for too long.
reasonable chunk size and transmit only a portion. The maximum chunk
size can be changed by clients with the :ref:`binarylimit
<command_binarylimit>` command.
Usually, the response also contains a ``size`` line which specifies
the total (uncropped) size, and the command usually has a way to
specify an offset into the object; this way, the client can copy the
whole file without blocking the connection for too long.
Example::
...
...
@@ -739,7 +742,7 @@ Whenever possible, ids should be used.
.. _command_playlistfind:
:command:`playlistfind {
TAG} {NEEDLE
}`
:command:`playlistfind {
FILTER
}`
Finds songs in the queue with strict
matching.
...
...
@@ -760,7 +763,7 @@ Whenever possible, ids should be used.
.. _command_playlistsearch:
:command:`playlistsearch {
TAG} {NEEDLE
}`
:command:`playlistsearch {
FILTER
}`
Searches case-insensitively for partial matches in the
queue.
...
...
@@ -1367,6 +1370,17 @@ Connection settings
:command:`ping`
Does nothing but return "OK".
.. _command_binarylimit:
:command:`binarylimit SIZE` [#since_0_22_4]_
Set the maximum :ref:`binary response <binary>` size for the
current connection to the specified number of bytes.
A bigger value means less overhead for transmitting large
entities, but it also means that the connection is blocked for a
longer time.
.. _command_tagtypes:
:command:`tagtypes`
...
...
@@ -1595,3 +1609,4 @@ client-to-client messages are local to the current partition.
.. [#since_0_19] Since :program:`MPD` 0.19
.. [#since_0_20] Since :program:`MPD` 0.20
.. [#since_0_21] Since :program:`MPD` 0.21
.. [#since_0_22_4] Since :program:`MPD` 0.22.4
doc/user.rst
View file @
8279cafd
...
...
@@ -167,7 +167,7 @@ Compiling for Android
You need:
* Android SDK
*
Android NDK
*
`Android NDK r22 <https://developer.android.com/ndk/downloads>`_
Just like with the native build, unpack the :program:`MPD` source
tarball and change into the directory. Then, instead of
...
...
python/build/ffmpeg.py
View file @
8279cafd
...
...
@@ -10,11 +10,6 @@ class FfmpegProject(Project):
self
.
configure_args
=
configure_args
self
.
cppflags
=
cppflags
def
_filter_cflags
(
self
,
flags
):
# FFmpeg expects the GNU as syntax
flags
=
flags
.
replace
(
' -integrated-as '
,
' -no-integrated-as '
)
return
flags
def
build
(
self
,
toolchain
):
src
=
self
.
unpack
(
toolchain
)
build
=
self
.
make_build_path
(
toolchain
)
...
...
@@ -36,8 +31,8 @@ class FfmpegProject(Project):
'--cc='
+
toolchain
.
cc
,
'--cxx='
+
toolchain
.
cxx
,
'--nm='
+
toolchain
.
nm
,
'--extra-cflags='
+
self
.
_filter_cflags
(
toolchain
.
cflags
)
+
' '
+
toolchain
.
cppflags
+
' '
+
self
.
cppflags
,
'--extra-cxxflags='
+
self
.
_filter_cflags
(
toolchain
.
cxxflags
)
+
' '
+
toolchain
.
cppflags
+
' '
+
self
.
cppflags
,
'--extra-cflags='
+
toolchain
.
cflags
+
' '
+
toolchain
.
cppflags
+
' '
+
self
.
cppflags
,
'--extra-cxxflags='
+
toolchain
.
cxxflags
+
' '
+
toolchain
.
cppflags
+
' '
+
self
.
cppflags
,
'--extra-ldflags='
+
toolchain
.
ldflags
,
'--extra-libs='
+
toolchain
.
libs
,
'--ar='
+
toolchain
.
ar
,
...
...
python/build/libs.py
View file @
8279cafd
...
...
@@ -7,6 +7,7 @@ from build.meson import MesonProject
from
build.cmake
import
CmakeProject
from
build.autotools
import
AutotoolsProject
from
build.ffmpeg
import
FfmpegProject
from
build.openssl
import
OpenSSLProject
from
build.boost
import
BoostProject
libmpdclient
=
MesonProject
(
...
...
@@ -376,9 +377,15 @@ ffmpeg = FfmpegProject(
],
)
openssl
=
OpenSSLProject
(
'https://www.openssl.org/source/openssl-3.0.0-alpha10.tar.gz'
,
'b1699acf2148db31f12edf5ebfdf12a92bfd3f0e60538d169710408a3cd3b138'
,
'include/openssl/ossl_typ.h'
,
)
curl
=
AutotoolsProject
(
'http://curl.haxx.se/download/curl-7.7
3
.0.tar.xz'
,
'
7c4c7ca4ea88abe00fea4740dcf81075c031b1d0bb23aff2d5efde20a3c2408a
'
,
'http://curl.haxx.se/download/curl-7.7
4
.0.tar.xz'
,
'
999d5f2c403cf6e25d58319fdd596611e455dd195208746bc6e6d197a77e878b
'
,
'lib/libcurl.a'
,
[
'--disable-shared'
,
'--enable-static'
,
...
...
@@ -399,7 +406,7 @@ curl = AutotoolsProject(
'--disable-netrc'
,
'--disable-progress-meter'
,
'--disable-alt-svc'
,
'--without-
ssl'
,
'--without-
gnutls'
,
'--without-nss'
,
'--without-libssh2'
,
'--without-gnutls'
,
'--without-nss'
,
'--without-libssh2'
,
],
patches
=
'src/lib/curl/patches'
,
...
...
@@ -434,7 +441,7 @@ libnfs = AutotoolsProject(
)
boost
=
BoostProject
(
'https://dl.bintray.com/boostorg/release/1.7
4.0/source/boost_1_74
_0.tar.bz2'
,
'
83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
'
,
'https://dl.bintray.com/boostorg/release/1.7
5.0/source/boost_1_75
_0.tar.bz2'
,
'
953db31e016db7bb207f11432bef7df100516eeb746843fa0486a222e3fd49cb
'
,
'include/boost/version.hpp'
,
)
python/build/openssl.py
0 → 100644
View file @
8279cafd
import
subprocess
from
build.makeproject
import
MakeProject
class
OpenSSLProject
(
MakeProject
):
def
__init__
(
self
,
url
,
md5
,
installed
,
**
kwargs
):
MakeProject
.
__init__
(
self
,
url
,
md5
,
installed
,
install_target
=
'install_dev'
,
**
kwargs
)
def
get_make_args
(
self
,
toolchain
):
return
MakeProject
.
get_make_args
(
self
,
toolchain
)
+
[
'CC='
+
toolchain
.
cc
,
'CFLAGS='
+
toolchain
.
cflags
,
'CPPFLAGS='
+
toolchain
.
cppflags
,
'AR='
+
toolchain
.
ar
,
'RANLIB='
+
toolchain
.
ranlib
,
'build_libs'
,
]
def
build
(
self
,
toolchain
):
src
=
self
.
unpack
(
toolchain
,
out_of_tree
=
False
)
# OpenSSL has a weird target architecture scheme with lots of
# hard-coded architectures; this table translates between our
# "toolchain_arch" (HOST_TRIPLET) and the OpenSSL target
openssl_archs
=
{
# not using "android-*" because those OpenSSL targets want
# to know where the SDK is, but our own build scripts
# prepared everything already to look like a regular Linux
# build
'arm-linux-androideabi'
:
'linux-generic32'
,
'aarch64-linux-android'
:
'linux-aarch64'
,
'i686-linux-android'
:
'linux-x86-clang'
,
'x86_64-linux-android'
:
'linux-x86_64-clang'
,
# Kobo
'arm-linux-gnueabihf'
:
'linux-generic32'
,
# Windows
'i686-w64-mingw32'
:
'mingw'
,
'x86_64-w64-mingw32'
:
'mingw64'
,
}
openssl_arch
=
openssl_archs
[
toolchain
.
arch
]
subprocess
.
check_call
([
'./Configure'
,
'no-shared'
,
'no-module'
,
'no-engine'
,
'no-static-engine'
,
'no-async'
,
'no-tests'
,
'no-asm'
,
# "asm" causes build failures on Windows
openssl_arch
,
'--prefix='
+
toolchain
.
install_prefix
],
cwd
=
src
,
env
=
toolchain
.
env
)
MakeProject
.
build
(
self
,
toolchain
,
src
)
python/build/project.py
View file @
8279cafd
...
...
@@ -20,7 +20,7 @@ class Project:
self
.
base
=
base
if
name
is
None
or
version
is
None
:
m
=
re
.
match
(
r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*)$'
,
self
.
base
)
m
=
re
.
match
(
r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*
(?:-alpha\d+)?
)$'
,
self
.
base
)
if
name
is
None
:
name
=
m
.
group
(
1
)
if
version
is
None
:
version
=
m
.
group
(
2
)
...
...
src/SongPrint.cxx
View file @
8279cafd
...
...
@@ -91,7 +91,14 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept
if
(
song
.
audio_format
.
IsDefined
())
r
.
Format
(
"Format: %s
\n
"
,
ToString
(
song
.
audio_format
).
c_str
());
tag_print
(
r
,
song
.
tag
);
tag_print_values
(
r
,
song
.
tag
);
const
auto
duration
=
song
.
GetDuration
();
if
(
!
duration
.
IsNegative
())
r
.
Format
(
"Time: %i
\n
"
"duration: %1.3f
\n
"
,
duration
.
RoundS
(),
duration
.
ToDoubleS
());
}
void
...
...
src/client/Client.hxx
View file @
8279cafd
...
...
@@ -84,6 +84,12 @@ public:
*/
TagMask
tag_mask
=
TagMask
::
All
();
/**
* The maximum number of bytes transmitted in a binary
* response. Can be changed with the "binarylimit" command.
*/
size_t
binary_limit
=
8192
;
private
:
static
constexpr
size_t
MAX_SUBSCRIPTIONS
=
16
;
...
...
@@ -122,6 +128,7 @@ public:
~
Client
()
noexcept
;
using
FullyBufferedSocket
::
GetEventLoop
;
using
FullyBufferedSocket
::
GetOutputMaxSize
;
gcc_pure
bool
IsExpired
()
const
noexcept
{
...
...
src/client/Response.cxx
View file @
8279cafd
...
...
@@ -59,7 +59,7 @@ Response::Format(const char *fmt, ...) noexcept
bool
Response
::
WriteBinary
(
ConstBuffer
<
void
>
payload
)
noexcept
{
assert
(
payload
.
size
<=
MAX_BINARY_SIZE
);
assert
(
payload
.
size
<=
client
.
binary_limit
);
return
Format
(
"binary: %zu
\n
"
,
payload
.
size
)
&&
Write
(
payload
.
data
,
payload
.
size
)
&&
...
...
src/client/Response.hxx
View file @
8279cafd
...
...
@@ -75,9 +75,9 @@ public:
bool
Write
(
const
void
*
data
,
size_t
length
)
noexcept
;
bool
Write
(
const
char
*
data
)
noexcept
;
bool
FormatV
(
const
char
*
fmt
,
std
::
va_list
args
)
noexcept
;
bool
Format
(
const
char
*
fmt
,
...)
noexcept
;
static
constexpr
size_t
MAX_BINARY_SIZE
=
8192
;
gcc_printf
(
2
,
3
)
bool
Format
(
const
char
*
fmt
,
...)
noexcept
;
/**
* Write a binary chunk; this writes the "binary" line, the
...
...
src/command/AllCommands.cxx
View file @
8279cafd
...
...
@@ -87,6 +87,7 @@ static constexpr struct command commands[] = {
{
"addid"
,
PERMISSION_ADD
,
1
,
2
,
handle_addid
},
{
"addtagid"
,
PERMISSION_ADD
,
3
,
3
,
handle_addtagid
},
{
"albumart"
,
PERMISSION_READ
,
2
,
2
,
handle_album_art
},
{
"binarylimit"
,
PERMISSION_NONE
,
1
,
1
,
handle_binary_limit
},
{
"channels"
,
PERMISSION_READ
,
0
,
0
,
handle_channels
},
{
"clear"
,
PERMISSION_CONTROL
,
0
,
0
,
handle_clear
},
{
"clearerror"
,
PERMISSION_CONTROL
,
0
,
0
,
handle_clearerror
},
...
...
src/command/ClientCommands.cxx
View file @
8279cafd
...
...
@@ -41,6 +41,21 @@ handle_ping([[maybe_unused]] Client &client, [[maybe_unused]] Request args,
}
CommandResult
handle_binary_limit
(
Client
&
client
,
Request
args
,
[[
maybe_unused
]]
Response
&
r
)
{
size_t
value
=
args
.
ParseUnsigned
(
0
,
client
.
GetOutputMaxSize
()
-
4096
);
if
(
value
<
64
)
{
r
.
Error
(
ACK_ERROR_ARG
,
"Value too small"
);
return
CommandResult
::
ERROR
;
}
client
.
binary_limit
=
value
;
return
CommandResult
::
OK
;
}
CommandResult
handle_password
(
Client
&
client
,
Request
args
,
Response
&
r
)
{
unsigned
permission
=
0
;
...
...
src/command/ClientCommands.hxx
View file @
8279cafd
...
...
@@ -33,6 +33,9 @@ CommandResult
handle_ping
(
Client
&
client
,
Request
request
,
Response
&
response
);
CommandResult
handle_binary_limit
(
Client
&
client
,
Request
request
,
Response
&
response
);
CommandResult
handle_password
(
Client
&
client
,
Request
request
,
Response
&
response
);
CommandResult
...
...
src/command/FileCommands.cxx
View file @
8279cafd
...
...
@@ -43,6 +43,7 @@
#include "thread/Mutex.hxx"
#include "Log.hxx"
#include <algorithm>
#include <cassert>
#include <cinttypes>
/* for PRIu64 */
...
...
@@ -202,17 +203,26 @@ read_stream_art(Response &r, const char *uri, size_t offset)
const
offset_type
art_file_size
=
is
->
GetSize
();
uint8_t
buffer
[
Response
::
MAX_BINARY_SIZE
];
size_t
read_size
;
if
(
offset
>
art_file_size
)
{
r
.
Error
(
ACK_ERROR_ARG
,
"Offset too large"
);
return
CommandResult
::
ERROR
;
}
std
::
size_t
buffer_size
=
std
::
min
<
offset_type
>
(
art_file_size
-
offset
,
r
.
GetClient
().
binary_limit
);
{
std
::
unique_ptr
<
std
::
byte
[]
>
buffer
(
new
std
::
byte
[
buffer_size
]);
std
::
size_t
read_size
=
0
;
if
(
buffer_size
>
0
)
{
std
::
unique_lock
<
Mutex
>
lock
(
mutex
);
is
->
Seek
(
lock
,
offset
);
read_size
=
is
->
Read
(
lock
,
&
buffer
,
sizeof
(
buffer
)
);
read_size
=
is
->
Read
(
lock
,
buffer
.
get
(),
buffer_size
);
}
r
.
Format
(
"size: %"
PRIoffset
"
\n
"
,
art_file_size
);
r
.
WriteBinary
({
buffer
,
read_size
});
r
.
WriteBinary
({
buffer
.
get
()
,
read_size
});
return
CommandResult
::
OK
;
}
...
...
@@ -293,14 +303,16 @@ public:
return
;
}
response
.
Format
(
"size: %
"
PRIoffset
"
\n
"
,
buffer
.
size
);
response
.
Format
(
"size: %
zu
\n
"
,
buffer
.
size
);
if
(
mime_type
!=
nullptr
)
response
.
Format
(
"type: %s
\n
"
,
mime_type
);
buffer
.
size
-=
offset
;
if
(
buffer
.
size
>
Response
::
MAX_BINARY_SIZE
)
buffer
.
size
=
Response
::
MAX_BINARY_SIZE
;
const
std
::
size_t
binary_limit
=
response
.
GetClient
().
binary_limit
;
if
(
buffer
.
size
>
binary_limit
)
buffer
.
size
=
binary_limit
;
buffer
.
data
=
OffsetPointer
(
buffer
.
data
,
offset
);
response
.
WriteBinary
(
buffer
);
...
...
src/command/Request.hxx
View file @
8279cafd
...
...
@@ -54,12 +54,12 @@ public:
return
ParseCommandArgInt
(
data
[
idx
],
min_value
,
max_value
);
}
int
ParseUnsigned
(
unsigned
idx
)
const
{
unsigned
ParseUnsigned
(
unsigned
idx
)
const
{
assert
(
idx
<
size
);
return
ParseCommandArgUnsigned
(
data
[
idx
]);
}
int
ParseUnsigned
(
unsigned
idx
,
unsigned
max_value
)
const
{
unsigned
ParseUnsigned
(
unsigned
idx
,
unsigned
max_value
)
const
{
assert
(
idx
<
size
);
return
ParseCommandArgUnsigned
(
data
[
idx
],
max_value
);
}
...
...
src/db/plugins/simple/Directory.cxx
View file @
8279cafd
...
...
@@ -18,11 +18,11 @@
*/
#include "Directory.hxx"
#include "ExportedSong.hxx"
#include "SongSort.hxx"
#include "Song.hxx"
#include "Mount.hxx"
#include "db/LightDirectory.hxx"
#include "song/LightSong.hxx"
#include "db/Uri.hxx"
#include "db/DatabaseLock.hxx"
#include "db/Interface.hxx"
...
...
@@ -234,7 +234,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
if
(
visit_song
)
{
for
(
auto
&
song
:
songs
){
const
LightSong
song2
=
song
.
Export
();
const
auto
song2
=
song
.
Export
();
if
(
filter
==
nullptr
||
filter
->
Match
(
song2
))
visit_song
(
song2
);
}
...
...
src/db/plugins/simple/ExportedSong.hxx
0 → 100644
View file @
8279cafd
/*
* Copyright 2003-2021 The Music Player Daemon Project
* http://www.musicpd.org
*
* 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.
*
* 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.
*/
#ifndef MPD_DB_SIMPLE_EXPORTED_SONG_HXX
#define MPD_DB_SIMPLE_EXPORTED_SONG_HXX
#include "song/LightSong.hxx"
#include "tag/Tag.hxx"
/**
* The return type for Song::Export(). In addition to implementing
* #LightSong, it hold allocations necessary to represent the #Song as
* a #LightSong, e.g. a merged #Tag.
*/
class
ExportedSong
:
public
LightSong
{
Tag
tag_buffer
;
public
:
using
LightSong
::
LightSong
;
ExportedSong
(
const
char
*
_uri
,
Tag
&&
_tag
)
noexcept
:
LightSong
(
_uri
,
tag_buffer
),
tag_buffer
(
std
::
move
(
_tag
))
{}
};
#endif
src/db/plugins/simple/SimpleDatabasePlugin.cxx
View file @
8279cafd
...
...
@@ -233,25 +233,25 @@ SimpleDatabase::GetSong(std::string_view uri) const
"No such song"
);
const
Song
*
song
=
r
.
directory
->
FindSong
(
r
.
rest
);
protect
.
unlock
();
if
(
song
==
nullptr
)
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
"No such song"
);
light_song
.
Construct
(
song
->
Export
());
exported_song
.
Construct
(
song
->
Export
());
protect
.
unlock
();
#ifndef NDEBUG
++
borrowed_song_count
;
#endif
return
&
light
_song
.
Get
();
return
&
exported
_song
.
Get
();
}
void
SimpleDatabase
::
ReturnSong
([[
maybe_unused
]]
const
LightSong
*
song
)
const
noexcept
{
assert
(
song
!=
nullptr
);
assert
(
song
==
prefixed_light_song
||
song
==
&
light
_song
.
Get
());
assert
(
song
==
prefixed_light_song
||
song
==
&
exported
_song
.
Get
());
if
(
prefixed_light_song
!=
nullptr
)
{
delete
prefixed_light_song
;
...
...
@@ -262,7 +262,7 @@ SimpleDatabase::ReturnSong([[maybe_unused]] const LightSong *song) const noexcep
--
borrowed_song_count
;
#endif
light
_song
.
Destruct
();
exported
_song
.
Destruct
();
}
}
...
...
@@ -316,7 +316,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
if
(
visit_song
)
{
Song
*
song
=
r
.
directory
->
FindSong
(
r
.
rest
);
if
(
song
!=
nullptr
)
{
const
LightSong
song2
=
song
->
Export
();
const
auto
song2
=
song
->
Export
();
if
(
selection
.
Match
(
song2
))
visit_song
(
song2
);
...
...
src/db/plugins/simple/SimpleDatabasePlugin.hxx
View file @
8279cafd
...
...
@@ -20,10 +20,10 @@
#ifndef MPD_SIMPLE_DATABASE_PLUGIN_HXX
#define MPD_SIMPLE_DATABASE_PLUGIN_HXX
#include "ExportedSong.hxx"
#include "db/Interface.hxx"
#include "db/Ptr.hxx"
#include "fs/AllocatedPath.hxx"
#include "song/LightSong.hxx"
#include "util/Manual.hxx"
#include "util/Compiler.h"
#include "config.h"
...
...
@@ -63,7 +63,7 @@ class SimpleDatabase : public Database {
/**
* A buffer for GetSong().
*/
mutable
Manual
<
LightSong
>
light
_song
;
mutable
Manual
<
ExportedSong
>
exported
_song
;
#ifndef NDEBUG
mutable
unsigned
borrowed_song_count
;
...
...
src/db/plugins/simple/Song.cxx
View file @
8279cafd
...
...
@@ -18,11 +18,15 @@
*/
#include "Song.hxx"
#include "ExportedSong.hxx"
#include "Directory.hxx"
#include "tag/Tag.hxx"
#include "tag/Builder.hxx"
#include "song/DetachedSong.hxx"
#include "song/LightSong.hxx"
#include "fs/Traits.hxx"
#include "time/ChronoUtil.hxx"
#include "util/IterableSplitString.hxx"
Song
::
Song
(
DetachedSong
&&
other
,
Directory
&
_parent
)
noexcept
:
tag
(
std
::
move
(
other
.
WritableTag
())),
...
...
@@ -53,17 +57,87 @@ Song::GetURI() const noexcept
}
}
LightSong
/**
* Path name traversal of a #Directory.
*/
gcc_pure
static
const
Directory
*
FindTargetDirectory
(
const
Directory
&
base
,
StringView
path
)
noexcept
{
const
auto
*
directory
=
&
base
;
for
(
const
StringView
name
:
IterableSplitString
(
path
,
'/'
))
{
if
(
name
.
empty
()
||
name
.
Equals
(
"."
))
continue
;
directory
=
name
.
Equals
(
".."
)
?
directory
->
parent
:
directory
->
FindChild
(
name
);
if
(
directory
==
nullptr
)
break
;
}
return
directory
;
}
/**
* Path name traversal of a #Song.
*/
gcc_pure
static
const
Song
*
FindTargetSong
(
const
Directory
&
_directory
,
StringView
target
)
noexcept
{
auto
[
path
,
last
]
=
target
.
SplitLast
(
'/'
);
if
(
last
==
nullptr
)
{
last
=
path
;
path
=
nullptr
;
}
if
(
last
.
empty
())
return
nullptr
;
const
auto
*
directory
=
FindTargetDirectory
(
_directory
,
path
);
if
(
directory
==
nullptr
)
return
nullptr
;
return
directory
->
FindSong
(
last
);
}
ExportedSong
Song
::
Export
()
const
noexcept
{
LightSong
dest
(
filename
.
c_str
(),
tag
);
const
auto
*
target_song
=
!
target
.
empty
()
?
FindTargetSong
(
parent
,
(
std
::
string_view
)
target
)
:
nullptr
;
Tag
merged_tag
;
if
(
target_song
!=
nullptr
)
{
/* if we found the target song (which may be the
underlying song file of a CUE file), merge the tags
from that song with this song's tags (from the CUE
file) */
TagBuilder
builder
(
tag
);
builder
.
Complement
(
target_song
->
tag
);
merged_tag
=
builder
.
Commit
();
}
ExportedSong
dest
=
merged_tag
.
IsDefined
()
?
ExportedSong
(
filename
.
c_str
(),
std
::
move
(
merged_tag
))
:
ExportedSong
(
filename
.
c_str
(),
tag
);
if
(
!
parent
.
IsRoot
())
dest
.
directory
=
parent
.
GetPath
();
if
(
!
target
.
empty
())
dest
.
real_uri
=
target
.
c_str
();
dest
.
mtime
=
mtime
;
dest
.
start_time
=
start_time
;
dest
.
end_time
=
end_time
;
dest
.
audio_format
=
audio_format
;
dest
.
mtime
=
IsNegative
(
mtime
)
&&
target_song
!=
nullptr
?
target_song
->
mtime
:
mtime
;
dest
.
start_time
=
start_time
.
IsZero
()
&&
target_song
!=
nullptr
?
target_song
->
start_time
:
start_time
;
dest
.
end_time
=
end_time
.
IsZero
()
&&
target_song
!=
nullptr
?
target_song
->
end_time
:
end_time
;
dest
.
audio_format
=
audio_format
.
IsDefined
()
||
target_song
==
nullptr
?
audio_format
:
target_song
->
audio_format
;
return
dest
;
}
src/db/plugins/simple/Song.hxx
View file @
8279cafd
...
...
@@ -32,8 +32,8 @@
#include <string>
struct
StringView
;
struct
LightSong
;
struct
Directory
;
class
ExportedSong
;
class
DetachedSong
;
class
Storage
;
class
ArchiveFile
;
...
...
@@ -153,7 +153,7 @@ struct Song {
std
::
string
GetURI
()
const
noexcept
;
gcc_pure
Light
Song
Export
()
const
noexcept
;
Exported
Song
Export
()
const
noexcept
;
};
typedef
boost
::
intrusive
::
list
<
Song
,
...
...
src/event/FullyBufferedSocket.hxx
View file @
8279cafd
...
...
@@ -48,6 +48,10 @@ public:
BufferedSocket
::
Close
();
}
std
::
size_t
GetOutputMaxSize
()
const
noexcept
{
return
output
.
max_size
();
}
private
:
/**
* @return the number of bytes written to the socket, 0 if the
...
...
src/input/plugins/CurlInputPlugin.cxx
View file @
8279cafd
...
...
@@ -369,8 +369,15 @@ input_curl_init(EventLoop &event_loop, const ConfigBlock &block)
proxy_user
=
block
.
GetBlockValue
(
"proxy_user"
);
proxy_password
=
block
.
GetBlockValue
(
"proxy_password"
);
verify_peer
=
block
.
GetBlockValue
(
"verify_peer"
,
true
);
verify_host
=
block
.
GetBlockValue
(
"verify_host"
,
true
);
#ifdef ANDROID
// TODO: figure out how to use Android's CA certificates and re-enable verify
constexpr
bool
default_verify
=
false
;
#else
constexpr
bool
default_verify
=
true
;
#endif
verify_peer
=
block
.
GetBlockValue
(
"verify_peer"
,
default_verify
);
verify_host
=
block
.
GetBlockValue
(
"verify_host"
,
default_verify
);
}
static
void
...
...
src/lib/pcre/RegexPointer.hxx
View file @
8279cafd
...
...
@@ -40,6 +40,13 @@
#include <array>
#if GCC_CHECK_VERSION(11,0)
#pragma GCC diagnostic push
/* bogus GCC 11 warning "ovector may be used uninitialized" in the
ovector.size() call */
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
class
RegexPointer
{
protected
:
pcre
*
re
=
nullptr
;
...
...
@@ -63,4 +70,8 @@ public:
}
};
#if GCC_CHECK_VERSION(11,0)
#pragma GCC diagnostic pop
#endif
#endif
src/output/plugins/sles/SlesOutputPlugin.cxx
View file @
8279cafd
...
...
@@ -33,6 +33,7 @@
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <cassert>
#include <iterator>
#include <stdexcept>
...
...
src/storage/plugins/CurlStorage.cxx
View file @
8279cafd
...
...
@@ -468,19 +468,11 @@ CurlStorage::GetInfo(std::string_view uri_utf8, [[maybe_unused]] bool follow)
gcc_pure
static
std
::
string_view
UriPathOrSlash
(
const
char
*
uri
,
bool
relative
)
noexcept
UriPathOrSlash
(
const
char
*
uri
)
noexcept
{
auto
path
=
uri_get_path
(
uri
);
if
(
path
.
data
()
==
nullptr
)
path
=
"/"
;
else
if
(
relative
)
{
// search after first slash
path
=
path
.
substr
(
1
);
auto
slash
=
path
.
find
(
'/'
);
if
(
slash
!=
std
::
string_view
::
npos
)
path
=
path
.
substr
(
slash
);
}
return
path
;
}
...
...
@@ -489,15 +481,13 @@ UriPathOrSlash(const char *uri, bool relative) noexcept
*/
class
HttpListDirectoryOperation
final
:
public
PropfindOperation
{
const
std
::
string
base_path
;
const
std
::
string
base_path_relative
;
MemoryStorageDirectoryReader
::
List
entries
;
public
:
HttpListDirectoryOperation
(
CurlGlobal
&
curl
,
const
char
*
uri
)
:
PropfindOperation
(
curl
,
uri
,
1
),
base_path
(
CurlUnescape
(
GetEasy
(),
UriPathOrSlash
(
uri
,
false
))),
base_path_relative
(
CurlUnescape
(
GetEasy
(),
UriPathOrSlash
(
uri
,
true
)))
{}
base_path
(
CurlUnescape
(
GetEasy
(),
UriPathOrSlash
(
uri
)))
{}
std
::
unique_ptr
<
StorageDirectoryReader
>
Perform
()
{
DeferStart
();
...
...
@@ -523,15 +513,9 @@ private:
/* kludge: ignoring case in this comparison to avoid
false negatives if the web server uses a different
case */
if
(
uri_has_scheme
(
path
))
{
path
=
StringAfterPrefixIgnoreCase
(
path
,
base_path
.
c_str
());
}
else
{
path
=
StringAfterPrefixIgnoreCase
(
path
,
base_path_relative
.
c_str
());
}
if
(
path
==
nullptr
||
path
.
empty
())
{
path
=
StringAfterPrefixIgnoreCase
(
path
,
base_path
.
c_str
());
if
(
path
==
nullptr
||
path
.
empty
())
return
nullptr
;
}
const
char
*
slash
=
path
.
Find
(
'/'
);
if
(
slash
==
nullptr
)
...
...
src/util/ForeignFifoBuffer.hxx
View file @
8279cafd
...
...
@@ -235,7 +235,7 @@ public:
w
=
Write
();
}
size_t
n
=
std
::
min
(
r
.
size
,
w
.
size
);
const
auto
n
=
std
::
min
(
r
.
size
,
w
.
size
);
std
::
move
(
r
.
data
,
r
.
data
+
n
,
w
.
data
);
Append
(
n
);
...
...
src/util/PeakBuffer.cxx
View file @
8279cafd
...
...
@@ -25,7 +25,7 @@
#include <string.h>
PeakBuffer
::~
PeakBuffer
()
PeakBuffer
::~
PeakBuffer
()
noexcept
{
delete
normal_buffer
;
delete
peak_buffer
;
...
...
@@ -57,7 +57,7 @@ PeakBuffer::Read() const noexcept
}
void
PeakBuffer
::
Consume
(
size_t
length
)
noexcept
PeakBuffer
::
Consume
(
s
td
::
s
ize_t
length
)
noexcept
{
if
(
normal_buffer
!=
nullptr
&&
!
normal_buffer
->
empty
())
{
normal_buffer
->
Consume
(
length
);
...
...
@@ -75,25 +75,25 @@ PeakBuffer::Consume(size_t length) noexcept
}
}
static
size_t
AppendTo
(
DynamicFifoBuffer
<
uint8_t
>
&
buffer
,
static
s
td
::
s
ize_t
AppendTo
(
DynamicFifoBuffer
<
std
::
byte
>
&
buffer
,
const
void
*
data
,
size_t
length
)
noexcept
{
assert
(
data
!=
nullptr
);
assert
(
length
>
0
);
size_t
total
=
0
;
s
td
::
s
ize_t
total
=
0
;
do
{
const
auto
p
=
buffer
.
Write
();
if
(
p
.
empty
())
break
;
const
size_t
nbytes
=
std
::
min
(
length
,
p
.
size
);
const
s
td
::
s
ize_t
nbytes
=
std
::
min
(
length
,
p
.
size
);
memcpy
(
p
.
data
,
data
,
nbytes
);
buffer
.
Append
(
nbytes
);
data
=
(
const
uint8_t
*
)
data
+
nbytes
;
data
=
(
const
std
::
byte
*
)
data
+
nbytes
;
length
-=
nbytes
;
total
+=
nbytes
;
}
while
(
length
>
0
);
...
...
@@ -102,22 +102,22 @@ AppendTo(DynamicFifoBuffer<uint8_t> &buffer,
}
bool
PeakBuffer
::
Append
(
const
void
*
data
,
size_t
length
)
PeakBuffer
::
Append
(
const
void
*
data
,
s
td
::
s
ize_t
length
)
{
if
(
length
==
0
)
return
true
;
if
(
peak_buffer
!=
nullptr
&&
!
peak_buffer
->
empty
())
{
size_t
nbytes
=
AppendTo
(
*
peak_buffer
,
data
,
length
);
s
td
::
s
ize_t
nbytes
=
AppendTo
(
*
peak_buffer
,
data
,
length
);
return
nbytes
==
length
;
}
if
(
normal_buffer
==
nullptr
)
normal_buffer
=
new
DynamicFifoBuffer
<
uint8_t
>
(
normal_size
);
normal_buffer
=
new
DynamicFifoBuffer
<
std
::
byte
>
(
normal_size
);
size_t
nbytes
=
AppendTo
(
*
normal_buffer
,
data
,
length
);
s
td
::
s
ize_t
nbytes
=
AppendTo
(
*
normal_buffer
,
data
,
length
);
if
(
nbytes
>
0
)
{
data
=
(
const
uint8_t
*
)
data
+
nbytes
;
data
=
(
const
std
::
byte
*
)
data
+
nbytes
;
length
-=
nbytes
;
if
(
length
==
0
)
return
true
;
...
...
@@ -125,7 +125,7 @@ PeakBuffer::Append(const void *data, size_t length)
if
(
peak_buffer
==
nullptr
)
{
if
(
peak_size
>
0
)
peak_buffer
=
new
DynamicFifoBuffer
<
uint8_t
>
(
peak_size
);
peak_buffer
=
new
DynamicFifoBuffer
<
std
::
byte
>
(
peak_size
);
if
(
peak_buffer
==
nullptr
)
return
false
;
}
...
...
src/util/PeakBuffer.hxx
View file @
8279cafd
...
...
@@ -23,7 +23,6 @@
#include "Compiler.h"
#include <cstddef>
#include <cstdint>
template
<
typename
T
>
struct
WritableBuffer
;
template
<
typename
T
>
class
DynamicFifoBuffer
;
...
...
@@ -34,16 +33,16 @@ template<typename T> class DynamicFifoBuffer;
* kernel when it has been consumed.
*/
class
PeakBuffer
{
size_t
normal_size
,
peak_size
;
s
td
::
s
ize_t
normal_size
,
peak_size
;
DynamicFifoBuffer
<
uint8_t
>
*
normal_buffer
,
*
peak_buffer
;
DynamicFifoBuffer
<
std
::
byte
>
*
normal_buffer
,
*
peak_buffer
;
public
:
PeakBuffer
(
s
ize_t
_normal_size
,
size_t
_peak_size
)
PeakBuffer
(
s
td
::
size_t
_normal_size
,
std
::
size_t
_peak_size
)
noexcept
:
normal_size
(
_normal_size
),
peak_size
(
_peak_size
),
normal_buffer
(
nullptr
),
peak_buffer
(
nullptr
)
{}
PeakBuffer
(
PeakBuffer
&&
other
)
PeakBuffer
(
PeakBuffer
&&
other
)
noexcept
:
normal_size
(
other
.
normal_size
),
peak_size
(
other
.
peak_size
),
normal_buffer
(
other
.
normal_buffer
),
peak_buffer
(
other
.
peak_buffer
)
{
...
...
@@ -51,20 +50,24 @@ public:
other
.
peak_buffer
=
nullptr
;
}
~
PeakBuffer
();
~
PeakBuffer
()
noexcept
;
PeakBuffer
(
const
PeakBuffer
&
)
=
delete
;
PeakBuffer
&
operator
=
(
const
PeakBuffer
&
)
=
delete
;
std
::
size_t
max_size
()
const
noexcept
{
return
normal_size
+
peak_size
;
}
gcc_pure
bool
empty
()
const
noexcept
;
gcc_pure
WritableBuffer
<
void
>
Read
()
const
noexcept
;
void
Consume
(
size_t
length
)
noexcept
;
void
Consume
(
s
td
::
s
ize_t
length
)
noexcept
;
bool
Append
(
const
void
*
data
,
size_t
length
);
bool
Append
(
const
void
*
data
,
s
td
::
s
ize_t
length
);
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment