Compare commits

...

43 Commits

Author SHA1 Message Date
Max Kellermann
fe45f28204 release v0.18.16 2014-09-26 10:57:04 +02:00
Max Kellermann
861067412f configure.ac: fix DSD breakage due to typo 2014-09-26 10:56:20 +02:00
Max Kellermann
7eca886608 configure.ac: prepare for 0.18.16 2014-09-26 10:55:43 +02:00
Max Kellermann
79b6f9e89e release v0.18.15 2014-09-26 09:41:40 +02:00
Max Kellermann
3d17c06777 configure.ac: allow building MPD without decoder plugin
There's always the "PCM" decoder plugin, which was never checked by
configure.ac.
2014-09-26 09:29:18 +02:00
Max Kellermann
d6c08fb79f configure.ac: allow building MPD without output plugin
MPD can easily be used as a database provider for the proxy database
plugin.  In that case, it needs only one "null" output, and no real
output plugin.
2014-09-26 09:29:18 +02:00
Max Kellermann
ef02b20811 CommandLine: update copyright year 2014-09-26 09:29:18 +02:00
Max Kellermann
8bf46a665e configure.ac: add option to disable the DSD decoders
Allow building a smaller MPD binary for people who don't need DSD.
2014-09-26 09:29:18 +02:00
Max Kellermann
c4fca2aa61 playlist/embcue: change name string to "embcue"
The name "cue" was listed twice in "mpd --version".
2014-09-26 09:29:18 +02:00
Max Kellermann
87268c2297 test/test_protocol: add missing stdlib.h include
EXIT_SUCCESS and EXIT_FAILURE are defined in stdlib.h, not unistd.h.
D'oh!
2014-09-24 23:03:28 +02:00
Max Kellermann
e93975cb46 test/test_protocol: add missing unistd.h include 2014-09-24 21:43:11 +02:00
Max Kellermann
b6fa22bd84 OutputThread: retain negative mix ratio
Fixes MixRamp breakage.
2014-09-18 13:50:23 +02:00
Andrzej Rybczak
a0ef27a0cd command/list: reset used size after the list has been processed 2014-09-18 09:15:39 +02:00
Max Kellermann
e304d0f8ee thread/Posix{Cond,Mutex}: don't ues PTHREAD_*_INITIALIZER on NetBSD
On NetBSD, PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER are
not compatible with C++11 "constexpr" (see Mantis ticket 0004110).  As
a workaround, don't ues "constexpr", and use the functions
pthread_mutex_init(), pthread_mutex_destroy(), pthread_cond_init() and
pthread_cond_destroy() instead.  This adds some runtime overhead, but
is portable to POSIX implementations that have awkward initializer
macros.
2014-09-13 11:26:17 +02:00
Max Kellermann
ab7b38d4b9 configure.ac: prepare for 0.18.15 2014-09-13 11:14:41 +02:00
Max Kellermann
eaf675dc92 release v0.18.14 2014-09-11 19:09:49 +02:00
Max Kellermann
57068e526c test/run_decoder: dump MixRamp data 2014-09-09 19:17:22 +02:00
Max Kellermann
c14a00eec9 decoder/ffmpeg: use memset() to initialize AVProbeData 2014-09-09 19:07:46 +02:00
Max Kellermann
219c42522f decoder/ffmpeg: pass MIME type to ffmpeg/libav version 11
That attribute was uninitialized before, which could crash
libavformat.

See Debian bug 760669
2014-09-07 22:05:33 +02:00
Max Kellermann
e3a0f15837 Decoder*: add more assertions 2014-09-07 21:52:34 +02:00
Max Kellermann
a6bb27483b DecoderThread: clear the pipe when handling late SEEK
See code comment.  Fixes assertion failure in
decoder_command_finished().
2014-09-07 21:50:00 +02:00
Max Kellermann
7ada7def9e decoder/audiofile: fix crash after seeking
Log call was added to the wrong branch.

Fixes regression by commit ca1a1149
2014-09-06 19:32:10 +02:00
Max Kellermann
421c4ae907 protocol/ArgParser: fix integer overflow in parse_range()
Casting std::numeric_limits<unsigned>::max() to "long" leads to an
overflow if sizeof(unsigned)==sizeof(long), and the result will be -1.

This happens on some 32 bit architectures, for example ARM and WIN32.

