You need to sign in or sign up before continuing.
Commit df4af2b5 authored by Max Kellermann's avatar Max Kellermann

Merge tag 'v0.20.4'

release v0.20.4
parents 97132e3d 0a033fb1
ver 0.21 (not yet released) ver 0.21 (not yet released)
ver 0.20.4 (2017/02/01)
* input
- nfs: fix freeze after reconnect
* output
- sndio: work around a libroar C++ incompatibility
* workaround for GCC 4.9 "constexpr" bug
* fix FreeBSD build failure
ver 0.20.3 (2017/01/25) ver 0.20.3 (2017/01/25)
* protocol * protocol
- "playlistadd" creates new playlist if it does not exist, as documented - "playlistadd" creates new playlist if it does not exist, as documented
......
...@@ -19,8 +19,8 @@ libvorbis = AutotoolsProject( ...@@ -19,8 +19,8 @@ libvorbis = AutotoolsProject(
) )
opus = AutotoolsProject( opus = AutotoolsProject(
'http://downloads.xiph.org/releases/opus/opus-1.1.3.tar.gz', 'http://downloads.xiph.org/releases/opus/opus-1.1.4.tar.gz',
'32bbb6b557fe1b6066adc0ae1f08b629', '9122b6b380081dd2665189f97bfd777f04f92dc3ab6698eea1dbb27ad59d8692',
'lib/libopus.a', 'lib/libopus.a',
['--disable-shared', '--enable-static'], ['--disable-shared', '--enable-static'],
) )
......
...@@ -62,7 +62,7 @@ Print(Response &r, TagType group, const TagCountMap &m) ...@@ -62,7 +62,7 @@ Print(Response &r, TagType group, const TagCountMap &m)
} }
} }
static bool static void
stats_visitor_song(SearchStats &stats, const LightSong &song) stats_visitor_song(SearchStats &stats, const LightSong &song)
{ {
stats.n_songs++; stats.n_songs++;
...@@ -70,8 +70,6 @@ stats_visitor_song(SearchStats &stats, const LightSong &song) ...@@ -70,8 +70,6 @@ stats_visitor_song(SearchStats &stats, const LightSong &song)
const auto duration = song.GetDuration(); const auto duration = song.GetDuration();
if (!duration.IsNegative()) if (!duration.IsNegative())
stats.total_duration += duration; stats.total_duration += duration;
return true;
} }
static bool static bool
...@@ -94,7 +92,7 @@ CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag) ...@@ -94,7 +92,7 @@ CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag)
return found; return found;
} }
static bool static void
GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song) GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
{ {
assert(song.tag != nullptr); assert(song.tag != nullptr);
...@@ -103,8 +101,6 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song) ...@@ -103,8 +101,6 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
if (!CollectGroupCounts(map, group, tag) && group == TAG_ALBUM_ARTIST) if (!CollectGroupCounts(map, group, tag) && group == TAG_ALBUM_ARTIST)
/* fall back to "Artist" if no "AlbumArtist" was found */ /* fall back to "Artist" if no "AlbumArtist" was found */
CollectGroupCounts(map, TAG_ARTIST, tag); CollectGroupCounts(map, TAG_ARTIST, tag);
return true;
} }
void void
......
...@@ -27,13 +27,12 @@ ...@@ -27,13 +27,12 @@
#include <functional> #include <functional>
static bool static void
AddSong(const Storage &storage, const char *playlist_path_utf8, AddSong(const Storage &storage, const char *playlist_path_utf8,
const LightSong &song) const LightSong &song)
{ {
spl_append_song(playlist_path_utf8, spl_append_song(playlist_path_utf8,
DatabaseDetachSong(storage, song)); DatabaseDetachSong(storage, song));
return true;
} }
void void
......
...@@ -49,16 +49,14 @@ PrintDirectoryURI(Response &r, bool base, const LightDirectory &directory) ...@@ -49,16 +49,14 @@ PrintDirectoryURI(Response &r, bool base, const LightDirectory &directory)
ApplyBaseFlag(directory.GetPath(), base)); ApplyBaseFlag(directory.GetPath(), base));
} }
static bool static void
PrintDirectoryBrief(Response &r, bool base, const LightDirectory &directory) PrintDirectoryBrief(Response &r, bool base, const LightDirectory &directory)
{ {
if (!directory.IsRoot()) if (!directory.IsRoot())
PrintDirectoryURI(r, base, directory); PrintDirectoryURI(r, base, directory);
return true;
} }
static bool static void
PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory) PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory)
{ {
if (!directory.IsRoot()) { if (!directory.IsRoot()) {
...@@ -67,8 +65,6 @@ PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory) ...@@ -67,8 +65,6 @@ PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory)
if (directory.mtime > 0) if (directory.mtime > 0)
time_print(r, "Last-Modified", directory.mtime); time_print(r, "Last-Modified", directory.mtime);
} }
return true;
} }
static void static void
...@@ -96,7 +92,7 @@ print_playlist_in_directory(Response &r, bool base, ...@@ -96,7 +92,7 @@ print_playlist_in_directory(Response &r, bool base,
directory->GetPath(), name_utf8); directory->GetPath(), name_utf8);
} }
static bool static void
PrintSongBrief(Response &r, Partition &partition, PrintSongBrief(Response &r, Partition &partition,
bool base, const LightSong &song) bool base, const LightSong &song)
{ {
...@@ -106,11 +102,9 @@ PrintSongBrief(Response &r, Partition &partition, ...@@ -106,11 +102,9 @@ PrintSongBrief(Response &r, Partition &partition,
/* this song file has an embedded CUE sheet */ /* this song file has an embedded CUE sheet */
print_playlist_in_directory(r, base, print_playlist_in_directory(r, base,
song.directory, song.uri); song.directory, song.uri);
return true;
} }
static bool static void
PrintSongFull(Response &r, Partition &partition, PrintSongFull(Response &r, Partition &partition,
bool base, const LightSong &song) bool base, const LightSong &song)
{ {
...@@ -120,21 +114,18 @@ PrintSongFull(Response &r, Partition &partition, ...@@ -120,21 +114,18 @@ PrintSongFull(Response &r, Partition &partition,
/* this song file has an embedded CUE sheet */ /* this song file has an embedded CUE sheet */
print_playlist_in_directory(r, base, print_playlist_in_directory(r, base,
song.directory, song.uri); song.directory, song.uri);
return true;
} }
static bool static void
PrintPlaylistBrief(Response &r, bool base, PrintPlaylistBrief(Response &r, bool base,
const PlaylistInfo &playlist, const PlaylistInfo &playlist,
const LightDirectory &directory) const LightDirectory &directory)
{ {
print_playlist_in_directory(r, base, print_playlist_in_directory(r, base,
&directory, playlist.name.c_str()); &directory, playlist.name.c_str());
return true;
} }
static bool static void
PrintPlaylistFull(Response &r, bool base, PrintPlaylistFull(Response &r, bool base,
const PlaylistInfo &playlist, const PlaylistInfo &playlist,
const LightDirectory &directory) const LightDirectory &directory)
...@@ -144,8 +135,6 @@ PrintPlaylistFull(Response &r, bool base, ...@@ -144,8 +135,6 @@ PrintPlaylistFull(Response &r, bool base,
if (playlist.mtime > 0) if (playlist.mtime > 0)
time_print(r, "Last-Modified", playlist.mtime); time_print(r, "Last-Modified", playlist.mtime);
return true;
} }
void void
...@@ -191,15 +180,13 @@ db_selection_print(Response &r, Partition &partition, ...@@ -191,15 +180,13 @@ db_selection_print(Response &r, Partition &partition,
0, std::numeric_limits<int>::max()); 0, std::numeric_limits<int>::max());
} }
static bool static void
PrintSongURIVisitor(Response &r, Partition &partition, const LightSong &song) PrintSongURIVisitor(Response &r, Partition &partition, const LightSong &song)
{ {
song_print_uri(r, partition, song); song_print_uri(r, partition, song);
return true;
} }
static bool static void
PrintUniqueTag(Response &r, TagType tag_type, PrintUniqueTag(Response &r, TagType tag_type,
const Tag &tag) const Tag &tag)
{ {
...@@ -211,8 +198,6 @@ PrintUniqueTag(Response &r, TagType tag_type, ...@@ -211,8 +198,6 @@ PrintUniqueTag(Response &r, TagType tag_type,
if (item.type != tag_type) if (item.type != tag_type)
r.Format("%s: %s\n", r.Format("%s: %s\n",
tag_item_names[item.type], item.value); tag_item_names[item.type], item.value);
return true;
} }
void void
......
...@@ -27,14 +27,13 @@ ...@@ -27,14 +27,13 @@
#include <functional> #include <functional>
static bool static void
AddToQueue(Partition &partition, const LightSong &song) AddToQueue(Partition &partition, const LightSong &song)
{ {
const Storage &storage = *partition.instance.storage; const Storage &storage = *partition.instance.storage;
partition.playlist.AppendSong(partition.pc, partition.playlist.AppendSong(partition.pc,
DatabaseDetachSong(storage, DatabaseDetachSong(storage,
song)); song));
return true;
} }
void void
......
...@@ -67,15 +67,13 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums, ...@@ -67,15 +67,13 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
} }
} }
static bool static void
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums, StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
const LightSong &song) const LightSong &song)
{ {
++stats.song_count; ++stats.song_count;
StatsVisitTag(stats, artists, albums, *song.tag); StatsVisitTag(stats, artists, albums, *song.tag);
return true;
} }
DatabaseStats DatabaseStats
......
...@@ -396,6 +396,17 @@ NfsConnection::ScheduleSocket() ...@@ -396,6 +396,17 @@ NfsConnection::ScheduleSocket()
assert(GetEventLoop().IsInside()); assert(GetEventLoop().IsInside());
assert(context != nullptr); assert(context != nullptr);
const int which_events = nfs_which_events(context);
if (which_events == POLLOUT && SocketMonitor::IsDefined())
/* kludge: if libnfs asks only for POLLOUT, it means
that it is currently waiting for the connect() to
finish - rpc_reconnect_requeue() may have been
called from inside nfs_service(); we must now
unregister the old socket and register the new one
instead */
SocketMonitor::Steal();
if (!SocketMonitor::IsDefined()) { if (!SocketMonitor::IsDefined()) {
int _fd = nfs_get_fd(context); int _fd = nfs_get_fd(context);
if (_fd < 0) if (_fd < 0)
...@@ -405,7 +416,8 @@ NfsConnection::ScheduleSocket() ...@@ -405,7 +416,8 @@ NfsConnection::ScheduleSocket()
SocketMonitor::Open(_fd); SocketMonitor::Open(_fd);
} }
SocketMonitor::Schedule(libnfs_to_events(nfs_which_events(context))); SocketMonitor::Schedule(libnfs_to_events(which_events)
| SocketMonitor::HANGUP);
} }
inline int inline int
...@@ -442,10 +454,14 @@ NfsConnection::OnSocketReady(unsigned flags) ...@@ -442,10 +454,14 @@ NfsConnection::OnSocketReady(unsigned flags)
bool closed = false; bool closed = false;
const bool was_mounted = mount_finished; const bool was_mounted = mount_finished;
if (!mount_finished) if (!mount_finished || (flags & SocketMonitor::HANGUP) != 0)
/* until the mount is finished, the NFS client may use /* until the mount is finished, the NFS client may use
various sockets, therefore we unregister and various sockets, therefore we unregister and
re-register it each time */ re-register it each time */
/* also re-register the socket if we got a HANGUP,
which is a sure sign that libnfs will close the
socket, which can lead to a race condition if
epoll_ctl() is called later */
SocketMonitor::Steal(); SocketMonitor::Steal();
const int result = Service(flags); const int result = Service(flags);
......
...@@ -24,8 +24,16 @@ ...@@ -24,8 +24,16 @@
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
/* work around a C++ incompatibility if the sndio API is emulated by
libroar: libroar's "struct roar_service_stream" has a member named
"new", which is an illegal identifier in C++ */
#define new new_
#include <sndio.h> #include <sndio.h>
/* undo the libroar workaround */
#undef new
#include <stdexcept> #include <stdexcept>
#ifndef SIO_DEVANY #ifndef SIO_DEVANY
......
...@@ -64,7 +64,10 @@ enum class SampleFormat : uint8_t { ...@@ -64,7 +64,10 @@ enum class SampleFormat : uint8_t {
/** /**
* Checks whether the sample format is valid. * Checks whether the sample format is valid.
*/ */
static constexpr inline bool #if !GCC_OLDER_THAN(5,0)
constexpr
#endif
static inline bool
audio_valid_sample_format(SampleFormat format) audio_valid_sample_format(SampleFormat format)
{ {
switch (format) { switch (format) {
...@@ -83,7 +86,10 @@ audio_valid_sample_format(SampleFormat format) ...@@ -83,7 +86,10 @@ audio_valid_sample_format(SampleFormat format)
return false; return false;
} }
static constexpr inline unsigned #if !GCC_OLDER_THAN(5,0)
constexpr
#endif
static inline unsigned
sample_format_size(SampleFormat format) sample_format_size(SampleFormat format)
{ {
switch (format) { switch (format) {
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <new> #include <new>
#include <cstdlib>
/** /**
* Allocate and construct a variable-size object. That is useful for * Allocate and construct a variable-size object. That is useful for
......
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