release v0.21.24
-----BEGIN PGP SIGNATURE----- iQJEBAABCgAuFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAl7hRzQQHG1heEBtdXNp Y3BkLm9yZwAKCRAjbopYxttFEp7dD/483fkBEyipufQyQT9nntP8R/vqKlUT+M9V 8LyoJBtNtbNkO4bdrgAQCzElYzkDnd8VR++ZDEcqSEF49y5wafsiuufJNW2/s02Y ygAqgTCpcuS58F7aK92CW99bhZcKC6zoQovkenSMaZ39gorE1ZuO1JyrFR1LWOat ELekougQe0JbX2YX0YOH0Qags5fv9joxYJYsx8ZC60sCRNc+h8CBQjpyhZqzk7wC EPviLeMDw5lXkoSI3C045QmwJRFG8GMEyZ/4E/mnibxoTXBJmsm4ArKrfJznrUUs r8Mkf4G7sVqbsRMyMFBpzw+lsRDpVWI26mhdah9Y1zuUYPaEMe7OVKuEsASJQ/oK 33wRSBVZc7EPhV3m8f7U8NAJI0/XaaPKGgP2OrtnOfxD+OyAze4vNLZ/GJCYSsh+ wN1grmJw1mTP52xBicN2AITqXSVVpuvznn+p0g9MBB9Nw8/vbeWaqGPQhMHGHW6a JIL9yUTWwhkvkhav1bT7zKaeZv3qfgO7fjkgJqQFYt/q4FZwPFHJme55mVGq9d1y FNR8BMh+0A8hRhhQVwVycLxr4+NJja3vaqx+uVG2kov1g3eQBSgnEYCiEV7uls4V Pr4sIEeU/QQ+0jsMoJCaW65bNm4tOGKibpjSHrwJ+gxwKn3N7sJaAOo7PgGsUZyS 30cBC5zkjw== =XHev -----END PGP SIGNATURE----- Merge tag 'v0.21.24' release v0.21.24
This commit is contained in:
commit
c6a7f6dabc
9
NEWS
9
NEWS
|
@ -40,7 +40,7 @@ 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.24 (not yet released)
|
ver 0.21.24 (2020/06/10)
|
||||||
* protocol
|
* protocol
|
||||||
- "tagtypes" requires no permissions
|
- "tagtypes" requires no permissions
|
||||||
* database
|
* database
|
||||||
|
@ -49,11 +49,14 @@ ver 0.21.24 (not yet released)
|
||||||
- modplug: fix Windows build failure
|
- modplug: fix Windows build failure
|
||||||
- wildmidi: attempt to detect WildMidi using pkg-config
|
- wildmidi: attempt to detect WildMidi using pkg-config
|
||||||
- wildmidi: fix Windows build failure
|
- wildmidi: fix Windows build failure
|
||||||
|
* player
|
||||||
|
- don't restart current song if seeking beyond end
|
||||||
* Android
|
* Android
|
||||||
- enable the decoder plugins ModPlug and WildMidi
|
- enable the decoder plugins GME, ModPlug and WildMidi
|
||||||
- fix build failure with Android NDK r21
|
- fix build failure with Android NDK r21
|
||||||
* Windows
|
* Windows
|
||||||
- enable the decoder plugins ModPlug and WildMidi
|
- fix stream playback
|
||||||
|
- enable the decoder plugins GME, ModPlug and WildMidi
|
||||||
- work around Meson bug breaking the Windows build with GCC 10
|
- work around Meson bug breaking the Windows build with GCC 10
|
||||||
* fix unit test failure
|
* fix unit test failure
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,7 @@ thirdparty_libs = [
|
||||||
libid3tag,
|
libid3tag,
|
||||||
libmodplug,
|
libmodplug,
|
||||||
wildmidi,
|
wildmidi,
|
||||||
|
gme,
|
||||||
ffmpeg,
|
ffmpeg,
|
||||||
curl,
|
curl,
|
||||||
libexpat,
|
libexpat,
|
||||||
|
|
|
@ -485,7 +485,8 @@ Querying :program:`MPD`'s status
|
||||||
- ``songs``: number of songs
|
- ``songs``: number of songs
|
||||||
- ``uptime``: daemon uptime in seconds
|
- ``uptime``: daemon uptime in seconds
|
||||||
- ``db_playtime``: sum of all song times in the database in seconds
|
- ``db_playtime``: sum of all song times in the database in seconds
|
||||||
- ``db_update``: last db update in UNIX time
|
- ``db_update``: last db update in UNIX time (seconds since
|
||||||
|
1970-01-01 UTC)
|
||||||
- ``playtime``: time length of music played
|
- ``playtime``: time length of music played
|
||||||
|
|
||||||
Playback options
|
Playback options
|
||||||
|
|
|
@ -135,6 +135,18 @@ wildmidi = CmakeProject(
|
||||||
version='0.4.3',
|
version='0.4.3',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gme = CmakeProject(
|
||||||
|
'https://bitbucket.org/mpyne/game-music-emu/downloads/game-music-emu-0.6.3.tar.xz',
|
||||||
|
'aba34e53ef0ec6a34b58b84e28bf8cfbccee6585cebca25333604c35db3e051d',
|
||||||
|
'lib/libgme.a',
|
||||||
|
[
|
||||||
|
'-DBUILD_SHARED_LIBS=OFF',
|
||||||
|
'-DENABLE_UBSAN=OFF',
|
||||||
|
'-DZLIB_INCLUDE_DIR=OFF',
|
||||||
|
'-DSDL2_DIR=OFF',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-4.2.3.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-4.2.3.tar.xz',
|
||||||
'9df6c90aed1337634c1fb026fb01c154c29c82a64ea71291ff2da9aacb9aad31',
|
'9df6c90aed1337634c1fb026fb01c154c29c82a64ea71291ff2da9aacb9aad31',
|
||||||
|
|
|
@ -38,15 +38,19 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
DecoderBridge::DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
|
DecoderBridge::DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
|
||||||
|
bool _initial_seek_essential,
|
||||||
std::unique_ptr<Tag> _tag) noexcept
|
std::unique_ptr<Tag> _tag) noexcept
|
||||||
:dc(_dc),
|
:dc(_dc),
|
||||||
initial_seek_pending(_initial_seek_pending),
|
initial_seek_pending(_initial_seek_pending),
|
||||||
|
initial_seek_essential(_initial_seek_essential),
|
||||||
song_tag(std::move(_tag)) {}
|
song_tag(std::move(_tag)) {}
|
||||||
|
|
||||||
|
|
||||||
DecoderBridge::~DecoderBridge() noexcept
|
DecoderBridge::~DecoderBridge() noexcept
|
||||||
{
|
{
|
||||||
/* caller must flush the chunk */
|
/* caller must flush the chunk */
|
||||||
|
@ -364,6 +368,10 @@ DecoderBridge::SeekError() noexcept
|
||||||
/* d'oh, we can't seek to the sub-song start position,
|
/* d'oh, we can't seek to the sub-song start position,
|
||||||
what now? - no idea, ignoring the problem for now. */
|
what now? - no idea, ignoring the problem for now. */
|
||||||
initial_seek_running = false;
|
initial_seek_running = false;
|
||||||
|
|
||||||
|
if (initial_seek_essential)
|
||||||
|
error = std::make_exception_ptr(std::runtime_error("Decoder failed to seek"));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,11 @@ private:
|
||||||
*/
|
*/
|
||||||
bool initial_seek_pending;
|
bool initial_seek_pending;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are initial seek failures fatal?
|
||||||
|
*/
|
||||||
|
const bool initial_seek_essential;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the initial seek currently running? During this time,
|
* Is the initial seek currently running? During this time,
|
||||||
* the decoder command is SEEK. This flag is set by
|
* the decoder command is SEEK. This flag is set by
|
||||||
|
@ -112,6 +117,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
|
DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
|
||||||
|
bool _initial_seek_essential,
|
||||||
std::unique_ptr<Tag> _tag) noexcept;
|
std::unique_ptr<Tag> _tag) noexcept;
|
||||||
|
|
||||||
~DecoderBridge() noexcept;
|
~DecoderBridge() noexcept;
|
||||||
|
|
|
@ -80,6 +80,7 @@ void
|
||||||
DecoderControl::Start(std::unique_lock<Mutex> &lock,
|
DecoderControl::Start(std::unique_lock<Mutex> &lock,
|
||||||
std::unique_ptr<DetachedSong> _song,
|
std::unique_ptr<DetachedSong> _song,
|
||||||
SongTime _start_time, SongTime _end_time,
|
SongTime _start_time, SongTime _end_time,
|
||||||
|
bool _initial_seek_essential,
|
||||||
MusicBuffer &_buffer,
|
MusicBuffer &_buffer,
|
||||||
std::shared_ptr<MusicPipe> _pipe) noexcept
|
std::shared_ptr<MusicPipe> _pipe) noexcept
|
||||||
{
|
{
|
||||||
|
@ -89,6 +90,7 @@ DecoderControl::Start(std::unique_lock<Mutex> &lock,
|
||||||
song = std::move(_song);
|
song = std::move(_song);
|
||||||
start_time = _start_time;
|
start_time = _start_time;
|
||||||
end_time = _end_time;
|
end_time = _end_time;
|
||||||
|
initial_seek_essential = _initial_seek_essential;
|
||||||
buffer = &_buffer;
|
buffer = &_buffer;
|
||||||
pipe = std::move(_pipe);
|
pipe = std::move(_pipe);
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,12 @@ private:
|
||||||
public:
|
public:
|
||||||
bool seek_error;
|
bool seek_error;
|
||||||
bool seekable;
|
bool seekable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DecoderBridge::initial_seek_essential
|
||||||
|
*/
|
||||||
|
bool initial_seek_essential;
|
||||||
|
|
||||||
SongTime seek_time;
|
SongTime seek_time;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -383,12 +389,15 @@ public:
|
||||||
* owned and freed by the decoder
|
* owned and freed by the decoder
|
||||||
* @param start_time see #DecoderControl
|
* @param start_time see #DecoderControl
|
||||||
* @param end_time see #DecoderControl
|
* @param end_time see #DecoderControl
|
||||||
|
* @param initial_seek_essential see
|
||||||
|
* #DecoderBridge::initial_seek_essential
|
||||||
* @param pipe the pipe which receives the decoded chunks (owned by
|
* @param pipe the pipe which receives the decoded chunks (owned by
|
||||||
* the caller)
|
* the caller)
|
||||||
*/
|
*/
|
||||||
void Start(std::unique_lock<Mutex> &lock,
|
void Start(std::unique_lock<Mutex> &lock,
|
||||||
std::unique_ptr<DetachedSong> song,
|
std::unique_ptr<DetachedSong> song,
|
||||||
SongTime start_time, SongTime end_time,
|
SongTime start_time, SongTime end_time,
|
||||||
|
bool initial_seek_essential,
|
||||||
MusicBuffer &buffer,
|
MusicBuffer &buffer,
|
||||||
std::shared_ptr<MusicPipe> pipe) noexcept;
|
std::shared_ptr<MusicPipe> pipe) noexcept;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
#include <forward_list>
|
#include <forward_list> // IWYU pragma: export
|
||||||
|
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class InputStream;
|
class InputStream;
|
||||||
|
|
|
@ -422,6 +422,7 @@ decoder_run_song(DecoderControl &dc,
|
||||||
dc.start_time = dc.seek_time;
|
dc.start_time = dc.seek_time;
|
||||||
|
|
||||||
DecoderBridge bridge(dc, dc.start_time.IsPositive(),
|
DecoderBridge bridge(dc, dc.start_time.IsPositive(),
|
||||||
|
dc.initial_seek_essential,
|
||||||
/* pass the song tag only if it's
|
/* pass the song tag only if it's
|
||||||
authoritative, i.e. if it's a local
|
authoritative, i.e. if it's a local
|
||||||
file - tags on "stream" songs are just
|
file - tags on "stream" songs are just
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
|
#include "fs/NarrowPath.hxx"
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
#include "util/StringFormat.hxx"
|
#include "util/StringFormat.hxx"
|
||||||
#include "util/StringView.hxx"
|
#include "util/StringView.hxx"
|
||||||
#include "util/UriExtract.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define SUBTUNE_PREFIX "tune_"
|
#define SUBTUNE_PREFIX "tune_"
|
||||||
|
|
||||||
|
@ -83,11 +82,10 @@ gcc_pure
|
||||||
static unsigned
|
static unsigned
|
||||||
ParseSubtuneName(const char *base) noexcept
|
ParseSubtuneName(const char *base) noexcept
|
||||||
{
|
{
|
||||||
if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
|
base = StringAfterPrefix(base, SUBTUNE_PREFIX);
|
||||||
|
if (base == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
base += sizeof(SUBTUNE_PREFIX) - 1;
|
|
||||||
|
|
||||||
char *endptr;
|
char *endptr;
|
||||||
auto track = strtoul(base, &endptr, 10);
|
auto track = strtoul(base, &endptr, 10);
|
||||||
if (endptr == base || *endptr != '.')
|
if (endptr == base || *endptr != '.')
|
||||||
|
@ -106,41 +104,46 @@ ParseContainerPath(Path path_fs)
|
||||||
const Path base = path_fs.GetBase();
|
const Path base = path_fs.GetBase();
|
||||||
unsigned track;
|
unsigned track;
|
||||||
if (base.IsNull() ||
|
if (base.IsNull() ||
|
||||||
(track = ParseSubtuneName(base.c_str())) < 1)
|
(track = ParseSubtuneName(NarrowPath(base))) < 1)
|
||||||
return { AllocatedPath(path_fs), 0 };
|
return { AllocatedPath(path_fs), 0 };
|
||||||
|
|
||||||
return { path_fs.GetDirectoryName(), track - 1 };
|
return { path_fs.GetDirectoryName(), track - 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AllocatedPath
|
||||||
|
ReplaceSuffix(Path src,
|
||||||
|
const PathTraitsFS::const_pointer new_suffix) noexcept
|
||||||
|
{
|
||||||
|
const auto *old_suffix = src.GetSuffix();
|
||||||
|
if (old_suffix == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PathTraitsFS::string s(src.c_str(), old_suffix);
|
||||||
|
s += new_suffix;
|
||||||
|
return AllocatedPath::FromFS(std::move(s));
|
||||||
|
}
|
||||||
|
|
||||||
static Music_Emu*
|
static Music_Emu*
|
||||||
LoadGmeAndM3u(const GmeContainerPath& container) {
|
LoadGmeAndM3u(const GmeContainerPath& container) {
|
||||||
|
|
||||||
const char *path = container.path.c_str();
|
|
||||||
const char *suffix = uri_get_suffix(path);
|
|
||||||
|
|
||||||
Music_Emu *emu;
|
Music_Emu *emu;
|
||||||
const char *gme_err =
|
const char *gme_err =
|
||||||
gme_open_file(path, &emu, GME_SAMPLE_RATE);
|
gme_open_file(NarrowPath(container.path), &emu, GME_SAMPLE_RATE);
|
||||||
if (gme_err != nullptr) {
|
if (gme_err != nullptr) {
|
||||||
LogWarning(gme_domain, gme_err);
|
LogWarning(gme_domain, gme_err);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(suffix == nullptr) {
|
const auto m3u_path = ReplaceSuffix(container.path,
|
||||||
return emu;
|
PATH_LITERAL("m3u"));
|
||||||
}
|
|
||||||
|
|
||||||
std::string m3u_path(path,suffix);
|
|
||||||
m3u_path += "m3u";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some GME formats lose metadata if you attempt to
|
* Some GME formats lose metadata if you attempt to
|
||||||
* load a non-existant M3U file, so check that one
|
* load a non-existant M3U file, so check that one
|
||||||
* exists before loading.
|
* exists before loading.
|
||||||
*/
|
*/
|
||||||
if(FileExists(Path::FromFS(m3u_path.c_str()))) {
|
if (!m3u_path.IsNull() && FileExists(m3u_path))
|
||||||
gme_load_m3u(emu,m3u_path.c_str());
|
gme_load_m3u(emu, NarrowPath(m3u_path));
|
||||||
}
|
|
||||||
return emu;
|
return emu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +323,7 @@ gme_container_scan(Path path_fs)
|
||||||
if (num_songs < 2)
|
if (num_songs < 2)
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
|
const auto *subtune_suffix = path_fs.GetSuffix();
|
||||||
|
|
||||||
TagBuilder tag_builder;
|
TagBuilder tag_builder;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ CurlRequest::CurlRequest(CurlGlobal &_global,
|
||||||
easy.SetUserAgent("Music Player Daemon " VERSION);
|
easy.SetUserAgent("Music Player Daemon " VERSION);
|
||||||
easy.SetHeaderFunction(_HeaderFunction, this);
|
easy.SetHeaderFunction(_HeaderFunction, this);
|
||||||
easy.SetWriteFunction(WriteFunction, this);
|
easy.SetWriteFunction(WriteFunction, this);
|
||||||
#ifndef ANDROID
|
#if !defined(ANDROID) && !defined(_WIN32)
|
||||||
easy.SetOption(CURLOPT_NETRC, 1L);
|
easy.SetOption(CURLOPT_NETRC, 1L);
|
||||||
#endif
|
#endif
|
||||||
easy.SetErrorBuffer(error_buffer);
|
easy.SetErrorBuffer(error_buffer);
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#ifndef MPD_AUDIO_FORMAT_HXX
|
#ifndef MPD_AUDIO_FORMAT_HXX
|
||||||
#define MPD_AUDIO_FORMAT_HXX
|
#define MPD_AUDIO_FORMAT_HXX
|
||||||
|
|
||||||
#include "pcm/SampleFormat.hxx"
|
#include "pcm/SampleFormat.hxx" // IWYU pragma: export
|
||||||
#include "pcm/ChannelDefs.hxx"
|
#include "pcm/ChannelDefs.hxx" // IWYU pragma: export
|
||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
|
@ -224,7 +224,8 @@ private:
|
||||||
* Caller must lock the mutex.
|
* Caller must lock the mutex.
|
||||||
*/
|
*/
|
||||||
void StartDecoder(std::unique_lock<Mutex> &lock,
|
void StartDecoder(std::unique_lock<Mutex> &lock,
|
||||||
std::shared_ptr<MusicPipe> pipe) noexcept;
|
std::shared_ptr<MusicPipe> pipe,
|
||||||
|
bool initial_seek_essential) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The decoder has acknowledged the "START" command (see
|
* The decoder has acknowledged the "START" command (see
|
||||||
|
@ -367,7 +368,8 @@ public:
|
||||||
|
|
||||||
void
|
void
|
||||||
Player::StartDecoder(std::unique_lock<Mutex> &lock,
|
Player::StartDecoder(std::unique_lock<Mutex> &lock,
|
||||||
std::shared_ptr<MusicPipe> _pipe) noexcept
|
std::shared_ptr<MusicPipe> _pipe,
|
||||||
|
bool initial_seek_essential) noexcept
|
||||||
{
|
{
|
||||||
assert(queued || pc.command == PlayerCommand::SEEK);
|
assert(queued || pc.command == PlayerCommand::SEEK);
|
||||||
assert(pc.next_song != nullptr);
|
assert(pc.next_song != nullptr);
|
||||||
|
@ -379,6 +381,7 @@ Player::StartDecoder(std::unique_lock<Mutex> &lock,
|
||||||
|
|
||||||
dc.Start(lock, std::make_unique<DetachedSong>(*pc.next_song),
|
dc.Start(lock, std::make_unique<DetachedSong>(*pc.next_song),
|
||||||
start_time, pc.next_song->GetEndTime(),
|
start_time, pc.next_song->GetEndTime(),
|
||||||
|
initial_seek_essential,
|
||||||
buffer, std::move(_pipe));
|
buffer, std::move(_pipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +639,7 @@ Player::SeekDecoder(std::unique_lock<Mutex> &lock) noexcept
|
||||||
pipe->Clear();
|
pipe->Clear();
|
||||||
|
|
||||||
/* re-start the decoder */
|
/* re-start the decoder */
|
||||||
StartDecoder(lock, pipe);
|
StartDecoder(lock, pipe, true);
|
||||||
ActivateDecoder();
|
ActivateDecoder();
|
||||||
|
|
||||||
pc.seeking = true;
|
pc.seeking = true;
|
||||||
|
@ -714,7 +717,8 @@ Player::ProcessCommand(std::unique_lock<Mutex> &lock) noexcept
|
||||||
pc.CommandFinished();
|
pc.CommandFinished();
|
||||||
|
|
||||||
if (dc.IsIdle())
|
if (dc.IsIdle())
|
||||||
StartDecoder(lock, std::make_shared<MusicPipe>());
|
StartDecoder(lock, std::make_shared<MusicPipe>(),
|
||||||
|
false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -985,7 +989,7 @@ Player::Run() noexcept
|
||||||
|
|
||||||
std::unique_lock<Mutex> lock(pc.mutex);
|
std::unique_lock<Mutex> lock(pc.mutex);
|
||||||
|
|
||||||
StartDecoder(lock, pipe);
|
StartDecoder(lock, pipe, true);
|
||||||
ActivateDecoder();
|
ActivateDecoder();
|
||||||
|
|
||||||
pc.state = PlayerState::PLAY;
|
pc.state = PlayerState::PLAY;
|
||||||
|
@ -1025,7 +1029,8 @@ Player::Run() noexcept
|
||||||
|
|
||||||
assert(dc.pipe == nullptr || dc.pipe == pipe);
|
assert(dc.pipe == nullptr || dc.pipe == pipe);
|
||||||
|
|
||||||
StartDecoder(lock, std::make_shared<MusicPipe>());
|
StartDecoder(lock, std::make_shared<MusicPipe>(),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/* no cross-fading if MPD is going to pause at the
|
if (/* no cross-fading if MPD is going to pause at the
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#ifndef STRING_FORMAT_HXX
|
#ifndef STRING_FORMAT_HXX
|
||||||
#define STRING_FORMAT_HXX
|
#define STRING_FORMAT_HXX
|
||||||
|
|
||||||
#include "StringBuffer.hxx"
|
#include "StringBuffer.hxx" // IWYU pragma: export
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ thirdparty_libs = [
|
||||||
liblame,
|
liblame,
|
||||||
libmodplug,
|
libmodplug,
|
||||||
wildmidi,
|
wildmidi,
|
||||||
|
gme,
|
||||||
ffmpeg,
|
ffmpeg,
|
||||||
curl,
|
curl,
|
||||||
libexpat,
|
libexpat,
|
||||||
|
|
Loading…
Reference in New Issue