Merge remote-tracking branches 'neheb/patch-2', 'neheb/con', 'neheb/cons', 'neheb/guruhg', 'neheb/r12R3', 'neheb/fefgheh' and 'neheb/rhgerg3453'

This commit is contained in:
Max Kellermann 2020-02-05 19:36:01 +01:00
63 changed files with 230 additions and 121 deletions

6
NEWS
View File

@ -35,6 +35,12 @@ ver 0.22 (not yet released)
* switch to C++17
- GCC 7 or clang 4 (or newer) recommended
ver 0.21.20 (not yet released)
* decoder
- audiofile, ffmpeg, sndfile: handle MIME type "audio/wav"
- ffmpeg: fix playback of AIFF and TTA
- vorbis, opus: fix seeking in small files
ver 0.21.19 (2020/01/17)
* configuration
- allow overriding top-level settings in includes

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.musicpd"
android:installLocation="auto"
android:versionCode="42"
android:versionName="0.21.19">
android:versionCode="43"
android:versionName="0.21.20">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>

View File

@ -297,7 +297,7 @@ public:
explicit ConfigLoader(ConfigData &_config) noexcept
:config(_config) {}
bool TryFile(const Path path);
bool TryFile(Path path);
bool TryFile(const AllocatedPath &base_path, Path path);
};

View File

