Commit a464dc68 authored by Max Kellermann's avatar Max Kellermann

Merge tag 'v0.18.14'

parents af384d9a eaf675dc
...@@ -64,6 +64,7 @@ tags ...@@ -64,6 +64,7 @@ tags
/test/tmp /test/tmp
/test/run_inotify /test/run_inotify
/test/test_queue_priority /test/test_queue_priority
/test/test_protocol
/test/run_ntp_server /test/run_ntp_server
/test/run_resolver /test/run_resolver
/test/run_tcp_connect /test/run_tcp_connect
......
...@@ -1458,6 +1458,7 @@ C_TESTS = \ ...@@ -1458,6 +1458,7 @@ C_TESTS = \
test/test_rewind \ test/test_rewind \
test/test_mixramp \ test/test_mixramp \
test/test_pcm \ test/test_pcm \
test/test_protocol \
test/test_queue_priority test/test_queue_priority
if ENABLE_CURL if ENABLE_CURL
...@@ -2035,6 +2036,16 @@ test_test_translate_song_LDADD = \ ...@@ -2035,6 +2036,16 @@ test_test_translate_song_LDADD = \
endif endif
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 = \ test_test_queue_priority_SOURCES = \
src/queue/Queue.cxx \ src/queue/Queue.cxx \
src/DetachedSong.cxx \ src/DetachedSong.cxx \
......
...@@ -69,6 +69,14 @@ ver 0.19 (not yet released) ...@@ -69,6 +69,14 @@ ver 0.19 (not yet released)
* install systemd unit for socket activation * install systemd unit for socket activation
* Android port * Android port
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) ver 0.18.13 (2014/08/31)
* protocol * protocol
- don't change song on "seekcur" in random mode - don't change song on "seekcur" in random mode
......
...@@ -48,6 +48,7 @@ decoder_initialized(Decoder &decoder, ...@@ -48,6 +48,7 @@ decoder_initialized(Decoder &decoder,
assert(dc.state == DecoderState::START); assert(dc.state == DecoderState::START);
assert(dc.pipe != nullptr); assert(dc.pipe != nullptr);
assert(dc.pipe->IsEmpty());
assert(decoder.convert == nullptr); assert(decoder.convert == nullptr);
assert(decoder.stream_tag == nullptr); assert(decoder.stream_tag == nullptr);
assert(decoder.decoder_tag == nullptr); assert(decoder.decoder_tag == nullptr);
...@@ -461,6 +462,9 @@ decoder_data(Decoder &decoder, ...@@ -461,6 +462,9 @@ decoder_data(Decoder &decoder,
length == 0) length == 0)
return cmd; return cmd;
assert(!decoder.initial_seek_pending);
assert(!decoder.initial_seek_running);
/* send stream tags */ /* send stream tags */
if (update_stream_tag(decoder, is)) { if (update_stream_tag(decoder, is)) {
......
...@@ -85,6 +85,9 @@ Decoder::GetChunk() ...@@ -85,6 +85,9 @@ Decoder::GetChunk()
void void
Decoder::FlushChunk() Decoder::FlushChunk()
{ {
assert(!seeking);
assert(!initial_seek_running);
assert(!initial_seek_pending);
assert(chunk != nullptr); assert(chunk != nullptr);
if (chunk->IsEmpty()) if (chunk->IsEmpty())
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "DecoderPlugin.hxx" #include "DecoderPlugin.hxx"
#include "DetachedSong.hxx" #include "DetachedSong.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "MusicPipe.hxx"
#include "fs/Traits.hxx" #include "fs/Traits.hxx"
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
...@@ -449,9 +450,18 @@ decoder_task(void *arg) ...@@ -449,9 +450,18 @@ decoder_task(void *arg)
dc.replay_gain_prev_db = dc.replay_gain_db; dc.replay_gain_prev_db = dc.replay_gain_db;
dc.replay_gain_db = 0; dc.replay_gain_db = 0;
/* fall through */ decoder_run(dc);
break;
case DecoderCommand::SEEK: 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); decoder_run(dc);
break; break;
......
...@@ -412,10 +412,23 @@ ffmpeg_probe(Decoder *decoder, InputStream &is) ...@@ -412,10 +412,23 @@ ffmpeg_probe(Decoder *decoder, InputStream &is)
nbytes -= PADDING; nbytes -= PADDING;
AVProbeData avpd; 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 = buffer;
avpd.buf_size = nbytes; avpd.buf_size = nbytes;
avpd.filename = is.GetURI(); avpd.filename = is.GetURI();
#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); return av_probe_input_format(&avpd, true);
} }
......
...@@ -82,7 +82,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2, ...@@ -82,7 +82,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
/* compatibility with older MPD versions: specifying /* compatibility with older MPD versions: specifying
"-1" makes MPD display the whole list */ "-1" makes MPD display the whole list */
*value_r1 = 0; *value_r1 = 0;
*value_r2 = std::numeric_limits<unsigned>::max(); *value_r2 = std::numeric_limits<int>::max();
return true; return true;
} }
...@@ -109,7 +109,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2, ...@@ -109,7 +109,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
} }
if (test == test2) if (test == test2)
value = std::numeric_limits<unsigned>::max(); value = std::numeric_limits<int>::max();
if (value < 0) { if (value < 0) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG,
......
#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>
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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment