Commit a90685d6 authored by Max Kellermann's avatar Max Kellermann

Merge tag 'v0.21.12'

release v0.21.12
parents fe2f8c08 ae19bda1
...@@ -13,9 +13,16 @@ ver 0.22 (not yet released) ...@@ -13,9 +13,16 @@ ver 0.22 (not yet released)
- hdcd: new plugin based on FFmpeg's "af_hdcd" for HDCD playback - hdcd: new plugin based on FFmpeg's "af_hdcd" for HDCD playback
- volume: convert S16 to S24 to preserve quality and reduce dithering noise - volume: convert S16 to S24 to preserve quality and reduce dithering noise
ver 0.21.12 (not yet released) ver 0.21.12 (2019/08/03)
* decoder * decoder
- mad: update bit rate after seeking
- mad: fix several bugs preventing the plugin from decoding the last frame
- opus: ignore case in replay gain tag names - opus: ignore case in replay gain tag names
- opus, vorbis: decode the "end of stream" packet
* output
- jack: fix mono-to-stereo conversion
* player
- don't restart unseekable song after failed seek attempt
* Windows * Windows
- support backslash in relative URIs loaded from playlists - support backslash in relative URIs loaded from playlists
......
...@@ -15,6 +15,12 @@ version_cxx = vcs_tag(input: 'src/GitVersion.cxx', output: 'GitVersion.cxx') ...@@ -15,6 +15,12 @@ version_cxx = vcs_tag(input: 'src/GitVersion.cxx', output: 'GitVersion.cxx')
compiler = meson.get_compiler('cpp') compiler = meson.get_compiler('cpp')
c_compiler = meson.get_compiler('c') c_compiler = meson.get_compiler('c')
if compiler.get_id() == 'gcc' and compiler.version().version_compare('<6')
warning('Your GCC version is too old. You need at least version 6.')
elif compiler.get_id() == 'clang' and compiler.version().version_compare('<3')
warning('Your clang version is too old. You need at least version 3.')
endif
conf = configuration_data() conf = configuration_data()
conf.set_quoted('PACKAGE', meson.project_name()) conf.set_quoted('PACKAGE', meson.project_name())
conf.set_quoted('PACKAGE_NAME', meson.project_name()) conf.set_quoted('PACKAGE_NAME', meson.project_name())
......
...@@ -311,6 +311,11 @@ public: ...@@ -311,6 +311,11 @@ public:
bool IsCurrentSong(const DetachedSong &_song) const noexcept; bool IsCurrentSong(const DetachedSong &_song) const noexcept;
gcc_pure gcc_pure
bool IsUnseekableCurrentSong(const DetachedSong &_song) const noexcept {
return !seekable && IsCurrentSong(_song);
}
gcc_pure
bool IsSeekableCurrentSong(const DetachedSong &_song) const noexcept { bool IsSeekableCurrentSong(const DetachedSong &_song) const noexcept {
return seekable && IsCurrentSong(_song); return seekable && IsCurrentSong(_song);
} }
......
...@@ -69,12 +69,12 @@ OggVisitor::HandlePacket(const ogg_packet &packet) ...@@ -69,12 +69,12 @@ OggVisitor::HandlePacket(const ogg_packet &packet)
/* fail if BOS is missing */ /* fail if BOS is missing */
throw std::runtime_error("BOS packet expected"); throw std::runtime_error("BOS packet expected");
OnOggPacket(packet);
if (packet.e_o_s) { if (packet.e_o_s) {
EndStream(); EndStream();
return; return;
} }
OnOggPacket(packet);
} }
inline void inline void
......
...@@ -67,8 +67,21 @@ private: ...@@ -67,8 +67,21 @@ private:
void HandlePackets(); void HandlePackets();
protected: protected:
/**
* Called when the "beginning of stream" packet has been seen.
*
* @param packet the "beginning of stream" packet
*/
virtual void OnOggBeginning(const ogg_packet &packet) = 0; virtual void OnOggBeginning(const ogg_packet &packet) = 0;
/**
* Called for each follow-up packet.
*/
virtual void OnOggPacket(const ogg_packet &packet) = 0; virtual void OnOggPacket(const ogg_packet &packet) = 0;
/**
* Called after the "end of stream" packet has been processed.
*/
virtual void OnOggEnd() = 0; virtual void OnOggEnd() = 0;
}; };
......
...@@ -539,7 +539,7 @@ JackOutput::Start() ...@@ -539,7 +539,7 @@ JackOutput::Start()
std::fill(dports + num_dports, dports + audio_format.channels, std::fill(dports + num_dports, dports + audio_format.channels,
dports[0]); dports[0]);
} else if (num_dports > audio_format.channels) { } else if (num_dports > audio_format.channels) {
if (audio_format.channels == 1 && num_dports > 2) { if (audio_format.channels == 1 && num_dports >= 2) {
/* mono input file: connect the one source /* mono input file: connect the one source
channel to the both destination channels */ channel to the both destination channels */
duplicate_port = dports[1]; duplicate_port = dports[1];
......
...@@ -602,6 +602,19 @@ Player::SeekDecoder(std::unique_lock<Mutex> &lock) noexcept ...@@ -602,6 +602,19 @@ Player::SeekDecoder(std::unique_lock<Mutex> &lock) noexcept
{ {
assert(pc.next_song != nullptr); assert(pc.next_song != nullptr);
if (pc.seek_time > SongTime::zero() && // TODO: allow this only if the song duration is known
dc.IsUnseekableCurrentSong(*pc.next_song)) {
/* seeking into the current song; but we already know
it's not seekable, so let's fail early */
/* note the seek_time>0 check: if seeking to the
beginning, we can simply restart the decoder */
pc.next_song.reset();
pc.SetError(PlayerError::DECODER,
std::make_exception_ptr(std::runtime_error("Not seekable")));
pc.CommandFinished();
return true;
}
CancelPendingSeek(); CancelPendingSeek();
{ {
......
...@@ -57,18 +57,6 @@ ...@@ -57,18 +57,6 @@
(GCC_VERSION > 0 && CLANG_VERSION == 0 && \ (GCC_VERSION > 0 && CLANG_VERSION == 0 && \
GCC_VERSION < GCC_MAKE_VERSION(major, minor, 0)) GCC_VERSION < GCC_MAKE_VERSION(major, minor, 0))
#ifdef __clang__
# if __clang_major__ < 3
# error Sorry, your clang version is too old. You need at least version 3.1.
# endif
#elif defined(__GNUC__)
# if GCC_OLDER_THAN(6,0)
# error Sorry, your gcc version is too old. You need at least version 6.0.
# endif
#else
# warning Untested compiler. Use at your own risk!
#endif
/** /**
* Are we building with the specified version of clang or newer? * Are we building with the specified version of clang or newer?
*/ */
......
...@@ -56,11 +56,11 @@ protected: ...@@ -56,11 +56,11 @@ protected:
T data[size]; T data[size];
public: public:
constexpr size_type GetCapacity() const { constexpr size_type GetCapacity() const noexcept {
return size; return size;
} }
void Shift() { void Shift() noexcept {
if (head == 0) if (head == 0)
return; return;
...@@ -74,15 +74,15 @@ public: ...@@ -74,15 +74,15 @@ public:
head = 0; head = 0;
} }
void Clear() { void Clear() noexcept {
head = tail = 0; head = tail = 0;
} }
bool empty() const { constexpr bool empty() const noexcept {
return head == tail; return head == tail;
} }
bool IsFull() const { constexpr bool IsFull() const noexcept {
return head == 0 && tail == size; return head == 0 && tail == size;
} }
...@@ -90,7 +90,7 @@ public: ...@@ -90,7 +90,7 @@ public:
* Prepares writing. Returns a buffer range which may be written. * Prepares writing. Returns a buffer range which may be written.
* When you are finished, call Append(). * When you are finished, call Append().
*/ */
Range Write() { Range Write() noexcept {
if (empty()) if (empty())
Clear(); Clear();
else if (tail == size) else if (tail == size)
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
* Expands the tail of the buffer, after data has been written to * Expands the tail of the buffer, after data has been written to
* the buffer returned by Write(). * the buffer returned by Write().
*/ */
void Append(size_type n) { void Append(size_type n) noexcept {
assert(tail <= size); assert(tail <= size);
assert(n <= size); assert(n <= size);
assert(tail + n <= size); assert(tail + n <= size);
...@@ -111,18 +111,22 @@ public: ...@@ -111,18 +111,22 @@ public:
tail += n; tail += n;
} }
constexpr size_type GetAvailable() const noexcept {
return tail - head;
}
/** /**
* Return a buffer range which may be read. The buffer pointer is * Return a buffer range which may be read. The buffer pointer is
* writable, to allow modifications while parsing. * writable, to allow modifications while parsing.
*/ */
Range Read() { constexpr Range Read() noexcept {
return Range(data + head, tail - head); return Range(data + head, tail - head);
} }
/** /**
* Marks a chunk as consumed. * Marks a chunk as consumed.
*/ */
void Consume(size_type n) { void Consume(size_type n) noexcept {
assert(tail <= size); assert(tail <= size);
assert(head <= tail); assert(head <= tail);
assert(n <= tail); assert(n <= tail);
......
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