diff --git a/Makefile.am b/Makefile.am index 5b5caa766..030455ca2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -527,6 +527,7 @@ libthread_a_SOURCES = \ libnet_a_SOURCES = \ src/net/Features.hxx \ + src/net/Init.hxx \ src/net/ToString.cxx src/net/ToString.hxx \ src/net/Resolver.cxx src/net/Resolver.hxx \ src/net/StaticSocketAddress.cxx src/net/StaticSocketAddress.hxx \ diff --git a/NEWS b/NEWS index 72db01fc4..ba44df990 100644 --- a/NEWS +++ b/NEWS @@ -26,10 +26,14 @@ ver 0.21 (not yet released) - sndio: new mixer plugin * require GCC 5.0 -ver 0.20.18 (not yet released) +ver 0.20.18 (2018/02/24) +* input + - curl: allow authentication methods other than "Basic" * decoder - flac: improve seeking precision * fix gapless CUE song transitions +* Android, Windows + - enable the NFS storage plugin ver 0.20.17 (2018/02/11) * output diff --git a/android/build.py b/android/build.py index 3e2e71dcc..4c4f77ae7 100755 --- a/android/build.py +++ b/android/build.py @@ -124,9 +124,9 @@ thirdparty_libs = [ opus, flac, libid3tag, - libmad, ffmpeg, curl, + libnfs, boost, ] diff --git a/python/build/autotools.py b/python/build/autotools.py index 58d5d8c54..9abd418ff 100644 --- a/python/build/autotools.py +++ b/python/build/autotools.py @@ -5,6 +5,7 @@ from build.makeproject import MakeProject class AutotoolsProject(MakeProject): def __init__(self, url, md5, installed, configure_args=[], autogen=False, + autoreconf=False, cppflags='', ldflags='', libs='', @@ -13,6 +14,7 @@ class AutotoolsProject(MakeProject): MakeProject.__init__(self, url, md5, installed, **kwargs) self.configure_args = configure_args self.autogen = autogen + self.autoreconf = autoreconf self.cppflags = cppflags self.ldflags = ldflags self.libs = libs @@ -28,6 +30,8 @@ class AutotoolsProject(MakeProject): subprocess.check_call(['aclocal'], cwd=src) subprocess.check_call(['automake', '--add-missing', '--force-missing', '--foreign'], cwd=src) subprocess.check_call(['autoconf'], cwd=src) + if self.autoreconf: + subprocess.check_call(['autoreconf', '-vif'], cwd=src) build = self.make_build_path(toolchain) diff --git a/python/build/libs.py b/python/build/libs.py index 7d93799d8..4cbab63ee 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -100,8 +100,8 @@ liblame = AutotoolsProject( ) ffmpeg = FfmpegProject( - 'http://ffmpeg.org/releases/ffmpeg-3.4.1.tar.xz', - '5a77278a63741efa74e26bf197b9bb09ac6381b9757391b922407210f0f991c0', + 'http://ffmpeg.org/releases/ffmpeg-3.4.2.tar.xz', + '2b92e9578ef8b3e49eeab229e69305f5f4cbc1fdaa22e927fc7fca18acccd740', 'lib/libavcodec.a', [ '--disable-shared', '--enable-static', @@ -124,7 +124,6 @@ ffmpeg = FfmpegProject( '--disable-protocols', '--disable-devices', '--disable-filters', - '--disable-filters', '--disable-v4l2_m2m', '--disable-parser=bmp', @@ -142,7 +141,6 @@ ffmpeg = FfmpegProject( '--disable-parser=mjpeg', '--disable-parser=mlp', '--disable-parser=mpeg4video', - '--disable-parser=mpegaudio', '--disable-parser=mpegvideo', '--disable-parser=opus', '--disable-parser=vc1', @@ -194,16 +192,6 @@ ffmpeg = FfmpegProject( # we don't need these decoders, because we have the dedicated # libraries '--disable-decoder=flac', - '--disable-decoder=mp1', - '--disable-decoder=mp1float', - '--disable-decoder=mp2', - '--disable-decoder=mp2float', - '--disable-decoder=mp3', - '--disable-decoder=mp3adu', - '--disable-decoder=mp3adufloat', - '--disable-decoder=mp3float', - '--disable-decoder=mp3on4', - '--disable-decoder=mp3on4float', '--disable-decoder=opus', '--disable-decoder=vorbis', @@ -317,7 +305,7 @@ ffmpeg = FfmpegProject( '--disable-decoder=svq1', '--disable-decoder=svq3', '--disable-decoder=tiff', - '--disable-decoder=mottiertexseqvideo', + '--disable-decoder=tiertexseqvideo', '--disable-decoder=truemotion1', '--disable-decoder=truemotion2', '--disable-decoder=truemotion2rt', @@ -364,6 +352,21 @@ curl = AutotoolsProject( patches='src/lib/curl/patches', ) +libnfs = AutotoolsProject( + 'https://github.com/sahlberg/libnfs/archive/libnfs-2.0.0.tar.gz', + '7ea6cd8fa6c461d01091e584d424d28e137d23ff4b65b95d01a3fd0ef95d120e', + 'lib/libnfs.a', + [ + '--disable-shared', '--enable-static', + '--disable-debug', + + # work around -Wtautological-compare + '--disable-werror', + ], + base='libnfs-libnfs-2.0.0', + autoreconf=True, +) + boost = BoostProject( 'http://downloads.sourceforge.net/project/boost/boost/1.66.0/boost_1_66_0.tar.bz2', '5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9', diff --git a/src/Main.cxx b/src/Main.cxx index f4477aa13..fce8dc06e 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -50,6 +50,7 @@ #include "unix/SignalHandlers.hxx" #include "system/FatalError.hxx" #include "thread/Slack.hxx" +#include "net/Init.hxx" #include "lib/icu/Init.hxx" #include "config/ConfigGlobal.hxx" #include "config/Param.hxx" @@ -106,11 +107,6 @@ #include #endif -#ifdef _WIN32 -#include -#include -#endif - #ifdef __BLOCKS__ #include #endif @@ -286,25 +282,6 @@ glue_state_file_init() instance->state_file->Read(); } -/** - * Windows-only initialization of the Winsock2 library. - */ -static void winsock_init(void) -{ -#ifdef _WIN32 - WSADATA sockinfo; - - int retval = WSAStartup(MAKEWORD(2, 2), &sockinfo); - if(retval != 0) - FormatFatalError("Attempt to open Winsock2 failed; error code %d", - retval); - - if (LOBYTE(sockinfo.wVersion) != 2) - FatalError("We use Winsock2 but your version is either too new " - "or old; please install Winsock 2.x"); -#endif -} - /** * Initialize the decoder and player core, including the music pipe. */ @@ -504,7 +481,8 @@ try { IcuInit(); - winsock_init(); + const ScopeNetInit net_init; + config_global_init(); #ifdef ANDROID @@ -749,10 +727,6 @@ try { daemonize_finish(); #endif -#ifdef _WIN32 - WSACleanup(); -#endif - IcuFinish(); log_deinit(); diff --git a/src/lib/curl/Request.cxx b/src/lib/curl/Request.cxx index 0a0dc2256..a9a61de98 100644 --- a/src/lib/curl/Request.cxx +++ b/src/lib/curl/Request.cxx @@ -64,6 +64,7 @@ CurlRequest::CurlRequest(CurlGlobal &_global, easy.SetOption(CURLOPT_NOPROGRESS, 1l); easy.SetOption(CURLOPT_NOSIGNAL, 1l); easy.SetOption(CURLOPT_CONNECTTIMEOUT, 10l); + easy.SetOption(CURLOPT_HTTPAUTH, (long) CURLAUTH_ANY); } CurlRequest::~CurlRequest() noexcept diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index 15b73224a..2afcf094c 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -31,7 +31,11 @@ extern "C" { #include +#ifdef _WIN32 +#include +#else #include /* for POLLIN, POLLOUT */ +#endif static constexpr std::chrono::steady_clock::duration NFS_MOUNT_TIMEOUT = std::chrono::minutes(1); diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 984f5518d..82ce39152 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -30,7 +30,6 @@ #include #include #include -#include NfsFileReader::NfsFileReader() noexcept :defer_open(nfs_get_event_loop(), BIND_THIS_METHOD(OnDeferredOpen)) diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx index 18d0cf1c3..8447036d4 100644 --- a/src/lib/nfs/FileReader.hxx +++ b/src/lib/nfs/FileReader.hxx @@ -31,6 +31,7 @@ #include #include +#include struct nfsfh; class NfsConnection; diff --git a/src/net/Init.hxx b/src/net/Init.hxx new file mode 100644 index 000000000..9e4581438 --- /dev/null +++ b/src/net/Init.hxx @@ -0,0 +1,46 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef NET_INIT_HXX +#define NET_INIT_HXX + +#include "check.h" +#include "SocketError.hxx" + +#ifdef _WIN32 +#include +#endif + +class ScopeNetInit { +#ifdef _WIN32 +public: + ScopeNetInit() { + WSADATA sockinfo; + int retval = WSAStartup(MAKEWORD(2, 2), &sockinfo); + if (retval != 0) + throw MakeSocketError(retval, "WSAStartup() failed"); + } + + ~ScopeNetInit() noexcept { + WSACleanup(); + } +#endif +}; + +#endif diff --git a/src/playlist/cue/CueParser.cxx b/src/playlist/cue/CueParser.cxx index c5dc4dc1b..2bd1aa4b0 100644 --- a/src/playlist/cue/CueParser.cxx +++ b/src/playlist/cue/CueParser.cxx @@ -229,6 +229,7 @@ CueParser::Feed2(char *p) noexcept } state = TRACK; + ignore_index = false; current = std::make_unique(filename); assert(!current->GetTag().IsDefined()); @@ -238,6 +239,9 @@ CueParser::Feed2(char *p) noexcept } else if (state == IGNORE_TRACK) { return; } else if (state == TRACK && strcmp(command, "INDEX") == 0) { + if (ignore_index) + return; + const char *nr = cue_next_token(&p); if (nr == nullptr) return; @@ -255,7 +259,7 @@ CueParser::Feed2(char *p) noexcept current->SetStartTime(SongTime::FromMS(position_ms)); if(strcmp(nr, "00") != 0 || previous == nullptr) - state = IGNORE_TRACK; + ignore_index = true; } } diff --git a/src/playlist/cue/CueParser.hxx b/src/playlist/cue/CueParser.hxx index be89a543e..9f8984aa6 100644 --- a/src/playlist/cue/CueParser.hxx +++ b/src/playlist/cue/CueParser.hxx @@ -87,6 +87,13 @@ class CueParser { */ std::unique_ptr finished; + /** + * Ignore "INDEX" lines? Only up the first one after "00" is + * used. If there is a pregap (INDEX 00..01), it is assigned + * to the previous song. + */ + bool ignore_index; + /** * Tracks whether Finish() has been called. If true, then all * remaining (partial) results will be delivered by Get(). diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx index 49a2adca1..b615ee200 100644 --- a/src/storage/plugins/NfsStorage.cxx +++ b/src/storage/plugins/NfsStorage.cxx @@ -222,7 +222,12 @@ UriToNfsPath(const char *_uri_utf8) std::string uri_utf8("/"); uri_utf8.append(_uri_utf8); +#ifdef _WIN32 + /* assume UTF-8 when accessing NFS from Windows */ + return uri_utf8; +#else return AllocatedPath::FromUTF8Throw(uri_utf8.c_str()).Steal(); +#endif } std::string @@ -294,7 +299,7 @@ NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow) gcc_pure static bool -SkipNameFS(const char *name) noexcept +SkipNameFS(PathTraitsFS::const_pointer_type name) noexcept { return name[0] == '.' && (name[1] == 0 || @@ -362,7 +367,14 @@ NfsListDirectoryOperation::CollectEntries(struct nfsdir *dir) const struct nfsdirent *ent; while ((ent = connection.ReadDirectory(dir)) != nullptr) { +#ifdef _WIN32 + /* assume UTF-8 when accessing NFS from Windows */ + const auto name_fs = AllocatedPath::FromUTF8Throw(ent->name); + if (name_fs.IsNull()) + continue; +#else const Path name_fs = Path::FromFS(ent->name); +#endif if (SkipNameFS(name_fs.c_str())) continue; diff --git a/test/run_storage.cxx b/test/run_storage.cxx index 3d987f541..1ab8d625d 100644 --- a/test/run_storage.cxx +++ b/test/run_storage.cxx @@ -23,6 +23,7 @@ #include "storage/Registry.hxx" #include "storage/StorageInterface.hxx" #include "storage/FileInfo.hxx" +#include "net/Init.hxx" #include "util/ChronoUtil.hxx" #include @@ -72,7 +73,12 @@ Ls(Storage &storage, const char *path) const char *mtime = " "; if (!IsNegative(info.mtime)) { time_t t = std::chrono::system_clock::to_time_t(info.mtime); - strftime(mtime_buffer, sizeof(mtime_buffer), "%F", + strftime(mtime_buffer, sizeof(mtime_buffer), +#ifdef _WIN32 + "%Y-%m-%d", +#else + "%F", +#endif gmtime(&t)); mtime = mtime_buffer; } @@ -96,6 +102,7 @@ try { const char *const command = argv[1]; const char *const storage_uri = argv[2]; + const ScopeNetInit net_init; EventThread io_thread; io_thread.Start(); diff --git a/win32/build.py b/win32/build.py index 45c5dfa4c..38cc9c271 100755 --- a/win32/build.py +++ b/win32/build.py @@ -58,7 +58,8 @@ class CrossGccToolchain: self.cflags = common_flags self.cxxflags = common_flags - self.cppflags = '-isystem ' + os.path.join(install_prefix, 'include') + self.cppflags = '-isystem ' + os.path.join(install_prefix, 'include') + \ + ' -DWINVER=0x0600 -D_WIN32_WINNT=0x0600' self.ldflags = '-L' + os.path.join(install_prefix, 'lib') self.libs = '' @@ -84,6 +85,7 @@ thirdparty_libs = [ liblame, ffmpeg, curl, + libnfs, boost, ]