Workaround: use std::numeric_limits<int>::max(), which is the largest
signed integer.  Since sizeof(long)>=sizeof(int), this will never
overflow.

Fixes Mantis ticket 0004080.
2014-09-04 17:37:31 +02:00
Max Kellermann
4907f610d6 test/test_protocol: unit test for protocol/ArgParser.cxx 2014-09-04 17:10:30 +02:00
Max Kellermann
f9d1bbbffb configure.ac: prepare for 0.18.14 2014-09-03 19:59:26 +02:00
Max Kellermann
86e8b3b4bd release v0.18.13 2014-08-31 14:50:23 +02:00
Max Kellermann
a26ead035a PlaylistControl: use SeekSongOrder(current) to keep current song
The "current" attribute is a "song order", not a "song position".
This is usually the same - except in random mode.  Fixes Mantis ticket
0004073.
2014-08-31 14:44:20 +02:00
Max Kellermann
704be54c3a PlaylistControl: move code to new method SeekSongOrder() 2014-08-31 14:23:06 +02:00
Max Kellermann
2406152576 output/alsa: fix endless loop at end of file in dsd_usb mode 2014-08-31 14:01:57 +02:00
Max Kellermann
af260b5a64 output/{alsa,oss}: add assertions 2014-08-31 14:00:09 +02:00
Joachim Fasting
4efa96df21 doc/protocol: fix description of "stats" response
Fix incorrect description of the "songs" field and add missing
"albums" field.

Signed-off-by: Joachim Fasting <joachifm@fastmail.fm>
2014-08-31 13:16:39 +02:00
Max Kellermann
8b62127770 decoder/gme: fix song duration
The unit of gme_info_t::length is milliseconds, not centiseconds.
2014-08-29 23:03:29 +02:00
Max Kellermann
f06fe1ea98 event/TimeoutMonitor: really reset "active" flag before invoking OnTimeout()
The previous commit was broken.  D'oh!
2014-08-24 13:19:50 +02:00
Max Kellermann
d16fb79708 event/TimeoutMonitor: reset "active" flag before invoking OnTimeout()
The IsActive() method returned true even if the timer was not active,
after it completed once.  This broke the state file timer, and the
state file was not saved periodically.
2014-08-24 13:13:12 +02:00
Thomas Klausner
c38f29ce56 system/ByteOrder: <endian.h> is a non-standard header that only Linux provides. 2014-08-23 14:27:44 +02:00
Max Kellermann
78abcd7df7 decoer/dsdiff: fix endless loop on malformed file
Same bug as in the previous commit.
2014-08-21 12:48:03 +02:00
Max Kellermann
23dce21647 decoer/dsf: fix endless loop on malformed file
When the data chunk size is not a multiple of the frame size, the last
partial frame lead to an endless loop.  We fix this by checking
chunk_sze>=frame instead of chunk_sze>0.  This way, the partial frame
is simply skipped.
2014-08-21 12:37:22 +02:00
François Revol
40280fa6cf util: Fix header for strcasecmp
According to POSIX and both OSX and Linux manpages,
strcasecmp comes from strings.h, not string.h.

Most OSes also have them available in string.h,
but we just fixed the headers on Haiku and it now
only provides them in strings.h.

We might want to fall back to string.h for other
OSes though...

cf.
http://pubs.opengroup.org/onlinepubs/009695399/functions/strcasecmp.html
http://linux.die.net/man/3/strcasecmp
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/strcasecmp.3.html
2014-08-16 06:51:13 +02:00
Max Kellermann
fe9299ceff decoder/ffmpeg: use avcodec_descriptor_get() to determine codec name
In version 11, both ffmpeg and libav deprecate
AVCodecContext::codec_name.  The function avcodec_descriptor_get() has
been introduced long ago.
2014-08-13 18:40:39 +02:00
Max Kellermann
c3f111a56c event/BufferedSocket: fix inversed buffer check
This was broken by commit 84d20d9e, which deleted the "!" from the
check.
2014-08-07 16:03:44 +02:00
François Revol
250318329f Makefile.am: fix dependencies for win32
It happened to me when doing the Haiku port, src/mpd failed to
be relinked properly when editing source files, and likely also
happens on win32, although I didn't try this change.

When building for windows, src_mpd_DEPENDENCIES is overriden.

Automake then disables the default version which contains all
the static libraries. In Makefile.in:
@HAVE_WINDOWS_FALSE@src_mpd_DEPENDENCIES = libmpd.a \

Instead we use EXTRA_src_mpd_DEPENDENCIES which is meant for this.
2014-08-02 08:48:44 +02:00
Max Kellermann
14c538c9c7 Win32Main: move to win32/ 2014-08-02 08:48:30 +02:00
Max Kellermann
abe4c57663 configure.ac: prepare for 0.18.13 2014-08-02 08:45:44 +02:00
35 changed files with 290 additions and 83 deletions

3
.gitignore vendored

@@ -40,7 +40,7 @@ tags
.#*
.stgit*
src/dsd2pcm/dsd2pcm
src/win/mpd_win32_rc.rc
src/win32/mpd_win32_rc.rc
doc/doxygen.conf
doc/protocol.html
doc/protocol
@@ -63,6 +63,7 @@ test/run_normalize
test/tmp
test/run_inotify
test/test_queue_priority
test/test_protocol
test/run_ntp_server
test/run_resolver
test/run_tcp_connect

@@ -151,7 +151,7 @@ src_mpd_SOURCES = \
src/IOThread.cxx src/IOThread.hxx \
src/Main.cxx src/Main.hxx \
src/Instance.cxx src/Instance.hxx \
src/Win32Main.cxx \
src/win32/Win32Main.cxx \
src/GlobalEvents.cxx src/GlobalEvents.hxx \
src/Daemon.cxx src/Daemon.hxx \
src/AudioCompress/compress.c \
@@ -211,14 +211,14 @@ src_mpd_SOURCES = \
# Windows resource file
#
src/win/mpd_win32_rc.$(OBJEXT): src/win/mpd_win32_rc.rc
src/win32/mpd_win32_rc.$(OBJEXT): src/win32/mpd_win32_rc.rc
$(WINDRES) -i $< -o $@
if HAVE_WINDOWS
noinst_DATA = src/win/mpd_win32_rc.rc
noinst_DATA = src/win32/mpd_win32_rc.rc
src_mpd_DEPENDENCIES = src/win/mpd_win32_rc.$(OBJEXT)
src_mpd_LDFLAGS = -Wl,src/win/mpd_win32_rc.$(OBJEXT)
EXTRA_src_mpd_DEPENDENCIES = src/win32/mpd_win32_rc.$(OBJEXT)
src_mpd_LDFLAGS = -Wl,src/win32/mpd_win32_rc.$(OBJEXT)
endif
if ENABLE_DESPOTIFY
@@ -476,12 +476,6 @@ endif
libdecoder_plugins_a_SOURCES = \
src/decoder/PcmDecoderPlugin.cxx \
src/decoder/PcmDecoderPlugin.hxx \
src/decoder/DsdiffDecoderPlugin.cxx \
src/decoder/DsdiffDecoderPlugin.hxx \
src/decoder/DsfDecoderPlugin.cxx \
src/decoder/DsfDecoderPlugin.hxx \
src/decoder/DsdLib.cxx \
src/decoder/DsdLib.hxx \
src/DecoderBuffer.cxx src/DecoderBuffer.hxx \
src/DecoderPlugin.cxx \
src/DecoderList.cxx src/DecoderList.hxx
@@ -525,6 +519,16 @@ DECODER_LIBS = \
DECODER_SRC =
if ENABLE_DSD
libdecoder_plugins_a_SOURCES += \
src/decoder/DsdiffDecoderPlugin.cxx \
src/decoder/DsdiffDecoderPlugin.hxx \
src/decoder/DsfDecoderPlugin.cxx \
src/decoder/DsfDecoderPlugin.hxx \
src/decoder/DsdLib.cxx \
src/decoder/DsdLib.hxx
endif
if HAVE_MAD
libdecoder_plugins_a_SOURCES += \
src/decoder/MadDecoderPlugin.cxx \
@@ -1064,6 +1068,7 @@ C_TESTS = \
test/test_mixramp \
test/test_icy_parser \
test/test_pcm \
test/test_protocol \
test/test_queue_priority
if ENABLE_ARCHIVE
@@ -1538,6 +1543,16 @@ test_test_archive_LDADD = \
$(GLIB_LIBS) \
$(CPPUNIT_LIBS)
test_test_protocol_SOURCES = \
src/protocol/ArgParser.cxx \
test/test_protocol.cxx
test_test_protocol_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0
test_test_protocol_CXXFLAGS = $(AM_CXXFLAGS) -Wno-error=deprecated-declarations
test_test_protocol_LDADD = \
libsystem.a \
libutil.a \
$(CPPUNIT_LIBS)
test_test_queue_priority_SOURCES = \
src/Queue.cxx \
test/test_queue_priority.cxx
@@ -1548,6 +1563,8 @@ test_test_queue_priority_LDADD = \
libutil.a \
$(CPPUNIT_LIBS)
if ENABLE_DSD
noinst_PROGRAMS += src/pcm/dsd2pcm/dsd2pcm
src_pcm_dsd2pcm_dsd2pcm_SOURCES = \
@@ -1560,6 +1577,8 @@ src_pcm_dsd2pcm_dsd2pcm_LDADD = libutil.a
endif
endif
#
# Documentation
@@ -1633,4 +1652,4 @@ EXTRA_DIST = $(doc_DATA) autogen.sh \
test/test_archive_zzip.sh \
$(wildcard scripts/*.sh) \
$(man_MANS) $(DOCBOOK_FILES) doc/mpdconf.example doc/doxygen.conf \
src/win/mpd_win32_rc.rc.in src/win/mpd.ico
src/win32/mpd_win32_rc.rc.in src/win32/mpd.ico

29
NEWS

@@ -1,3 +1,32 @@
ver 0.18.16 (2014/09/26)
* fix DSD breakage due to typo in configure.ac
ver 0.18.15 (2014/09/26)
* command
- list: reset used size after the list has been processed
* fix MixRamp
* work around build failure on NetBSD
ver 0.18.14 (2014/09/11)
* protocol
- fix range parser bug on certain 32 bit architectures
* decoder
- audiofile: fix crash after seeking
- ffmpeg: fix crash with ffmpeg/libav version 11
- fix assertion failure after seeking
ver 0.18.13 (2014/08/31)
* protocol
- don't change song on "seekcur" in random mode
* decoder
- dsdiff, dsf: fix endless loop on malformed file
- ffmpeg: support ffmpeg/libav version 11
- gme: fix song duration
* output
- alsa: fix endless loop at end of file in dsd_usb mode
* fix state file saver
* fix build failure on Darwin
ver 0.18.12 (2014/07/30)
* database
- proxy: fix build failure with libmpdclient 2.2

@@ -1,6 +1,6 @@
AC_PREREQ(2.60)
AC_INIT(mpd, 0.18.12, mpd-devel@musicpd.org)
AC_INIT(mpd, 0.18.16, mpd-devel@musicpd.org)
VERSION_MAJOR=0
VERSION_MINOR=18
@@ -70,7 +70,7 @@ host_is_darwin=no
case "$host_os" in
mingw32* | windows*)
AC_CONFIG_FILES([
src/win/mpd_win32_rc.rc
src/win32/mpd_win32_rc.rc
])
AC_CHECK_TOOL(WINDRES, windres)
AM_CPPFLAGS="$AM_CPPFLAGS -DWIN32_LEAN_AND_MEAN"
@@ -214,6 +214,11 @@ AC_ARG_ENABLE(documentation,
[build documentation (default: disable)]),,
[enable_documentation=no])
AC_ARG_ENABLE(dsd,
AS_HELP_STRING([--enable-dsd],
[enable DSD decoder (default: enable)]),,
[enable_dsd=yes])
AC_ARG_ENABLE(ffmpeg,
AS_HELP_STRING([--enable-ffmpeg],
[enable FFMPEG support]),,
@@ -846,6 +851,14 @@ if test x$enable_audiofile = xyes; then
AC_DEFINE(HAVE_AUDIOFILE, 1, [Define for audiofile support])
fi
dnl ----------------------------------- DSD -----------------------------------
if test x$enable_dsd = xyes; then
AC_DEFINE(ENABLE_DSD, 1, [Define for the DSD decoder])
fi
AM_CONDITIONAL(ENABLE_DSD, test x$enable_dsd = xyes)
dnl ----------------------------------- FAAD ----------------------------------
AM_PATH_FAAD()
@@ -1081,27 +1094,6 @@ AM_CONDITIONAL(ENABLE_WILDMIDI, test x$enable_wildmidi = xyes)
dnl ------------------------ Post Decoder Plugins Tests -----------------------
if
test x$enable_aac = xno &&
test x$enable_audiofile = xno &&
test x$enable_ffmpeg = xno &&
test x$enable_flac = xno &&
test x$enable_fluidsynth = xno &&
test x$enable_mad = xno &&
test x$enable_mikmod = xno; then
test x$enable_modplug = xno &&
test x$enable_mpc = xno &&
test x$enable_mpg123 = xno &&
test x$enable_opus = xno &&
test x$enable_sidplay = xno &&
test x$enable_tremor = xno &&
test x$enable_vorbis = xno &&
test x$enable_wavpack = xno &&
test x$enable_wildmidi = xno &&
AC_MSG_ERROR([No input plugins supported!])
fi
AM_CONDITIONAL(HAVE_XIPH,
test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_flac = xyes || test x$enable_opus = xyes)
@@ -1410,27 +1402,6 @@ esac
AM_CONDITIONAL(ENABLE_WINMM_OUTPUT, test x$enable_winmm_output = xyes)
dnl --------------------- Post Audio Output Plugins Tests ---------------------
if
test x$enable_alsa = xno &&
test x$enable_roar = xno &&
test x$enable_ao = xno &&
test x$enable_fifo = xno &&
test x$enable_httpd_output = xno &&
test x$enable_jack = xno &&
test x$enable_openal = xno &&
test x$enable_oss = xno &&
test x$enable_osx = xno &&
test x$enable_pipe_output = xno &&
test x$enable_pulse = xno &&
test x$enable_recorder_output = xno &&
test x$enable_shout = xno &&
test x$enable_solaris_output = xno &&
test x$enable_winmm_output = xno; then
AC_MSG_ERROR([No Audio Output types configured!])
fi
dnl ---------------------------------------------------------------------------
dnl Documentation
dnl ---------------------------------------------------------------------------

@@ -576,7 +576,12 @@
</listitem>
<listitem>
<para>
<varname>songs</varname>: number of albums
<varname>albums</varname>: number of albums
</para>
</listitem>
<listitem>
<para>
<varname>songs</varname>: number of songs
</para>
</listitem>
<listitem>

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -69,7 +69,7 @@ static void version(void)
puts("Music Player Daemon " VERSION "\n"
"\n"
"Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"
"Copyright (C) 2008-2013 Max Kellermann <max@duempel.org>\n"
"Copyright (C) 2008-2014 Max Kellermann <max@duempel.org>\n"
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
"\n"

@@ -47,6 +47,7 @@ decoder_initialized(Decoder &decoder,
assert(dc.state == DecoderState::START);
assert(dc.pipe != nullptr);
assert(dc.pipe->IsEmpty());
assert(decoder.stream_tag == nullptr);
assert(decoder.decoder_tag == nullptr);
assert(!decoder.seeking);
@@ -405,6 +406,9 @@ decoder_data(Decoder &decoder,
length == 0)
return cmd;
assert(!decoder.initial_seek_pending);
assert(!decoder.initial_seek_running);
/* send stream tags */
if (update_stream_tag(decoder, is)) {

@@ -83,6 +83,9 @@ void
decoder_flush_chunk(Decoder &decoder)
{
DecoderControl &dc = decoder.dc;
assert(!decoder.seeking);
assert(!decoder.initial_seek_running);
assert(!decoder.initial_seek_pending);
assert(decoder.chunk != nullptr);

@@ -73,8 +73,10 @@ const struct DecoderPlugin *const decoder_plugins[] = {
#ifdef HAVE_AUDIOFILE
&audiofile_decoder_plugin,
#endif
#ifdef ENABLE_DSD
&dsdiff_decoder_plugin,
&dsf_decoder_plugin,
#endif
#ifdef HAVE_FAAD
&faad_decoder_plugin,
#endif

@@ -26,6 +26,7 @@
#include "Song.hxx"
#include "system/FatalError.hxx"
#include "Mapper.hxx"
#include "MusicPipe.hxx"
#include "fs/Traits.hxx"
#include "fs/AllocatedPath.hxx"
#include "DecoderAPI.hxx"
@@ -418,9 +419,18 @@ decoder_task(void *arg)
dc.replay_gain_prev_db = dc.replay_gain_db;
dc.replay_gain_db = 0;
/* fall through */
decoder_run(dc);
break;
case DecoderCommand::SEEK:
/* this seek was too late, and the decoder had
already finished; start a new decoder */
/* we need to clear the pipe here; usually the
PlayerThread is responsible, but it is not
aware that the decoder has finished */
dc.pipe->Clear(*dc.buffer);
decoder_run(dc);
break;

@@ -385,11 +385,20 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
if (length > other_length)
length = other_length;
float mix_ratio = chunk->mix_ratio;
if (mix_ratio >= 0)
/* reverse the mix ratio (because the
arguments to pcm_mix() are reversed), but
only if the mix ratio is non-negative; a
negative mix ratio is a MixRamp special
case */
mix_ratio = 1.0 - mix_ratio;
void *dest = ao->cross_fade_buffer.Get(other_length);
memcpy(dest, other_data, other_length);
if (!pcm_mix(dest, data, length,
ao->in_audio_format.format,
1.0 - chunk->mix_ratio)) {
mix_ratio)) {
FormatError(output_domain,
"Cannot cross-fade format %s",
sample_format_to_string(ao->in_audio_format.format));

@@ -234,6 +234,10 @@ public:
void PlayPrevious(PlayerControl &pc);
PlaylistResult SeekSongOrder(PlayerControl &pc,
unsigned song_order,
float seek_time);
PlaylistResult SeekSongPosition(PlayerControl &pc,
unsigned song_position,
float seek_time);

@@ -190,17 +190,12 @@ playlist::PlayPrevious(PlayerControl &pc)
}
PlaylistResult
playlist::SeekSongPosition(PlayerControl &pc, unsigned song, float seek_time)
playlist::SeekSongOrder(PlayerControl &pc, unsigned i, float seek_time)
{
if (!queue.IsValidPosition(song))
return PlaylistResult::BAD_RANGE;
assert(queue.IsValidOrder(i));
const Song *queued_song = GetQueuedSong();
unsigned i = queue.random
? queue.PositionToOrder(song)
: song;
pc.ClearError();
stop_on_error = true;
error_count = 0;
@@ -228,6 +223,19 @@ playlist::SeekSongPosition(PlayerControl &pc, unsigned song, float seek_time)
return PlaylistResult::SUCCESS;
}
PlaylistResult
playlist::SeekSongPosition(PlayerControl &pc, unsigned song, float seek_time)
{
if (!queue.IsValidPosition(song))
return PlaylistResult::BAD_RANGE;
unsigned i = queue.random
? queue.PositionToOrder(song)
: song;
return SeekSongOrder(pc, i, seek_time);
}
PlaylistResult
playlist::SeekSongId(PlayerControl &pc, unsigned id, float seek_time)
{
@@ -257,5 +265,5 @@ playlist::SeekCurrent(PlayerControl &pc, float seek_time, bool relative)
if (seek_time < 0)
seek_time = 0;
return SeekSongPosition(pc, current, seek_time);
return SeekSongOrder(pc, current, seek_time);
}

@@ -27,6 +27,7 @@ void
CommandListBuilder::Reset()
{
list.clear();
size = 0;
mode = Mode::DISABLED;
}

@@ -110,9 +110,9 @@ audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative)
Error error;
if (is.LockSeek(offset, whence, error)) {
LogError(error, "Seek failed");
return is.GetOffset();
} else {
LogError(error, "Seek failed");
return -1;
}
}

@@ -377,7 +377,7 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
const unsigned buffer_samples = buffer_frames * frame_size;
const size_t buffer_size = buffer_samples * sample_size;
while (chunk_size > 0) {
while (chunk_size >= frame_size) {
/* see how much aligned data from the remaining chunk
fits into the local buffer */
size_t now_size = buffer_size;

@@ -238,7 +238,7 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
const unsigned buffer_samples = buffer_frames * frame_size;
const size_t buffer_size = buffer_samples * sample_size;
while (chunk_size > 0) {
while (chunk_size >= frame_size) {
/* see how much aligned data from the remaining chunk
fits into the local buffer */
size_t now_size = buffer_size;

@@ -383,10 +383,23 @@ ffmpeg_probe(Decoder *decoder, InputStream &is)
nbytes -= PADDING;
AVProbeData avpd;
/* new versions of ffmpeg may add new attributes, and leaving
them uninitialized may crash; hopefully, zero-initializing
everything we don't know is ok */
memset(&avpd, 0, sizeof(avpd));
avpd.buf = buffer;
avpd.buf_size = nbytes;
avpd.filename = is.uri.c_str();
#ifdef AVPROBE_SCORE_MIME
/* this attribute was added in libav/ffmpeg version 11, but
unfortunately it's "uint8_t" instead of "char", and it's
not "const" - wtf? */
avpd.mime_type = (uint8_t *)const_cast<char *>(is.GetMimeType());
#endif
return av_probe_input_format(&avpd, true);
}
@@ -433,9 +446,18 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
AVStream *av_stream = format_context->streams[audio_stream];
AVCodecContext *codec_context = av_stream->codec;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0)
const AVCodecDescriptor *codec_descriptor =
avcodec_descriptor_get(codec_context->codec_id);
if (codec_descriptor != nullptr)
FormatDebug(ffmpeg_domain, "codec '%s'",
codec_descriptor->name);
#else
if (codec_context->codec_name[0] != 0)
FormatDebug(ffmpeg_domain, "codec '%s'",
codec_context->codec_name);
#endif
AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);

@@ -235,7 +235,7 @@ gme_scan_file(const char *path_fs,
if (ti->length > 0)
tag_handler_invoke_duration(handler, handler_ctx,
ti->length / 100);
ti->length / 1000);
if (ti->song != nullptr) {
if (gme_track_count(emu) > 1) {

@@ -118,7 +118,7 @@ BufferedSocket::OnSocketReady(unsigned flags)
if (!ReadToBuffer() || !ResumeInput())
return false;
if (input.IsFull())
if (!input.IsFull())
ScheduleRead();
}

@@ -64,7 +64,9 @@ TimeoutMonitor::ScheduleSeconds(unsigned s)
void
TimeoutMonitor::Run()
{
#ifndef USE_EPOLL
#ifdef USE_EPOLL
active = false;
#else
Cancel();
#endif

@@ -28,7 +28,7 @@ struct notify {
Cond cond;
bool pending;
#ifndef WIN32
#if !defined(WIN32) && !defined(__NetBSD__)
constexpr
#endif
notify():pending(false) {}

@@ -802,6 +802,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
{
AlsaOutput *ad = (AlsaOutput *)ao;
assert(size > 0);
assert(size % ad->in_frame_size == 0);
if (ad->must_prepare) {
@@ -814,11 +815,21 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
}
}
const size_t original_size = size;
chunk = ad->pcm_export->Export(chunk, size, size);
if (size == 0)
/* the DoP (DSD over PCM) filter converts two frames
at a time and ignores the last odd frame; if there
was only one frame (e.g. the last frame in the
file), the result is empty; to avoid an endless
loop, bail out here, and pretend the one frame has
been played */
return original_size;
assert(size % ad->out_frame_size == 0);
size /= ad->out_frame_size;
assert(size > 0);
while (true) {
snd_pcm_sframes_t ret = ad->writei(ad->pcm, chunk, size);

@@ -727,6 +727,8 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
OssOutput *od = (OssOutput *)ao;
ssize_t ret;
assert(size > 0);
/* reopen the device since it was closed by dropBufferedAudio */
if (od->fd < 0 && !oss_reopen(od, error))
return 0;
@@ -735,6 +737,8 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
chunk = od->pcm_export->Export(chunk, size, size);
#endif
assert(size > 0);
while (true) {
ret = write(od->fd, chunk, size);
if (ret > 0) {

@@ -171,7 +171,7 @@ static const char *const embcue_playlist_suffixes[] = {
};
const struct playlist_plugin embcue_playlist_plugin = {
"cue",
"embcue",
nullptr,
nullptr,

@@ -81,7 +81,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
/* compatibility with older MPD versions: specifying
"-1" makes MPD display the whole list */
*value_r1 = 0;
*value_r2 = std::numeric_limits<unsigned>::max();
*value_r2 = std::numeric_limits<int>::max();
return true;
}
@@ -108,7 +108,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
}
if (test == test2)
value = std::numeric_limits<unsigned>::max();
value = std::numeric_limits<int>::max();
if (value < 0) {
command_error(client, ACK_ERROR_ARG,

@@ -40,6 +40,16 @@
/* well-known big-endian */
# define IS_LITTLE_ENDIAN false
# define IS_BIG_ENDIAN true
#elif defined(__APPLE__)
/* compile-time check for MacOS */
# include <machine/endian.h>
# if BYTE_ORDER == LITTLE_ENDIAN
# define IS_LITTLE_ENDIAN true
# define IS_BIG_ENDIAN false
# else
# define IS_LITTLE_ENDIAN false
# define IS_BIG_ENDIAN true
# endif
#else
/* generic compile-time check */
# include <endian.h>

@@ -41,7 +41,21 @@ class PosixCond {
pthread_cond_t cond;
public:
#ifdef __NetBSD__
/* NetBSD's PTHREAD_COND_INITIALIZER is not compatible with
"constexpr" */
PosixCond() {
pthread_cond_init(&cond, nullptr);
}
~PosixCond() {
pthread_cond_destroy(&cond);
}
#else
/* optimized constexpr constructor for sane POSIX
implementations */
constexpr PosixCond():cond(PTHREAD_COND_INITIALIZER) {}
#endif
PosixCond(const PosixCond &other) = delete;
PosixCond &operator=(const PosixCond &other) = delete;

@@ -41,7 +41,21 @@ class PosixMutex {
pthread_mutex_t mutex;
public:
#ifdef __NetBSD__
/* NetBSD's PTHREAD_MUTEX_INITIALIZER is not compatible with
"constexpr" */
PosixMutex() {
pthread_mutex_init(&mutex, nullptr);
}
~PosixMutex() {
pthread_mutex_destroy(&mutex);
}
#else
/* optimized constexpr constructor for sane POSIX
implementations */
constexpr PosixMutex():mutex(PTHREAD_MUTEX_INITIALIZER) {}
#endif
PosixMutex(const PosixMutex &other) = delete;
PosixMutex &operator=(const PosixMutex &other) = delete;

@@ -33,7 +33,7 @@
#include "Compiler.h"
#include <assert.h>
#include <string.h>
#include <strings.h>
/**
* Determine whether two strings are equal, ignoring case for ASCII

Before

(image error) Size: 345 KiB

After

(image error) Size: 345 KiB

@@ -3,7 +3,7 @@
#define VERSION_NUMBER @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@
#define VERSION_NUMBER_STR "@VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@"
MPD_ICON ICON "@top_srcdir@/src/win/mpd.ico"
MPD_ICON ICON "@top_srcdir@/src/win32/mpd.ico"
1 VERSIONINFO
FILETYPE VFT_APP

@@ -175,8 +175,10 @@ decoder_replay_gain(gcc_unused Decoder &decoder,
}
void
decoder_mixramp(gcc_unused Decoder &decoder, gcc_unused MixRampInfo &&mix_ramp)
decoder_mixramp(gcc_unused Decoder &decoder, MixRampInfo &&mix_ramp)
{
fprintf(stderr, "MixRamp: start='%s' end='%s'\n",
mix_ramp.GetStart(), mix_ramp.GetEnd());
}
int main(int argc, char **argv)

62
test/test_protocol.cxx Normal file

@@ -0,0 +1,62 @@
#include "config.h"
#include "protocol/ArgParser.hxx"
#include "protocol/Result.hxx"
#include "Compiler.h"
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <stdlib.h>
static enum ack last_error = ack(-1);
void
command_error(gcc_unused Client &client, enum ack error,
gcc_unused const char *fmt, ...)
{
last_error = error;
}
class ArgParserTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ArgParserTest);
CPPUNIT_TEST(TestRange);
CPPUNIT_TEST_SUITE_END();
public:
void TestRange();
};
void
ArgParserTest::TestRange()
{
Client &client = *(Client *)nullptr;
unsigned a, b;
CPPUNIT_ASSERT(check_range(client, &a, &b, "1"));
CPPUNIT_ASSERT_EQUAL(1u, a);
CPPUNIT_ASSERT_EQUAL(2u, b);
CPPUNIT_ASSERT(check_range(client, &a, &b, "1:5"));
CPPUNIT_ASSERT_EQUAL(1u, a);
CPPUNIT_ASSERT_EQUAL(5u, b);
CPPUNIT_ASSERT(check_range(client, &a, &b, "1:"));
CPPUNIT_ASSERT_EQUAL(1u, a);
CPPUNIT_ASSERT(b >= 999999u);
CPPUNIT_ASSERT(!check_range(client, &a, &b, "-2"));
CPPUNIT_ASSERT_EQUAL(ACK_ERROR_ARG, last_error);
}
CPPUNIT_TEST_SUITE_REGISTRATION(ArgParserTest);
int
main(gcc_unused int argc, gcc_unused char **argv)
{
CppUnit::TextUi::TestRunner runner;
auto &registry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest(registry.makeTest());
return runner.run() ? EXIT_SUCCESS : EXIT_FAILURE;
}