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
ecc07e4e
Commit
ecc07e4e
authored
Feb 15, 2021
by
Max Kellermann
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'v0.22.5'
release v0.22.5
parents
cbc830fd
f8be403c
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
152 additions
and
30 deletions
+152
-30
NEWS
NEWS
+11
-1
AndroidManifest.xml
android/AndroidManifest.xml
+1
-0
meson.build
android/meson.build
+2
-2
developer.rst
doc/developer.rst
+3
-3
protocol.rst
doc/protocol.rst
+5
-0
libs.py
python/build/libs.py
+3
-0
QueueCommands.cxx
src/command/QueueCommands.cxx
+5
-0
ExportedSong.hxx
src/db/plugins/simple/ExportedSong.hxx
+9
-0
Control.hxx
src/output/Control.hxx
+8
-0
Thread.cxx
src/output/Thread.cxx
+13
-1
PulseOutputPlugin.cxx
src/output/plugins/PulseOutputPlugin.cxx
+21
-18
WasapiOutputPlugin.cxx
src/output/plugins/WasapiOutputPlugin.cxx
+2
-0
ArgParser.cxx
src/protocol/ArgParser.cxx
+6
-2
RangeArg.hxx
src/protocol/RangeArg.hxx
+48
-2
LightSong.hxx
src/song/LightSong.hxx
+13
-0
ComPtr.hxx
src/win32/ComPtr.hxx
+1
-1
HResult.hxx
src/win32/HResult.hxx
+1
-0
No files found.
NEWS
View file @
ecc07e4e
...
...
@@ -2,13 +2,23 @@ ver 0.23 (not yet released)
* protocol
- new command "getvol"
ver 0.22.5 (not yet released)
ver 0.22.5 (2021/02/15)
* protocol
- error for malformed ranges instead of ignoring silently
- better error message for open-ended range with "move"
* database
- simple: fix missing CUE sheet metadata in "addid" command
* tags
- id: translate TPE3 to Conductor, not Performer
* archive
- iso9660: another fix for unaligned reads
* output
- httpd: error handling on Windows improved
- pulse: fix deadlock with "always_on"
* Windows:
- enable https:// support (via Schannel)
* Android
- work around "Permission denied" on mpd.conf
ver 0.22.4 (2021/01/21)
* protocol
...
...
android/AndroidManifest.xml
View file @
ecc07e4e
...
...
@@ -19,6 +19,7 @@
<uses-permission
android:name=
"android.permission.FOREGROUND_SERVICE"
/>
<application
android:allowBackup=
"true"
android:requestLegacyExternalStorage=
"true"
android:icon=
"@drawable/icon"
android:banner=
"@drawable/icon"
android:label=
"@string/app_name"
>
...
...
android/meson.build
View file @
ecc07e4e
...
...
@@ -5,8 +5,8 @@ android_ndk = get_option('android_ndk')
android_sdk = get_option('android_sdk')
android_abi = get_option('android_abi')
android_sdk_build_tools_version = '2
7.0.0
'
android_sdk_platform = 'android-2
3
'
android_sdk_build_tools_version = '2
9.0.3
'
android_sdk_platform = 'android-2
9
'
android_build_tools_dir = join_paths(android_sdk, 'build-tools', android_sdk_build_tools_version)
android_sdk_platform_dir = join_paths(android_sdk, 'platforms', android_sdk_platform)
...
...
doc/developer.rst
View file @
ecc07e4e
...
...
@@ -68,11 +68,11 @@ There are two active branches in the git repository:
- the "unstable" branch called ``master`` where new features are
merged. This will become the next major release eventually.
- the "stable" branch (currently called ``v0.2
1
.x``) where only bug
- the "stable" branch (currently called ``v0.2
2
.x``) where only bug
fixes are merged.
Once :program:`MPD` 0.2
2 is released, a new branch called ``v0.22
.x``
will be created for 0.2
2 bug-fix releases; after that, ``v0.21
.x``
Once :program:`MPD` 0.2
3 is released, a new branch called ``v0.23
.x``
will be created for 0.2
3 bug-fix releases; after that, ``v0.22
.x``
will eventually cease to be maintained.
After bug fixes have been added to the "stable" branch, it will be
...
...
doc/protocol.rst
View file @
ecc07e4e
...
...
@@ -689,6 +689,11 @@ Whenever possible, ids should be used.
(directories add recursively). ``URI``
can also be a single file.
Clients that are connected via local socket may add arbitrary
local files (URI is an absolute path). Exmaple::
add "/home/foo/Music/bar.ogg"
.. _command_addid:
:command:`addid {URI} [POSITION]`
...
...
python/build/libs.py
View file @
ecc07e4e
...
...
@@ -407,6 +407,9 @@ curl = AutotoolsProject(
'--disable-progress-meter'
,
'--disable-alt-svc'
,
'--without-gnutls'
,
'--without-nss'
,
'--without-libssh2'
,
# native Windows SSL/TLS support, option ignored on non-Windows builds
'--with-schannel'
,
],
patches
=
'src/lib/curl/patches'
,
...
...
src/command/QueueCommands.cxx
View file @
ecc07e4e
...
...
@@ -326,6 +326,11 @@ CommandResult
handle_move
(
Client
&
client
,
Request
args
,
[[
maybe_unused
]]
Response
&
r
)
{
RangeArg
range
=
args
.
ParseRange
(
0
);
if
(
range
.
IsOpenEnded
())
{
r
.
Error
(
ACK_ERROR_ARG
,
"Open-ended range not supported"
);
return
CommandResult
::
ERROR
;
}
int
to
=
args
.
ParseInt
(
1
);
client
.
GetPartition
().
MoveRange
(
range
.
start
,
range
.
end
,
to
);
return
CommandResult
::
OK
;
...
...
src/db/plugins/simple/ExportedSong.hxx
View file @
ecc07e4e
...
...
@@ -37,6 +37,15 @@ public:
ExportedSong
(
const
char
*
_uri
,
Tag
&&
_tag
)
noexcept
:
LightSong
(
_uri
,
tag_buffer
),
tag_buffer
(
std
::
move
(
_tag
))
{}
/* this custom move constructor is necessary so LightSong::tag
points to this instance's #Tag field instead of leaving a
dangling reference to the source object's #Tag field */
ExportedSong
(
ExportedSong
&&
src
)
noexcept
:
LightSong
(
src
,
tag_buffer
),
tag_buffer
(
std
::
move
(
src
.
tag_buffer
))
{}
ExportedSong
&
operator
=
(
ExportedSong
&&
)
=
delete
;
};
#endif
src/output/Control.hxx
View file @
ecc07e4e
...
...
@@ -182,6 +182,14 @@ class AudioOutputControl {
bool
open
=
false
;
/**
* Is the device currently playing, i.e. is its buffer
* (likely) non-empty? If not, then it will never be drained.
*
* This field is only valid while the output is open.
*/
bool
playing
;
/**
* Is the device paused? i.e. the output thread is in the
* ao_pause() loop.
*/
...
...
src/output/Thread.cxx
View file @
ecc07e4e
...
...
@@ -53,7 +53,7 @@ AudioOutputControl::InternalOpen2(const AudioFormat in_audio_format)
if
(
open
&&
cf
!=
output
->
filter_audio_format
)
/* if the filter's output format changes, the output
must be reopened as well */
InternalCloseOutput
(
true
);
InternalCloseOutput
(
playing
);
output
->
filter_audio_format
=
cf
;
...
...
@@ -64,6 +64,7 @@ AudioOutputControl::InternalOpen2(const AudioFormat in_audio_format)
}
open
=
true
;
playing
=
false
;
}
else
if
(
in_audio_format
!=
output
->
out_audio_format
)
{
/* reconfigure the final ConvertFilter for its new
input AudioFormat */
...
...
@@ -285,6 +286,9 @@ AudioOutputControl::PlayChunk(std::unique_lock<Mutex> &lock) noexcept
assert
(
nbytes
%
output
->
out_audio_format
.
GetFrameSize
()
==
0
);
source
.
ConsumeData
(
nbytes
);
/* there's data to be drained from now on */
playing
=
true
;
}
return
true
;
...
...
@@ -371,6 +375,9 @@ AudioOutputControl::InternalPause(std::unique_lock<Mutex> &lock) noexcept
}
skip_delay
=
true
;
/* ignore drain commands until we got something new to play */
playing
=
false
;
}
static
void
...
...
@@ -390,6 +397,10 @@ PlayFull(FilteredAudioOutput &output, ConstBuffer<void> _buffer)
inline
void
AudioOutputControl
::
InternalDrain
()
noexcept
{
/* after this method finishes, there's nothing left to be
drained */
playing
=
false
;
try
{
/* flush the filter and play its remaining output */
...
...
@@ -518,6 +529,7 @@ AudioOutputControl::Task() noexcept
source
.
Cancel
();
if
(
open
)
{
playing
=
false
;
const
ScopeUnlock
unlock
(
mutex
);
output
->
Cancel
();
}
...
...
src/output/plugins/PulseOutputPlugin.cxx
View file @
ecc07e4e
...
...
@@ -56,8 +56,6 @@ class PulseOutput final : AudioOutput {
size_t
writable
;
bool
pause
;
/**
* Was Interrupt() called? This will unblock Play(). It will
* be reset by Cancel() and Pause(), as documented by the
...
...
@@ -113,6 +111,7 @@ public:
[[
nodiscard
]]
std
::
chrono
::
steady_clock
::
duration
Delay
()
const
noexcept
override
;
size_t
Play
(
const
void
*
chunk
,
size_t
size
)
override
;
void
Drain
()
override
;
void
Cancel
()
noexcept
override
;
bool
Pause
()
override
;
...
...
@@ -688,7 +687,6 @@ PulseOutput::Open(AudioFormat &audio_format)
"pa_stream_connect_playback() has failed"
);
}
pause
=
false
;
interrupted
=
false
;
}
...
...
@@ -699,17 +697,6 @@ PulseOutput::Close() noexcept
Pulse
::
LockGuard
lock
(
mainloop
);
if
(
pa_stream_get_state
(
stream
)
==
PA_STREAM_READY
)
{
pa_operation
*
o
=
pa_stream_drain
(
stream
,
pulse_output_stream_success_cb
,
this
);
if
(
o
==
nullptr
)
{
LogPulseError
(
context
,
"pa_stream_drain() has failed"
);
}
else
pulse_wait_for_operation
(
mainloop
,
o
);
}
DeleteStream
();
if
(
context
!=
nullptr
&&
...
...
@@ -780,7 +767,7 @@ PulseOutput::Delay() const noexcept
Pulse
::
LockGuard
lock
(
mainloop
);
auto
result
=
std
::
chrono
::
steady_clock
::
duration
::
zero
();
if
(
pa
use
&&
pa
_stream_is_corked
(
stream
)
&&
if
(
pa_stream_is_corked
(
stream
)
&&
pa_stream_get_state
(
stream
)
==
PA_STREAM_READY
)
/* idle while paused */
result
=
std
::
chrono
::
seconds
(
1
);
...
...
@@ -796,8 +783,6 @@ PulseOutput::Play(const void *chunk, size_t size)
Pulse
::
LockGuard
lock
(
mainloop
);
pause
=
false
;
/* check if the stream is (already) connected */
WaitStream
();
...
...
@@ -841,6 +826,25 @@ PulseOutput::Play(const void *chunk, size_t size)
}
void
PulseOutput
::
Drain
()
{
Pulse
::
LockGuard
lock
(
mainloop
);
if
(
pa_stream_get_state
(
stream
)
!=
PA_STREAM_READY
||
pa_stream_is_suspended
(
stream
)
||
pa_stream_is_corked
(
stream
))
return
;
pa_operation
*
o
=
pa_stream_drain
(
stream
,
pulse_output_stream_success_cb
,
this
);
if
(
o
==
nullptr
)
throw
MakePulseError
(
context
,
"pa_stream_drain() failed"
);
pulse_wait_for_operation
(
mainloop
,
o
);
}
void
PulseOutput
::
Cancel
()
noexcept
{
assert
(
mainloop
!=
nullptr
);
...
...
@@ -876,7 +880,6 @@ PulseOutput::Pause()
Pulse
::
LockGuard
lock
(
mainloop
);
pause
=
true
;
interrupted
=
false
;
/* check if the stream is (already/still) connected */
...
...
src/output/plugins/WasapiOutputPlugin.cxx
View file @
ecc07e4e
...
...
@@ -24,6 +24,7 @@
#include "mixer/MixerList.hxx"
#include "thread/Cond.hxx"
#include "thread/Mutex.hxx"
#include "thread/Name.hxx"
#include "thread/Thread.hxx"
#include "util/AllocatedString.hxx"
#include "util/Domain.hxx"
...
...
@@ -231,6 +232,7 @@ IAudioClient *wasapi_output_get_client(WasapiOutput &output) noexcept {
}
void
WasapiOutputThread
::
Work
()
noexcept
{
SetThreadName
(
"Wasapi Output Worker"
);
FormatDebug
(
wasapi_output_domain
,
"Working thread started"
);
try
{
com
.
emplace
();
...
...
src/protocol/ArgParser.cxx
View file @
ecc07e4e
...
...
@@ -94,7 +94,7 @@ ParseCommandArgRange(const char *s)
s
);
if
(
test
==
test2
)
value
=
std
::
numeric_limits
<
int
>::
max
(
);
return
RangeArg
::
OpenEnded
(
range
.
start
);
if
(
value
<
0
)
throw
FormatProtocolError
(
ACK_ERROR_ARG
,
...
...
@@ -107,9 +107,13 @@ ParseCommandArgRange(const char *s)
range
.
end
=
(
unsigned
)
value
;
}
else
{
r
ange
.
end
=
(
unsigned
)
value
+
1
;
r
eturn
RangeArg
::
Single
(
range
.
start
)
;
}
if
(
!
range
.
IsWellFormed
())
throw
FormatProtocolError
(
ACK_ERROR_ARG
,
"Malformed range: %s"
,
s
);
return
range
;
}
...
...
src/protocol/RangeArg.hxx
View file @
ecc07e4e
...
...
@@ -25,8 +25,22 @@
struct
RangeArg
{
unsigned
start
,
end
;
static
constexpr
RangeArg
All
()
{
return
{
0
,
std
::
numeric_limits
<
unsigned
>::
max
()
};
/**
* Construct an open-ended range starting at the given index.
*/
static
constexpr
RangeArg
OpenEnded
(
unsigned
start
)
noexcept
{
return
{
start
,
std
::
numeric_limits
<
unsigned
>::
max
()
};
}
static
constexpr
RangeArg
All
()
noexcept
{
return
OpenEnded
(
0
);
}
/**
* Construct an instance describing exactly one index.
*/
static
constexpr
RangeArg
Single
(
unsigned
i
)
noexcept
{
return
{
i
,
i
+
1
};
}
constexpr
bool
operator
==
(
RangeArg
other
)
const
noexcept
{
...
...
@@ -37,13 +51,45 @@ struct RangeArg {
return
!
(
*
this
==
other
);
}
constexpr
bool
IsOpenEnded
()
const
noexcept
{
return
end
==
All
().
end
;
}
constexpr
bool
IsAll
()
const
noexcept
{
return
*
this
==
All
();
}
constexpr
bool
IsWellFormed
()
const
noexcept
{
return
start
<=
end
;
}
/**
* Is this range empty? A malformed range also counts as
* "empty" for this method.
*/
constexpr
bool
IsEmpty
()
const
noexcept
{
return
start
>=
end
;
}
/**
* Check if the range contains at least this number of items.
* Unlike Count(), this allows the object to be malformed.
*/
constexpr
bool
HasAtLeast
(
unsigned
n
)
const
noexcept
{
return
start
+
n
<=
end
;
}
constexpr
bool
Contains
(
unsigned
i
)
const
noexcept
{
return
i
>=
start
&&
i
<
end
;
}
/**
* Count the number of items covered by this range. This requires the
* object to be well-formed.
*/
constexpr
unsigned
Count
()
const
noexcept
{
return
end
-
start
;
}
};
#endif
src/song/LightSong.hxx
View file @
ecc07e4e
...
...
@@ -88,6 +88,19 @@ struct LightSong {
LightSong
(
const
char
*
_uri
,
const
Tag
&
_tag
)
noexcept
:
uri
(
_uri
),
tag
(
_tag
)
{}
/**
* A copy constructor which copies all fields, but only sets
* the tag to a caller-provided reference. This is used by
* the #ExportedSong move constructor.
*/
LightSong
(
const
LightSong
&
src
,
const
Tag
&
_tag
)
noexcept
:
directory
(
src
.
directory
),
uri
(
src
.
uri
),
real_uri
(
src
.
real_uri
),
tag
(
_tag
),
mtime
(
src
.
mtime
),
start_time
(
src
.
start_time
),
end_time
(
src
.
end_time
),
audio_format
(
src
.
audio_format
)
{}
gcc_pure
std
::
string
GetURI
()
const
noexcept
{
if
(
directory
==
nullptr
)
...
...
src/win32/ComPtr.hxx
View file @
ecc07e4e
...
...
@@ -112,6 +112,6 @@ template <typename T>
void
swap
(
ComPtr
<
T
>
&
lhs
,
ComPtr
<
T
>
&
rhs
)
noexcept
{
lhs
.
swap
(
rhs
);
}
}
}
// namespace std
#endif
src/win32/HResult.hxx
View file @
ecc07e4e
...
...
@@ -59,6 +59,7 @@ case x:
C
(
E_INVALIDARG
);
C
(
E_OUTOFMEMORY
);
C
(
E_POINTER
);
C
(
NO_ERROR
);
#undef C
}
return
std
::
string_view
();
...
...
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