@ -91,7 +91,7 @@ class ZzipInputStream final : public InputStream {
ZZIP_FILE *const file;
public:
ZzipInputStream(const std::shared_ptr<ZzipDir> _dir, const char *_uri,
ZzipInputStream(const std::shared_ptr<ZzipDir>& _dir, const char *_uri,
Mutex &_mutex,
ZZIP_FILE *_file)
:InputStream(_uri, _mutex),

View File

@ -82,7 +82,7 @@ ToAck(DatabaseErrorCode code) noexcept
gcc_pure
static enum ack
ToAck(std::exception_ptr ep) noexcept
ToAck(const std::exception_ptr& ep) noexcept
{
try {
std::rethrow_exception(ep);
@ -113,7 +113,7 @@ ToAck(std::exception_ptr ep) noexcept
}
void
PrintError(Response &r, std::exception_ptr ep)
PrintError(Response &r, const std::exception_ptr& ep)
{
LogError(ep);
r.Error(ToAck(ep), GetFullMessage(ep).c_str());

View File

@ -28,6 +28,6 @@ class Response;
* Send the exception to the client.
*/
void
PrintError(Response &r, std::exception_ptr ep);
PrintError(Response &r, const std::exception_ptr& ep);
#endif

View File

@ -174,7 +174,7 @@ handle_status(Client &client, gcc_unused Request args, Response &r)
COMMAND_STATUS_BITRATE ": %u\n",
player_status.elapsed_time.RoundS(),
player_status.total_time.IsNegative()
? 0u
? 0U
: unsigned(player_status.total_time.RoundS()),
player_status.elapsed_time.ToDoubleS(),
player_status.bit_rate);

View File

@ -50,7 +50,7 @@ template<typename T>
static auto
Append(std::forward_list<T> &list, T &&src)
{
return list.emplace_after(FindLast(list), std::move(src));
return list.emplace_after(FindLast(list), std::forward<T>(src));
}
void

View File

@ -39,7 +39,6 @@ search_add_to_playlist(const Database &db, const Storage *storage,
const DatabaseSelection &selection)
{
using namespace std::placeholders;
const auto f = std::bind(AddSong, storage,
playlist_path_utf8, _1);
const auto f = [=](auto && arg1) { return AddSong(storage, playlist_path_utf8, arg1); };
db.Visit(selection, f);
}

View File

@ -50,8 +50,9 @@
#include <mpd/async.h>
#include <cassert>
#include <string>
#include <list>
#include <string>
#include <utility>
class LibmpdclientError final : public std::runtime_error {
enum mpd_error code;
@ -447,7 +448,7 @@ ProxyDatabase::ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener,
listener(_listener),
host(block.GetBlockValue("host", "")),
password(block.GetBlockValue("password", "")),
port(block.GetBlockValue("port", 0u)),
port(block.GetBlockValue("port", 0U)),
keepalive(block.GetBlockValue("keepalive", false))
{
}
@ -516,7 +517,7 @@ ProxyDatabase::Connect()
(void)keepalive;
#endif
idle_received = ~0u;
idle_received = ~0U;
is_idle = false;
SocketMonitor::Open(SocketDescriptor(mpd_async_get_fd(mpd_connection_get_async(connection))));
@ -674,15 +675,15 @@ ProxyDatabase::ReturnSong(const LightSong *_song) const noexcept
static void
Visit(struct mpd_connection *connection, const char *uri,
bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist);
const VisitDirectory& visit_directory, const VisitSong& visit_song,
const VisitPlaylist& visit_playlist);
static void
Visit(struct mpd_connection *connection,
bool recursive, const SongFilter *filter,
const struct mpd_directory *directory,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist)
const VisitDirectory& visit_directory, const VisitSong& visit_song,
const VisitPlaylist& visit_playlist)
{
const char *path = mpd_directory_get_path(directory);
@ -697,7 +698,7 @@ Visit(struct mpd_connection *connection,
if (recursive)
Visit(connection, path, recursive, filter,
visit_directory, visit_song, visit_playlist);
visit_directory, std::move(visit_song), std::move(visit_playlist));
}
gcc_pure
@ -710,7 +711,7 @@ Match(const SongFilter *filter, const LightSong &song) noexcept
static void
Visit(const SongFilter *filter,
const mpd_song *_song,
VisitSong visit_song)
const VisitSong& visit_song)
{
if (!visit_song)
return;
@ -722,7 +723,7 @@ Visit(const SongFilter *filter,
static void
Visit(const struct mpd_playlist *playlist,
VisitPlaylist visit_playlist)
const VisitPlaylist& visit_playlist)
{
if (!visit_playlist)
return;
@ -778,8 +779,8 @@ ReceiveEntities(struct mpd_connection *connection) noexcept
static void
Visit(struct mpd_connection *connection, const char *uri,
bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist)
const VisitDirectory& visit_directory, const VisitSong& visit_song,
const VisitPlaylist& visit_playlist)
{
if (!mpd_send_list_meta(connection, uri))
ThrowError(connection);
@ -813,7 +814,7 @@ Visit(struct mpd_connection *connection, const char *uri,
static void
SearchSongs(struct mpd_connection *connection,
const DatabaseSelection &selection,
VisitSong visit_song)
const VisitSong& visit_song)
try {
assert(selection.recursive);
assert(visit_song);

View File

@ -220,8 +220,8 @@ Directory::Sort() noexcept
void
Directory::Walk(bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist) const
const VisitDirectory& visit_directory, const VisitSong& visit_song,
const VisitPlaylist& visit_playlist) const
{
if (IsMount()) {
assert(IsEmpty());

View File

@ -284,8 +284,8 @@ public:
* Caller must lock #db_mutex.
*/
void Walk(bool recursive, const SongFilter *match,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist) const;
const VisitDirectory& visit_directory, const VisitSong& visit_song,
const VisitPlaylist& visit_playlist) const;
gcc_pure
LightDirectory Export() const noexcept;

View File

@ -41,6 +41,7 @@
#include "util/SplitString.hxx"
#include <string>
#include <utility>
#include <assert.h>
#include <string.h>
@ -107,9 +108,9 @@ private:
void VisitServer(const ContentDirectoryService &server,
std::forward_list<std::string> &&vpath,
const DatabaseSelection &selection,
VisitDirectory visit_directory,
VisitSong visit_song,
VisitPlaylist visit_playlist) const;
const VisitDirectory& visit_directory,
const VisitSong& visit_song,
const VisitPlaylist& visit_playlist) const;
/**
* Run an UPnP search according to MPD parameters, and
@ -118,7 +119,7 @@ private:
void SearchSongs(const ContentDirectoryService &server,
const char *objid,
const DatabaseSelection &selection,
VisitSong visit_song) const;
const VisitSong& visit_song) const;
UPnPDirContent SearchSongs(const ContentDirectoryService &server,
const char *objid,
@ -311,7 +312,7 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
static void
visitSong(const UPnPDirObject &meta, const char *path,
const DatabaseSelection &selection,
VisitSong visit_song)
const VisitSong& visit_song)
{
if (!visit_song)
return;
@ -339,7 +340,7 @@ void
UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
const char *objid,
const DatabaseSelection &selection,
VisitSong visit_song) const
const VisitSong& visit_song) const
{
if (!visit_song)
return;
@ -440,13 +441,13 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
static void
VisitItem(const UPnPDirObject &object, const char *uri,
const DatabaseSelection &selection,
VisitSong visit_song, VisitPlaylist visit_playlist)
const VisitSong& visit_song, const VisitPlaylist& visit_playlist)
{
assert(object.type == UPnPDirObject::Type::ITEM);
switch (object.item_class) {
case UPnPDirObject::ItemClass::MUSIC:
visitSong(object, uri, selection, visit_song);
visitSong(object, uri, selection, std::move(visit_song));
break;
case UPnPDirObject::ItemClass::PLAYLIST:
@ -469,9 +470,9 @@ VisitItem(const UPnPDirObject &object, const char *uri,
static void
VisitObject(const UPnPDirObject &object, const char *uri,
const DatabaseSelection &selection,
VisitDirectory visit_directory,
VisitSong visit_song,
VisitPlaylist visit_playlist)
const VisitDirectory& visit_directory,
const VisitSong& visit_song,
const VisitPlaylist& visit_playlist)
{
switch (object.type) {
case UPnPDirObject::Type::UNKNOWN:
@ -486,7 +487,7 @@ VisitObject(const UPnPDirObject &object, const char *uri,
case UPnPDirObject::Type::ITEM:
VisitItem(object, uri, selection,
visit_song, visit_playlist);
std::move(visit_song), std::move(visit_playlist));
break;
}
}
@ -497,9 +498,9 @@ void
UpnpDatabase::VisitServer(const ContentDirectoryService &server,
std::forward_list<std::string> &&vpath,
const DatabaseSelection &selection,
VisitDirectory visit_directory,
VisitSong visit_song,
VisitPlaylist visit_playlist) const
const VisitDirectory& visit_directory,
const VisitSong& visit_song,
const VisitPlaylist& visit_playlist) const
{
/* If the path begins with rootid, we know that this is a
song, not a directory (because that's how we set things

View File

@ -41,7 +41,7 @@ adplug_init(const ConfigBlock &block)
FormatDebug(adplug_domain, "adplug %s",
CAdPlug::get_version().c_str());
sample_rate = block.GetPositiveValue("sample_rate", 48000u);
sample_rate = block.GetPositiveValue("sample_rate", 48000U);
CheckSampleRate(sample_rate);
return true;

View File

@ -200,7 +200,7 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
AudioFileInputStream afis{&client, is};
AFvirtualfile *const vf = setup_virtual_fops(afis);
const AFfilehandle fh = afOpenVirtualFile(vf, "r", nullptr);
auto fh = afOpenVirtualFile(vf, "r", nullptr);
if (fh == AF_NULL_FILEHANDLE)
return;
@ -269,6 +269,8 @@ static const char *const audiofile_suffixes[] = {
};
static const char *const audiofile_mime_types[] = {
"audio/wav",
"audio/aiff",
"audio/x-wav",
"audio/x-aiff",
nullptr

View File

@ -150,6 +150,5 @@ dsdlib_tag_id3(InputStream &is, TagHandler &handler,
scan_id3_tag(id3_tag, handler);
id3_tag_delete(id3_tag);
return;
}
#endif

View File

@ -213,7 +213,6 @@ dsdiff_handle_native_tag(DecoderClient *client, InputStream &is,
return;
handler.OnTag(type, {label, length});
return;
}
/**

View File

@ -231,7 +231,7 @@ faad_song_duration(DecoderBuffer &buffer, InputStream &is)
static NeAACDecHandle
faad_decoder_new()
{
const NeAACDecHandle decoder = NeAACDecOpen();
auto decoder = NeAACDecOpen();
NeAACDecConfigurationPtr config =
NeAACDecGetCurrentConfiguration(decoder);
@ -324,7 +324,7 @@ faad_get_file_time(InputStream &is)
static void
faad_stream_decode(DecoderClient &client, InputStream &is,
DecoderBuffer &buffer, const NeAACDecHandle decoder)
DecoderBuffer &buffer, NeAACDecHandle decoder)
{
const auto total_time = faad_song_duration(buffer, is);
@ -406,7 +406,7 @@ faad_stream_decode(DecoderClient &client, InputStream &is)
/* create the libfaad decoder */
const NeAACDecHandle decoder = faad_decoder_new();
auto decoder = faad_decoder_new();
AtScopeExit(decoder) { NeAACDecClose(decoder); };
faad_stream_decode(client, is, buffer, decoder);

View File

@ -698,7 +698,7 @@ static const char *const ffmpeg_mime_types[] = {
"audio/aac",
"audio/aacp",
"audio/ac3",
"audio/aiff"
"audio/aiff",
"audio/amr",
"audio/basic",
"audio/flac",
@ -711,12 +711,13 @@ static const char *const ffmpeg_mime_types[] = {
"audio/qcelp",
"audio/vorbis",
"audio/vorbis+ogg",
"audio/wav",
"audio/x-8svx",
"audio/x-16sv",
"audio/x-aac",
"audio/x-ac3",
"audio/x-adx",
"audio/x-aiff"
"audio/x-aiff",
"audio/x-alaw",
"audio/x-au",
"audio/x-dca",
@ -736,7 +737,7 @@ static const char *const ffmpeg_mime_types[] = {
"audio/x-pn-realaudio",
"audio/x-pn-multirate-realaudio",
"audio/x-speex",
"audio/x-tta"
"audio/x-tta",
"audio/x-voc",
"audio/x-wav",
"audio/x-wma",

View File

@ -77,7 +77,7 @@ fluidsynth_mpd_log_function(int level,
static bool
fluidsynth_init(const ConfigBlock &block)
{
sample_rate = block.GetPositiveValue("sample_rate", 48000u);
sample_rate = block.GetPositiveValue("sample_rate", 48000U);
CheckSampleRate(sample_rate);
soundfont_path = block.GetBlockValue("soundfont",

View File

@ -186,7 +186,7 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
client.Ready(result.first, true, duration);
frame_size = result.first.GetFrameSize();
kbit_rate = frame_size * result.first.sample_rate /
(1024u / 8u);
(1024U / 8U);
total_frames = result.second / frame_size;
} catch (UnsupportedFile) {
/* not a Hybrid-DSD file; let the next decoder plugin
@ -236,7 +236,7 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
/* fill the buffer */
auto w = buffer.Write();
if (!w.empty()) {
if (remaining_bytes < (1<<30ull) &&
if (remaining_bytes < (1<<30ULL) &&
w.size > size_t(remaining_bytes))
w.size = remaining_bytes;

View File

@ -760,7 +760,7 @@ MadDecoder::DecodeFirstFrame(Tag *tag) noexcept
if (max_frames > 8 * 1024 * 1024) {
FormatWarning(mad_domain,
"mp3 file header indicates too many frames: %lu",
"mp3 file header indicates too many frames: %zu",
max_frames);
return false;
}

View File

@ -108,7 +108,7 @@ mikmod_decoder_init(const ConfigBlock &block)
static char params[] = "";
mikmod_loop = block.GetBlockValue("loop", false);
mikmod_sample_rate = block.GetPositiveValue("sample_rate", 44100u);
mikmod_sample_rate = block.GetPositiveValue("sample_rate", 44100U);
if (!audio_valid_sample_rate(mikmod_sample_rate))
throw FormatRuntimeError("Invalid sample rate in line %d: %u",
block.line, mikmod_sample_rate);

View File

@ -45,8 +45,12 @@ OggDecoder::LoadEndPacket(ogg_packet &packet) const
DecoderReader reader(client, input_stream);
OggSyncState sync2(reader);
OggStreamState stream2(GetSerialNo());
/* passing synced=false because we're inside an
OggVisitor callback, and our InputStream may be in
the middle of an Ogg packet */
result = OggSeekFindEOS(sync2, stream2, packet,
input_stream);
input_stream, false);
}
/* restore the previous file position */

View File

@ -127,7 +127,7 @@ SidplayGlobal::SidplayGlobal(const ConfigBlock &block)
if (!database_path.IsNull())
songlength_database = sidplay_load_songlength_db(database_path);
default_songlength = block.GetPositiveValue("default_songlength", 0u);
default_songlength = block.GetPositiveValue("default_songlength", 0U);
default_genre = block.GetBlockValue("default_genre", "");
@ -403,7 +403,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
const unsigned timebase = player.timebase();
#endif
const unsigned end = duration.IsNegative()
? 0u
? 0U
: duration.ToScale<uint64_t>(timebase);
DecoderCommand cmd;

View File

@ -323,6 +323,8 @@ static const char *const sndfile_suffixes[] = {
};
static const char *const sndfile_mime_types[] = {
"audio/wav",
"audio/aiff",
"audio/x-wav",
"audio/x-aiff",

View File

@ -93,7 +93,7 @@ public:
};
PreparedFlacEncoder::PreparedFlacEncoder(const ConfigBlock &block)
:compression(block.GetBlockValue("compression", 5u))
:compression(block.GetBlockValue("compression", 5U))
{
}

View File

@ -105,7 +105,7 @@ PreparedOpusEncoder::PreparedOpusEncoder(const ConfigBlock &block)
throw std::runtime_error("Invalid bit rate");
}
complexity = block.GetBlockValue("complexity", 10u);
complexity = block.GetBlockValue("complexity", 10U);
if (complexity > 10)
throw std::runtime_error("Invalid complexity");

View File

@ -30,11 +30,13 @@
#include <nfsc/libnfs-raw-nfs.h>
#endif
#include <utility>
bool
IsFileNotFound(std::exception_ptr ep) noexcept
{
try {
std::rethrow_exception(ep);
std::rethrow_exception(std::move(ep));
} catch (const std::system_error &e) {
return IsFileNotFound(e);
#ifdef ENABLE_CURL

View File

@ -112,7 +112,7 @@ input_cdio_init(EventLoop &, const ConfigBlock &block)
throw FormatRuntimeError("Unrecognized 'default_byte_order' setting: %s",
value);
}
speed = block.GetBlockValue("speed",0u);
speed = block.GetBlockValue("speed",0U);
}
struct CdioUri {

View File

@ -364,7 +364,7 @@ input_curl_init(EventLoop &event_loop, const ConfigBlock &block)
http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK");
proxy = block.GetBlockValue("proxy");
proxy_port = block.GetBlockValue("proxy_port", 0u);
proxy_port = block.GetBlockValue("proxy_port", 0U);
proxy_user = block.GetBlockValue("proxy_user");
proxy_password = block.GetBlockValue("proxy_password");
@ -409,9 +409,9 @@ CurlInputStream::InitEasy()
request = new CurlRequest(**curl_init, GetURI(), *this);
request->SetOption(CURLOPT_HTTP200ALIASES, http_200_aliases);
request->SetOption(CURLOPT_FOLLOWLOCATION, 1l);
request->SetOption(CURLOPT_MAXREDIRS, 5l);
request->SetOption(CURLOPT_FAILONERROR, 1l);
request->SetOption(CURLOPT_FOLLOWLOCATION, 1L);
request->SetOption(CURLOPT_MAXREDIRS, 5L);
request->SetOption(CURLOPT_FAILONERROR, 1L);
if (proxy != nullptr)
request->SetOption(CURLOPT_PROXY, proxy);
@ -424,8 +424,8 @@ CurlInputStream::InitEasy()
StringFormat<1024>("%s:%s", proxy_user,
proxy_password).c_str());
request->SetOption(CURLOPT_SSL_VERIFYPEER, verify_peer ? 1l : 0l);
request->SetOption(CURLOPT_SSL_VERIFYHOST, verify_host ? 2l : 0l);
request->SetOption(CURLOPT_SSL_VERIFYPEER, verify_peer ? 1L : 0L);
request->SetOption(CURLOPT_SSL_VERIFYHOST, verify_host ? 2L : 0L);
request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get());
}

View File

@ -65,7 +65,7 @@ public:
}
private:
void Failed(std::exception_ptr e) {
void Failed(const std::exception_ptr& e) {
SetInput(std::make_unique<FailingInputStream>(GetURI(), e,
mutex));
}

View File

@ -35,6 +35,7 @@
#include "Log.hxx"
#include <memory>
#include <utility>
static constexpr Domain tidal_domain("tidal");
@ -77,7 +78,7 @@ public:
}
private:
void Failed(std::exception_ptr e) {
void Failed(const std::exception_ptr& e) {
SetInput(std::make_unique<FailingInputStream>(GetURI(), e,
mutex));
}
@ -133,7 +134,7 @@ static bool
IsInvalidSession(std::exception_ptr e) noexcept
{
try {
std::rethrow_exception(e);
std::rethrow_exception(std::move(e));
} catch (const TidalError &te) {
return te.IsInvalidSession();
} catch (...) {

View File

@ -56,7 +56,7 @@ CurlRequest::CurlRequest(CurlGlobal &_global,
easy.SetUserAgent("Music Player Daemon " VERSION);
easy.SetHeaderFunction(_HeaderFunction, this);
easy.SetWriteFunction(WriteFunction, this);
easy.SetOption(CURLOPT_NETRC, 1l);
easy.SetOption(CURLOPT_NETRC, 1L);
easy.SetErrorBuffer(error_buffer);
easy.SetNoProgress();
easy.SetNoSignal();

View File

@ -167,7 +167,7 @@ ParseObjects(ODBus::ReadMessageIter &&i,
ForEachInterface(std::move(i), [&callback](const char *path, auto &&j){
Object o(path);
ParseObject(o, std::move(j));
ParseObject(o, std::forward<decltype(j)>(j));
if (o.IsValid())
callback(std::move(o));
});

View File

@ -58,7 +58,7 @@ try {
if (u.IsNull())
return AllocatedString<>::Duplicate(src);
AllocatedArray<UChar> folded(u.size() * 2u);
AllocatedArray<UChar> folded(u.size() * 2U);
UErrorCode error_code = U_ZERO_ERROR;
size_t folded_length = u_strFoldCase(folded.begin(), folded.size(),

View File

@ -37,7 +37,7 @@ ContentDirectoryService::ContentDirectoryService(const UPnPDevice &device,
m_modelName(device.modelName),
m_rdreqcnt(200)
{
if (!m_modelName.compare("MediaTomb")) {
if (m_modelName == "MediaTomb") {
// Readdir by 200 entries is good for most, but MediaTomb likes
// them really big. Actually 1000 is better but I don't dare
m_rdreqcnt = 500;

View File

@ -57,13 +57,14 @@ OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is,
bool
OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet,
InputStream &is)
InputStream &is, bool synced)
{
if (!is.KnownSize())
return false;
if (is.GetRest() < 65536)
return OggFindEOS(oy, os, packet);
return (synced || oy.ExpectPageSeekIn(os)) &&
OggFindEOS(oy, os, packet);
if (!is.CheapSeeking())
return false;

View File

@ -47,10 +47,13 @@ OggSeekPageAtOffset(OggSyncState &oy, ogg_stream_state &os, InputStream &is,
* Try to find the end-of-stream (EOS) packet. Seek to the end of the
* file if necessary.
*
* @param synced is the #OggSyncState currently synced? If not, then
* we need to use ogg_sync_pageseek() instead of ogg_sync_pageout(),
* which is more expensive
* @return true if the EOS packet was found
*/
bool
OggSeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet,
InputStream &is);
InputStream &is, bool synced=true);
#endif

View File

@ -43,7 +43,7 @@ OggSyncState::ExpectPage(ogg_page &page)
if (r != 0) {
if (r > 0) {
start_offset = offset;
offset += r;
offset += page.header_len + page.body_len;
}
return r > 0;
}

View File

@ -231,7 +231,7 @@ UdisksNeighborExplorer::HandleMessage(DBusConnection *, DBusMessage *message) no
dbus_message_has_signature(message, InterfacesAddedType::value)) {
RecurseInterfaceDictEntry(ReadMessageIter(*message), [this](const char *path, auto &&i){
UDisks2::Object o(path);
UDisks2::ParseObject(o, std::move(i));
UDisks2::ParseObject(o, std::forward<decltype(i)>(i));
if (o.IsValid())
this->Insert(std::move(o));
});

View File

@ -116,7 +116,7 @@ AudioOutputControl::GetMixer() const noexcept
return output ? output->mixer : nullptr;
}
const std::map<std::string, std::string>
std::map<std::string, std::string>
AudioOutputControl::GetAttributes() const noexcept
{
return output

View File

@ -357,7 +357,7 @@ public:
void BeginDestroy() noexcept;
const std::map<std::string, std::string> GetAttributes() const noexcept;
std::map<std::string, std::string> GetAttributes() const noexcept;
void SetAttribute(std::string &&name, std::string &&value);
/**

View File

@ -39,7 +39,7 @@ FilteredAudioOutput::SupportsPause() const noexcept
return output->SupportsPause();
}
const std::map<std::string, std::string>
std::map<std::string, std::string>
FilteredAudioOutput::GetAttributes() const noexcept
{
return output->GetAttributes();

View File

@ -170,7 +170,7 @@ public:
gcc_pure
bool SupportsPause() const noexcept;
const std::map<std::string, std::string> GetAttributes() const noexcept;
std::map<std::string, std::string> GetAttributes() const noexcept;
void SetAttribute(std::string &&name, std::string &&value);
/**

View File

@ -64,7 +64,7 @@ public:
*
* This method must be thread-safe.
*/
virtual const std::map<std::string, std::string> GetAttributes() const noexcept {
virtual std::map<std::string, std::string> GetAttributes() const noexcept {
return {};
}

View File

@ -228,7 +228,7 @@ public:
}
private:
const std::map<std::string, std::string> GetAttributes() const noexcept override;
std::map<std::string, std::string> GetAttributes() const noexcept override;
void SetAttribute(std::string &&name, std::string &&value) override;
void Enable() override;
@ -404,7 +404,7 @@ AlsaOutput::AlsaOutput(EventLoop &_loop, const ConfigBlock &block)
#endif
buffer_time(block.GetPositiveValue("buffer_time",
MPD_ALSA_BUFFER_TIME_US)),
period_time(block.GetPositiveValue("period_time", 0u))
period_time(block.GetPositiveValue("period_time", 0U))
{
#ifdef SND_PCM_NO_AUTO_RESAMPLE
if (!block.GetBlockValue("auto_resample", true))
@ -427,7 +427,7 @@ AlsaOutput::AlsaOutput(EventLoop &_loop, const ConfigBlock &block)
allowed_formats = Alsa::AllowedFormat::ParseList(allowed_formats_string);
}
const std::map<std::string, std::string>
std::map<std::string, std::string>
AlsaOutput::GetAttributes() const noexcept
{
const std::lock_guard<Mutex> lock(attributes_mutex);

View File

@ -101,7 +101,7 @@ MakeAoError()
AoOutput::AoOutput(const ConfigBlock &block)
:AudioOutput(0),
write_size(block.GetPositiveValue("write_size", 1024u))
write_size(block.GetPositiveValue("write_size", 1024U))
{
const char *value = block.GetBlockValue("driver", "default");
if (StringIsEqual(value, "default"))

View File

@ -247,7 +247,7 @@ JackOutput::JackOutput(const ConfigBlock &block)
num_source_ports, num_destination_ports,
block.line);
ringbuffer_size = block.GetPositiveValue("ringbuffer_size", 32768u);
ringbuffer_size = block.GetPositiveValue("ringbuffer_size", 32768U);
}
inline jack_nframes_t

View File

@ -99,7 +99,7 @@ ShoutOutput::ShoutOutput(const ConfigBlock &block)
{
const char *host = require_block_string(block, "host");
const char *mount = require_block_string(block, "mount");
unsigned port = block.GetBlockValue("port", 0u);
unsigned port = block.GetBlockValue("port", 0U);
if (port == 0)
throw std::runtime_error("shout port must be configured");

View File

@ -50,11 +50,11 @@ HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block)
genre = block.GetBlockValue("genre", "Set genre in config");
website = block.GetBlockValue("website", "Set website in config");
clients_max = block.GetBlockValue("max_clients", 0u);
clients_max = block.GetBlockValue("max_clients", 0U);
/* set up bind_to_address */
ServerSocketAddGeneric(*this, block.GetBlockValue("bind_to_address"), block.GetBlockValue("port", 8000u));
ServerSocketAddGeneric(*this, block.GetBlockValue("bind_to_address"), block.GetBlockValue("port", 8000U));
/* determine content type */
content_type = prepared_encoder->GetMimeType();

View File

@ -94,5 +94,5 @@ DsdToDopConverter::Convert(ConstBuffer<uint8_t> src) noexcept
{
using namespace std::placeholders;
return rest_buffer.Process<uint32_t>(buffer, src, 2 * channels,
std::bind(DsdToDop, _1, _2, _3, channels));
[=](auto && arg1, auto && arg2, auto && arg3) { return DsdToDop(arg1, arg2, arg3, channels); });
}

View File

@ -65,5 +65,5 @@ Dsd16Converter::Convert(ConstBuffer<uint8_t> src) noexcept
{
using namespace std::placeholders;
return rest_buffer.Process<uint16_t>(buffer, src, channels,
std::bind(Dsd8To16, _1, _2, _3, channels));
[=](auto && arg1, auto && arg2, auto && arg3) { return Dsd8To16(arg1, arg2, arg3, channels); });
}

View File

@ -67,5 +67,5 @@ Dsd32Converter::Convert(ConstBuffer<uint8_t> src) noexcept
{
using namespace std::placeholders;
return rest_buffer.Process<uint32_t>(buffer, src, channels,
std::bind(Dsd8To32, _1, _2, _3, channels));
[=](auto && arg1, auto && arg2, auto && arg3) { return Dsd8To32(arg1, arg2, arg3, channels); });
}

View File

@ -261,8 +261,8 @@ public:
CommonExpatParser(ExpatNamespaceSeparator{'|'})
{
request.SetOption(CURLOPT_CUSTOMREQUEST, "PROPFIND");
request.SetOption(CURLOPT_FOLLOWLOCATION, 1l);
request.SetOption(CURLOPT_MAXREDIRS, 1l);
request.SetOption(CURLOPT_FOLLOWLOCATION, 1L);
request.SetOption(CURLOPT_MAXREDIRS, 1L);
request_headers.Append(StringFormat<40>("depth: %u", depth));

View File

@ -38,7 +38,7 @@ struct ApeFooter {
};
bool
tag_ape_scan(InputStream &is, ApeTagCallback callback)
tag_ape_scan(InputStream &is, const ApeTagCallback& callback)
try {
std::unique_lock<Mutex> lock(is.mutex);

View File

@ -37,6 +37,6 @@ typedef std::function<bool(unsigned long flags, const char *key,
* present
*/
bool
tag_ape_scan(InputStream &is, ApeTagCallback callback);
tag_ape_scan(InputStream &is, const ApeTagCallback& callback);
#endif

View File

@ -54,14 +54,14 @@ tag_ape_import_item(unsigned long flags,
return false;
if (handler.WantPair())
for (const auto &i : IterableSplitString(value, '\0'))
for (const auto i : IterableSplitString(value, '\0'))
handler.OnPair(key, i);
TagType type = tag_ape_name_parse(key);
if (type == TAG_NUM_OF_ITEM_TYPES)
return false;
for (const auto &i : IterableSplitString(value, '\0'))
for (const auto i : IterableSplitString(value, '\0'))
handler.OnTag(type, i);
return true;

View File

@ -204,7 +204,7 @@ struct CheckSequenceUTF8 {
};
template<>
struct CheckSequenceUTF8<0u> {
struct CheckSequenceUTF8<0U> {
constexpr bool operator()(gcc_unused const char *p) const noexcept {
return true;
}
@ -217,7 +217,7 @@ InnerSequenceLengthUTF8(const char *p) noexcept
{
return CheckSequenceUTF8<L>()(p)
? L + 1
: 0u;
: 0U;
}
size_t

View File

@ -28,15 +28,15 @@
void
DumpDecoderClient::Ready(const AudioFormat audio_format,
gcc_unused bool seekable,
bool seekable,
SignedSongTime duration) noexcept
{
assert(!initialized);
assert(audio_format.IsValid());
fprintf(stderr, "audio_format=%s duration=%f\n",
fprintf(stderr, "audio_format=%s duration=%f seekable=%d\n",
ToString(audio_format).c_str(),
duration.ToDoubleS());
duration.ToDoubleS(), seekable);
initialized = true;
}
@ -101,7 +101,7 @@ DumpDecoderClient::SubmitData(gcc_unused InputStream *is,
}
gcc_unused ssize_t nbytes = write(STDOUT_FILENO, data, datalen);
return DecoderCommand::NONE;
return GetCommand();
}
DecoderCommand
@ -113,7 +113,7 @@ DumpDecoderClient::SubmitTag(gcc_unused InputStream *is,
for (const auto &i : tag)
fprintf(stderr, " %s=%s\n", tag_item_names[i.type], i.value);
return DecoderCommand::NONE;
return GetCommand();
}
static void

View File

@ -27,7 +27,7 @@
* A #DecoderClient implementation which dumps metadata to stderr and
* decoded data to stdout.
*/
class DumpDecoderClient final : public DecoderClient {
class DumpDecoderClient : public DecoderClient {
bool initialized = false;
uint16_t prev_kbit_rate = 0;

View File

@ -6,10 +6,14 @@ if compiler.get_id() == 'gcc'
gtest_compile_args += [
'-Wno-suggest-attribute=format',
'-Wno-suggest-attribute=noreturn',
'-Wno-missing-declarations',
]
endif
# needed on Jessie for gtest's IsNullLiteralHelper
'-Wno-conversion-null',
if compiler.get_id() == 'clang' and compiler.version().version_compare('>=9')
gtest_compile_args += [
# work around clang warning caused by GTest's wrong "-lpthread"
# compiler flag
'-Wno-unused-command-line-argument',
]
endif

View File

@ -47,16 +47,20 @@ struct CommandLine {
Path config_path = nullptr;
bool verbose = false;
SongTime seek_where{};
};
enum Option {
OPTION_CONFIG,
OPTION_VERBOSE,
OPTION_SEEK,
};
static constexpr OptionDef option_defs[] = {
{"config", 0, true, "Load a MPD configuration file"},
{"verbose", 'v', false, "Verbose logging"},
{"seek", 0, true, "Seek to this position"},
};
static CommandLine
@ -74,6 +78,10 @@ ParseCommandLine(int argc, char **argv)
case OPTION_VERBOSE:
c.verbose = true;
break;
case OPTION_SEEK:
c.seek_where = SongTime::FromS(strtod(o.value, nullptr));
break;
}
}
@ -102,6 +110,85 @@ public:
}
};
class MyDecoderClient final : public DumpDecoderClient {
SongTime seek_where;
unsigned sample_rate;
bool seekable, seek_error = false;
public:
explicit MyDecoderClient(SongTime _seek_where) noexcept
:seek_where(_seek_where) {}
void Finish() {
if (!IsInitialized())
throw "Unrecognized file";
if (seek_error)
throw "Seek error";
if (seek_where != SongTime{}) {
if (!seekable)
throw "Not seekable";
throw "Did not seek";
}
}
/* virtual methods from DecoderClient */
void Ready(AudioFormat audio_format,
bool _seekable, SignedSongTime duration) noexcept override {
assert(!IsInitialized());
DumpDecoderClient::Ready(audio_format, _seekable, duration);
sample_rate = audio_format.sample_rate;
seekable = _seekable;
}
DecoderCommand GetCommand() noexcept override {
assert(IsInitialized());
if (seek_where != SongTime{}) {
if (!seekable)
return DecoderCommand::STOP;
return DecoderCommand::SEEK;
} else if (seek_error)
return DecoderCommand::STOP;
else
return DumpDecoderClient::GetCommand();
}
void CommandFinished() noexcept override {
assert(!seek_error);
if (seek_where != SongTime{})
seek_where = {};
else
DumpDecoderClient::CommandFinished();
}
SongTime GetSeekTime() noexcept override {
assert(seek_where != SongTime{});
return seek_where;
}
uint64_t GetSeekFrame() noexcept override {
assert(seek_where != SongTime{});
return GetSeekTime().ToScale<uint64_t>(sample_rate);
}
void SeekError() noexcept override {
assert(seek_where != SongTime{});
seek_error = true;
seek_where = {};
}
};
int main(int argc, char **argv)
try {
const auto c = ParseCommandLine(argc, argv);
@ -115,7 +202,7 @@ try {
return EXIT_FAILURE;
}
DumpDecoderClient client;
MyDecoderClient client(c.seek_where);
if (plugin->file_decode != nullptr) {
try {
plugin->FileDecode(client, Path::FromFS(c.uri));
@ -132,10 +219,7 @@ try {
return EXIT_FAILURE;
}
if (!client.IsInitialized()) {
fprintf(stderr, "Decoding failed\n");
return EXIT_FAILURE;
}
client.Finish();
return EXIT_SUCCESS;
} catch (...) {