aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AudioConfig.cxx6
-rw-r--r--src/AudioConfig.hxx2
-rw-r--r--src/AudioFormat.cxx2
-rw-r--r--src/AudioFormat.hxx2
-rw-r--r--src/AudioParser.cxx2
-rw-r--r--src/AudioParser.hxx2
-rw-r--r--src/BulkEdit.hxx2
-rw-r--r--src/CheckAudioFormat.cxx2
-rw-r--r--src/CheckAudioFormat.hxx2
-rw-r--r--src/Chrono.hxx4
-rw-r--r--src/CommandLine.cxx89
-rw-r--r--src/CommandLine.hxx2
-rw-r--r--src/Compiler.h26
-rw-r--r--src/CrossFade.cxx2
-rw-r--r--src/CrossFade.hxx2
-rw-r--r--src/DetachedSong.cxx2
-rw-r--r--src/DetachedSong.hxx3
-rw-r--r--src/GlobalEvents.cxx2
-rw-r--r--src/GlobalEvents.hxx2
-rw-r--r--src/IOThread.cxx2
-rw-r--r--src/IOThread.hxx2
-rw-r--r--src/IcyMetaDataParser.cxx2
-rw-r--r--src/IcyMetaDataParser.hxx2
-rw-r--r--src/Idle.cxx2
-rw-r--r--src/Idle.hxx2
-rw-r--r--src/Instance.cxx5
-rw-r--r--src/Instance.hxx2
-rw-r--r--src/Listen.cxx8
-rw-r--r--src/Listen.hxx2
-rw-r--r--src/Log.cxx2
-rw-r--r--src/Log.hxx2
-rw-r--r--src/LogBackend.cxx2
-rw-r--r--src/LogBackend.hxx2
-rw-r--r--src/LogInit.cxx18
-rw-r--r--src/LogInit.hxx2
-rw-r--r--src/LogLevel.hxx2
-rw-r--r--src/LogV.hxx2
-rw-r--r--src/Main.cxx69
-rw-r--r--src/Main.hxx2
-rw-r--r--src/Mapper.cxx2
-rw-r--r--src/Mapper.hxx2
-rw-r--r--src/MixRampInfo.hxx2
-rw-r--r--src/MusicBuffer.cxx2
-rw-r--r--src/MusicBuffer.hxx2
-rw-r--r--src/MusicChunk.cxx2
-rw-r--r--src/MusicChunk.hxx2
-rw-r--r--src/MusicPipe.cxx2
-rw-r--r--src/MusicPipe.hxx2
-rw-r--r--src/Partition.cxx2
-rw-r--r--src/Partition.hxx2
-rw-r--r--src/Permission.cxx8
-rw-r--r--src/Permission.hxx2
-rw-r--r--src/PlayerControl.cxx2
-rw-r--r--src/PlayerControl.hxx2
-rw-r--r--src/PlayerListener.hxx2
-rw-r--r--src/PlayerThread.cxx2
-rw-r--r--src/PlayerThread.hxx2
-rw-r--r--src/PlaylistDatabase.cxx2
-rw-r--r--src/PlaylistDatabase.hxx2
-rw-r--r--src/PlaylistError.cxx2
-rw-r--r--src/PlaylistError.hxx2
-rw-r--r--src/PlaylistFile.cxx9
-rw-r--r--src/PlaylistFile.hxx2
-rw-r--r--src/PlaylistGlobal.cxx2
-rw-r--r--src/PlaylistGlobal.hxx2
-rw-r--r--src/PlaylistPrint.cxx2
-rw-r--r--src/PlaylistPrint.hxx2
-rw-r--r--src/PlaylistSave.cxx2
-rw-r--r--src/PlaylistSave.hxx2
-rw-r--r--src/ReplayGainConfig.cxx14
-rw-r--r--src/ReplayGainConfig.hxx2
-rw-r--r--src/ReplayGainInfo.cxx2
-rw-r--r--src/ReplayGainInfo.hxx10
-rw-r--r--src/SongFilter.cxx2
-rw-r--r--src/SongFilter.hxx2
-rw-r--r--src/SongLoader.cxx2
-rw-r--r--src/SongLoader.hxx2
-rw-r--r--src/SongPrint.cxx7
-rw-r--r--src/SongPrint.hxx2
-rw-r--r--src/SongSave.cxx2
-rw-r--r--src/SongSave.hxx2
-rw-r--r--src/SongUpdate.cxx2
-rw-r--r--src/StateFile.cxx2
-rw-r--r--src/StateFile.hxx2
-rw-r--r--src/Stats.cxx2
-rw-r--r--src/Stats.hxx2
-rw-r--r--src/TagFile.cxx2
-rw-r--r--src/TagFile.hxx2
-rw-r--r--src/TagPrint.cxx9
-rw-r--r--src/TagPrint.hxx2
-rw-r--r--src/TagSave.cxx2
-rw-r--r--src/TagSave.hxx2
-rw-r--r--src/TagStream.cxx2
-rw-r--r--src/TagStream.hxx2
-rw-r--r--src/TimePrint.cxx2
-rw-r--r--src/TimePrint.hxx2
-rw-r--r--src/android/Context.cxx2
-rw-r--r--src/android/Context.hxx2
-rw-r--r--src/android/Environment.cxx2
-rw-r--r--src/android/Environment.hxx2
-rw-r--r--src/archive/ArchiveDomain.cxx2
-rw-r--r--src/archive/ArchiveDomain.hxx2
-rw-r--r--src/archive/ArchiveFile.hxx2
-rw-r--r--src/archive/ArchiveList.cxx8
-rw-r--r--src/archive/ArchiveList.hxx2
-rw-r--r--src/archive/ArchiveLookup.cxx2
-rw-r--r--src/archive/ArchiveLookup.hxx2
-rw-r--r--src/archive/ArchivePlugin.cxx2
-rw-r--r--src/archive/ArchivePlugin.hxx2
-rw-r--r--src/archive/ArchiveVisitor.hxx2
-rw-r--r--src/archive/plugins/Bzip2ArchivePlugin.cxx4
-rw-r--r--src/archive/plugins/Bzip2ArchivePlugin.hxx2
-rw-r--r--src/archive/plugins/Iso9660ArchivePlugin.cxx2
-rw-r--r--src/archive/plugins/Iso9660ArchivePlugin.hxx2
-rw-r--r--src/archive/plugins/ZzipArchivePlugin.cxx2
-rw-r--r--src/archive/plugins/ZzipArchivePlugin.hxx2
-rw-r--r--src/check.h2
-rw-r--r--src/client/Client.cxx2
-rw-r--r--src/client/Client.hxx2
-rw-r--r--src/client/ClientEvent.cxx2
-rw-r--r--src/client/ClientExpire.cxx2
-rw-r--r--src/client/ClientFile.cxx2
-rw-r--r--src/client/ClientGlobal.cxx8
-rw-r--r--src/client/ClientIdle.cxx2
-rw-r--r--src/client/ClientInternal.hxx2
-rw-r--r--src/client/ClientList.cxx2
-rw-r--r--src/client/ClientList.hxx2
-rw-r--r--src/client/ClientMessage.cxx2
-rw-r--r--src/client/ClientMessage.hxx2
-rw-r--r--src/client/ClientNew.cxx2
-rw-r--r--src/client/ClientProcess.cxx2
-rw-r--r--src/client/ClientRead.cxx2
-rw-r--r--src/client/ClientSubscribe.cxx2
-rw-r--r--src/client/ClientWrite.cxx2
-rw-r--r--src/command/AllCommands.cxx138
-rw-r--r--src/command/AllCommands.hxx2
-rw-r--r--src/command/CommandError.cxx2
-rw-r--r--src/command/CommandError.hxx2
-rw-r--r--src/command/CommandListBuilder.cxx2
-rw-r--r--src/command/CommandListBuilder.hxx2
-rw-r--r--src/command/CommandResult.hxx2
-rw-r--r--src/command/DatabaseCommands.cxx76
-rw-r--r--src/command/DatabaseCommands.hxx23
-rw-r--r--src/command/FileCommands.cxx10
-rw-r--r--src/command/FileCommands.hxx5
-rw-r--r--src/command/MessageCommands.cxx38
-rw-r--r--src/command/MessageCommands.hxx13
-rw-r--r--src/command/NeighborCommands.cxx6
-rw-r--r--src/command/NeighborCommands.hxx5
-rw-r--r--src/command/OtherCommands.cxx85
-rw-r--r--src/command/OtherCommands.hxx35
-rw-r--r--src/command/OutputCommands.cxx26
-rw-r--r--src/command/OutputCommands.hxx11
-rw-r--r--src/command/PlayerCommands.cxx92
-rw-r--r--src/command/PlayerCommands.hxx45
-rw-r--r--src/command/PlaylistCommands.cxx88
-rw-r--r--src/command/PlaylistCommands.hxx30
-rw-r--r--src/command/QueueCommands.cxx116
-rw-r--r--src/command/QueueCommands.hxx43
-rw-r--r--src/command/StickerCommands.cxx97
-rw-r--r--src/command/StickerCommands.hxx5
-rw-r--r--src/command/StorageCommands.cxx15
-rw-r--r--src/command/StorageCommands.hxx9
-rw-r--r--src/command/TagCommands.cxx19
-rw-r--r--src/command/TagCommands.hxx7
-rw-r--r--src/config/Block.cxx (renamed from src/config/ConfigData.cxx)49
-rw-r--r--src/config/Block.hxx (renamed from src/config/ConfigData.hxx)54
-rw-r--r--src/config/ConfigDefaults.hxx2
-rw-r--r--src/config/ConfigError.cxx2
-rw-r--r--src/config/ConfigError.hxx2
-rw-r--r--src/config/ConfigFile.cxx262
-rw-r--r--src/config/ConfigFile.hxx2
-rw-r--r--src/config/ConfigGlobal.cxx46
-rw-r--r--src/config/ConfigGlobal.hxx11
-rw-r--r--src/config/ConfigOption.hxx142
-rw-r--r--src/config/ConfigParser.cxx6
-rw-r--r--src/config/ConfigParser.hxx2
-rw-r--r--src/config/ConfigPath.cxx4
-rw-r--r--src/config/ConfigPath.hxx2
-rw-r--r--src/config/ConfigTemplates.cxx162
-rw-r--r--src/config/ConfigTemplates.hxx6
-rw-r--r--src/config/Data.cxx37
-rw-r--r--src/config/Data.hxx37
-rw-r--r--src/config/Param.cxx29
-rw-r--r--src/config/Param.hxx67
-rw-r--r--src/db/Configured.cxx15
-rw-r--r--src/db/Configured.hxx2
-rw-r--r--src/db/Count.cxx2
-rw-r--r--src/db/Count.hxx2
-rw-r--r--src/db/DatabaseError.cxx2
-rw-r--r--src/db/DatabaseError.hxx2
-rw-r--r--src/db/DatabaseGlue.cxx10
-rw-r--r--src/db/DatabaseGlue.hxx6
-rw-r--r--src/db/DatabaseListener.hxx2
-rw-r--r--src/db/DatabaseLock.cxx2
-rw-r--r--src/db/DatabaseLock.hxx2
-rw-r--r--src/db/DatabasePlaylist.cxx2
-rw-r--r--src/db/DatabasePlaylist.hxx2
-rw-r--r--src/db/DatabasePlugin.hxx6
-rw-r--r--src/db/DatabasePrint.cxx31
-rw-r--r--src/db/DatabasePrint.hxx8
-rw-r--r--src/db/DatabaseQueue.cxx2
-rw-r--r--src/db/DatabaseQueue.hxx2
-rw-r--r--src/db/DatabaseSong.cxx2
-rw-r--r--src/db/DatabaseSong.hxx2
-rw-r--r--src/db/Helpers.cxx6
-rw-r--r--src/db/Helpers.hxx2
-rw-r--r--src/db/Interface.hxx2
-rw-r--r--src/db/LightDirectory.hxx2
-rw-r--r--src/db/LightSong.cxx2
-rw-r--r--src/db/LightSong.hxx2
-rw-r--r--src/db/PlaylistInfo.hxx2
-rw-r--r--src/db/PlaylistVector.cxx2
-rw-r--r--src/db/PlaylistVector.hxx2
-rw-r--r--src/db/Registry.cxx6
-rw-r--r--src/db/Registry.hxx2
-rw-r--r--src/db/Selection.cxx2
-rw-r--r--src/db/Selection.hxx2
-rw-r--r--src/db/Stats.hxx2
-rw-r--r--src/db/UniqueTags.cxx2
-rw-r--r--src/db/UniqueTags.hxx2
-rw-r--r--src/db/Uri.hxx2
-rw-r--r--src/db/Visitor.hxx2
-rw-r--r--src/db/plugins/LazyDatabase.cxx2
-rw-r--r--src/db/plugins/LazyDatabase.hxx2
-rw-r--r--src/db/plugins/ProxyDatabasePlugin.cxx24
-rw-r--r--src/db/plugins/ProxyDatabasePlugin.hxx2
-rw-r--r--src/db/plugins/simple/DatabaseSave.cxx2
-rw-r--r--src/db/plugins/simple/DatabaseSave.hxx2
-rw-r--r--src/db/plugins/simple/Directory.cxx2
-rw-r--r--src/db/plugins/simple/Directory.hxx2
-rw-r--r--src/db/plugins/simple/DirectorySave.cxx2
-rw-r--r--src/db/plugins/simple/DirectorySave.hxx2
-rw-r--r--src/db/plugins/simple/Mount.cxx2
-rw-r--r--src/db/plugins/simple/Mount.hxx2
-rw-r--r--src/db/plugins/simple/PrefixedLightSong.hxx2
-rw-r--r--src/db/plugins/simple/SimpleDatabasePlugin.cxx34
-rw-r--r--src/db/plugins/simple/SimpleDatabasePlugin.hxx10
-rw-r--r--src/db/plugins/simple/Song.cxx2
-rw-r--r--src/db/plugins/simple/Song.hxx2
-rw-r--r--src/db/plugins/simple/SongSort.cxx2
-rw-r--r--src/db/plugins/simple/SongSort.hxx2
-rw-r--r--src/db/plugins/upnp/ContentDirectoryService.cxx2
-rw-r--r--src/db/plugins/upnp/Directory.cxx62
-rw-r--r--src/db/plugins/upnp/Directory.hxx2
-rw-r--r--src/db/plugins/upnp/Object.cxx2
-rw-r--r--src/db/plugins/upnp/Object.hxx29
-rw-r--r--src/db/plugins/upnp/Tags.cxx2
-rw-r--r--src/db/plugins/upnp/Tags.hxx2
-rw-r--r--src/db/plugins/upnp/UpnpDatabasePlugin.cxx30
-rw-r--r--src/db/plugins/upnp/UpnpDatabasePlugin.hxx2
-rw-r--r--src/db/update/Archive.cxx2
-rw-r--r--src/db/update/Container.cxx2
-rw-r--r--src/db/update/Editor.cxx2
-rw-r--r--src/db/update/Editor.hxx2
-rw-r--r--src/db/update/ExcludeList.cxx2
-rw-r--r--src/db/update/ExcludeList.hxx2
-rw-r--r--src/db/update/InotifyDomain.cxx2
-rw-r--r--src/db/update/InotifyDomain.hxx2
-rw-r--r--src/db/update/InotifyQueue.cxx2
-rw-r--r--src/db/update/InotifyQueue.hxx2
-rw-r--r--src/db/update/InotifySource.cxx2
-rw-r--r--src/db/update/InotifySource.hxx6
-rw-r--r--src/db/update/InotifyUpdate.cxx2
-rw-r--r--src/db/update/InotifyUpdate.hxx2
-rw-r--r--src/db/update/Queue.cxx2
-rw-r--r--src/db/update/Queue.hxx2
-rw-r--r--src/db/update/Remove.cxx2
-rw-r--r--src/db/update/Remove.hxx2
-rw-r--r--src/db/update/Service.cxx2
-rw-r--r--src/db/update/Service.hxx2
-rw-r--r--src/db/update/UpdateDomain.cxx2
-rw-r--r--src/db/update/UpdateDomain.hxx2
-rw-r--r--src/db/update/UpdateIO.cxx2
-rw-r--r--src/db/update/UpdateIO.hxx2
-rw-r--r--src/db/update/UpdateSong.cxx2
-rw-r--r--src/db/update/Walk.cxx6
-rw-r--r--src/db/update/Walk.hxx2
-rw-r--r--src/decoder/DecoderAPI.cxx2
-rw-r--r--src/decoder/DecoderAPI.hxx4
-rw-r--r--src/decoder/DecoderBuffer.cxx2
-rw-r--r--src/decoder/DecoderBuffer.hxx2
-rw-r--r--src/decoder/DecoderCommand.hxx2
-rw-r--r--src/decoder/DecoderControl.cxx2
-rw-r--r--src/decoder/DecoderControl.hxx2
-rw-r--r--src/decoder/DecoderError.cxx2
-rw-r--r--src/decoder/DecoderError.hxx2
-rw-r--r--src/decoder/DecoderInternal.cxx2
-rw-r--r--src/decoder/DecoderInternal.hxx2
-rw-r--r--src/decoder/DecoderList.cxx37
-rw-r--r--src/decoder/DecoderList.hxx2
-rw-r--r--src/decoder/DecoderPlugin.cxx2
-rw-r--r--src/decoder/DecoderPlugin.hxx10
-rw-r--r--src/decoder/DecoderPrint.cxx2
-rw-r--r--src/decoder/DecoderPrint.hxx2
-rw-r--r--src/decoder/DecoderThread.cxx2
-rw-r--r--src/decoder/DecoderThread.hxx2
-rw-r--r--src/decoder/plugins/AdPlugDecoderPlugin.cxx6
-rw-r--r--src/decoder/plugins/AdPlugDecoderPlugin.h2
-rw-r--r--src/decoder/plugins/AudiofileDecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/AudiofileDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/DsdLib.cxx6
-rw-r--r--src/decoder/plugins/DsdLib.hxx2
-rw-r--r--src/decoder/plugins/DsdiffDecoderPlugin.cxx12
-rw-r--r--src/decoder/plugins/DsdiffDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/DsfDecoderPlugin.cxx10
-rw-r--r--src/decoder/plugins/DsfDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/FaadDecoderPlugin.cxx2
-rw-r--r--src/decoder/plugins/FaadDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/FfmpegDecoderPlugin.cxx601
-rw-r--r--src/decoder/plugins/FfmpegDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/FfmpegIo.cxx98
-rw-r--r--src/decoder/plugins/FfmpegIo.hxx57
-rw-r--r--src/decoder/plugins/FfmpegMetaData.cxx40
-rw-r--r--src/decoder/plugins/FfmpegMetaData.hxx16
-rw-r--r--src/decoder/plugins/FlacCommon.cxx2
-rw-r--r--src/decoder/plugins/FlacCommon.hxx2
-rw-r--r--src/decoder/plugins/FlacDecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/FlacDecoderPlugin.h2
-rw-r--r--src/decoder/plugins/FlacDomain.cxx2
-rw-r--r--src/decoder/plugins/FlacDomain.hxx2
-rw-r--r--src/decoder/plugins/FlacIOHandle.cxx2
-rw-r--r--src/decoder/plugins/FlacIOHandle.hxx2
-rw-r--r--src/decoder/plugins/FlacInput.cxx2
-rw-r--r--src/decoder/plugins/FlacInput.hxx2
-rw-r--r--src/decoder/plugins/FlacMetadata.cxx6
-rw-r--r--src/decoder/plugins/FlacMetadata.hxx2
-rw-r--r--src/decoder/plugins/FlacPcm.cxx2
-rw-r--r--src/decoder/plugins/FlacPcm.hxx2
-rw-r--r--src/decoder/plugins/FluidsynthDecoderPlugin.cxx12
-rw-r--r--src/decoder/plugins/FluidsynthDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/GmeDecoderPlugin.cxx190
-rw-r--r--src/decoder/plugins/GmeDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/MadDecoderPlugin.cxx28
-rw-r--r--src/decoder/plugins/MadDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/MikmodDecoderPlugin.cxx10
-rw-r--r--src/decoder/plugins/MikmodDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/ModplugDecoderPlugin.cxx8
-rw-r--r--src/decoder/plugins/ModplugDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/MpcdecDecoderPlugin.cxx2
-rw-r--r--src/decoder/plugins/MpcdecDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/Mpg123DecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/Mpg123DecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/OggCodec.cxx2
-rw-r--r--src/decoder/plugins/OggCodec.hxx2
-rw-r--r--src/decoder/plugins/OggFind.cxx2
-rw-r--r--src/decoder/plugins/OggFind.hxx2
-rw-r--r--src/decoder/plugins/OggSyncState.hxx2
-rw-r--r--src/decoder/plugins/OggUtil.cxx2
-rw-r--r--src/decoder/plugins/OggUtil.hxx2
-rw-r--r--src/decoder/plugins/OpusDecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/OpusDecoderPlugin.h2
-rw-r--r--src/decoder/plugins/OpusDomain.cxx2
-rw-r--r--src/decoder/plugins/OpusDomain.hxx2
-rw-r--r--src/decoder/plugins/OpusHead.cxx2
-rw-r--r--src/decoder/plugins/OpusHead.hxx2
-rw-r--r--src/decoder/plugins/OpusReader.hxx2
-rw-r--r--src/decoder/plugins/OpusTags.cxx2
-rw-r--r--src/decoder/plugins/OpusTags.hxx2
-rw-r--r--src/decoder/plugins/PcmDecoderPlugin.cxx2
-rw-r--r--src/decoder/plugins/PcmDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/SidplayDecoderPlugin.cxx190
-rw-r--r--src/decoder/plugins/SidplayDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/SndfileDecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/SndfileDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/VorbisComments.cxx6
-rw-r--r--src/decoder/plugins/VorbisComments.hxx2
-rw-r--r--src/decoder/plugins/VorbisDecoderPlugin.cxx4
-rw-r--r--src/decoder/plugins/VorbisDecoderPlugin.h2
-rw-r--r--src/decoder/plugins/VorbisDomain.cxx2
-rw-r--r--src/decoder/plugins/VorbisDomain.hxx2
-rw-r--r--src/decoder/plugins/WavpackDecoderPlugin.cxx8
-rw-r--r--src/decoder/plugins/WavpackDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/WildmidiDecoderPlugin.cxx6
-rw-r--r--src/decoder/plugins/WildmidiDecoderPlugin.hxx2
-rw-r--r--src/decoder/plugins/XiphTags.cxx3
-rw-r--r--src/decoder/plugins/XiphTags.hxx2
-rw-r--r--src/encoder/EncoderAPI.hxx5
-rw-r--r--src/encoder/EncoderInterface.hxx258
-rw-r--r--src/encoder/EncoderList.cxx12
-rw-r--r--src/encoder/EncoderList.hxx2
-rw-r--r--src/encoder/EncoderPlugin.hxx257
-rw-r--r--src/encoder/ToOutputStream.cxx41
-rw-r--r--src/encoder/ToOutputStream.hxx32
-rw-r--r--src/encoder/plugins/FlacEncoderPlugin.cxx12
-rw-r--r--src/encoder/plugins/FlacEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/LameEncoderPlugin.cxx18
-rw-r--r--src/encoder/plugins/LameEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/NullEncoderPlugin.cxx4
-rw-r--r--src/encoder/plugins/NullEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/OggSerial.cxx2
-rw-r--r--src/encoder/plugins/OggSerial.hxx2
-rw-r--r--src/encoder/plugins/OggStream.hxx2
-rw-r--r--src/encoder/plugins/OpusEncoderPlugin.cxx16
-rw-r--r--src/encoder/plugins/OpusEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/ShineEncoderPlugin.cxx15
-rw-r--r--src/encoder/plugins/ShineEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/TwolameEncoderPlugin.cxx18
-rw-r--r--src/encoder/plugins/TwolameEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/VorbisEncoderPlugin.cxx155
-rw-r--r--src/encoder/plugins/VorbisEncoderPlugin.hxx2
-rw-r--r--src/encoder/plugins/WaveEncoderPlugin.cxx4
-rw-r--r--src/encoder/plugins/WaveEncoderPlugin.hxx2
-rw-r--r--src/event/BufferedSocket.cxx2
-rw-r--r--src/event/BufferedSocket.hxx2
-rw-r--r--src/event/Call.cxx2
-rw-r--r--src/event/Call.hxx2
-rw-r--r--src/event/DeferredMonitor.cxx2
-rw-r--r--src/event/DeferredMonitor.hxx2
-rw-r--r--src/event/FullyBufferedSocket.cxx2
-rw-r--r--src/event/FullyBufferedSocket.hxx2
-rw-r--r--src/event/IdleMonitor.cxx2
-rw-r--r--src/event/IdleMonitor.hxx2
-rw-r--r--src/event/Loop.cxx2
-rw-r--r--src/event/Loop.hxx2
-rw-r--r--src/event/MultiSocketMonitor.cxx2
-rw-r--r--src/event/MultiSocketMonitor.hxx2
-rw-r--r--src/event/PollGroup.hxx2
-rw-r--r--src/event/PollGroupEPoll.hxx2
-rw-r--r--src/event/PollGroupPoll.cxx2
-rw-r--r--src/event/PollGroupPoll.hxx2
-rw-r--r--src/event/PollGroupWinSelect.cxx2
-rw-r--r--src/event/PollGroupWinSelect.hxx2
-rw-r--r--src/event/PollResultGeneric.hxx2
-rw-r--r--src/event/ServerSocket.cxx4
-rw-r--r--src/event/ServerSocket.hxx2
-rw-r--r--src/event/SignalMonitor.cxx2
-rw-r--r--src/event/SignalMonitor.hxx2
-rw-r--r--src/event/SocketMonitor.cxx2
-rw-r--r--src/event/SocketMonitor.hxx2
-rw-r--r--src/event/TimeoutMonitor.cxx2
-rw-r--r--src/event/TimeoutMonitor.hxx2
-rw-r--r--src/event/WakeFD.hxx2
-rw-r--r--src/filter/FilterConfig.cxx9
-rw-r--r--src/filter/FilterConfig.hxx2
-rw-r--r--src/filter/FilterInternal.hxx2
-rw-r--r--src/filter/FilterPlugin.cxx14
-rw-r--r--src/filter/FilterPlugin.hxx10
-rw-r--r--src/filter/FilterRegistry.cxx2
-rw-r--r--src/filter/FilterRegistry.hxx2
-rw-r--r--src/filter/plugins/AutoConvertFilterPlugin.cxx6
-rw-r--r--src/filter/plugins/AutoConvertFilterPlugin.hxx2
-rw-r--r--src/filter/plugins/ChainFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/ChainFilterPlugin.hxx2
-rw-r--r--src/filter/plugins/ConvertFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/ConvertFilterPlugin.hxx2
-rw-r--r--src/filter/plugins/NormalizeFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/NullFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/ReplayGainFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/ReplayGainFilterPlugin.hxx2
-rw-r--r--src/filter/plugins/RouteFilterPlugin.cxx16
-rw-r--r--src/filter/plugins/VolumeFilterPlugin.cxx4
-rw-r--r--src/filter/plugins/VolumeFilterPlugin.hxx2
-rw-r--r--src/fs/AllocatedPath.cxx27
-rw-r--r--src/fs/AllocatedPath.hxx19
-rw-r--r--src/fs/Charset.cxx97
-rw-r--r--src/fs/Charset.hxx21
-rw-r--r--src/fs/CheckFile.cxx2
-rw-r--r--src/fs/CheckFile.hxx2
-rw-r--r--src/fs/Config.cxx38
-rw-r--r--src/fs/Config.hxx9
-rw-r--r--src/fs/DirectoryReader.hxx2
-rw-r--r--src/fs/Domain.cxx2
-rw-r--r--src/fs/Domain.hxx2
-rw-r--r--src/fs/FileSystem.cxx2
-rw-r--r--src/fs/FileSystem.hxx2
-rw-r--r--src/fs/Limits.hxx2
-rw-r--r--src/fs/Path.cxx2
-rw-r--r--src/fs/Path.hxx20
-rw-r--r--src/fs/Path2.cxx28
-rw-r--r--src/fs/StandardDirectory.cxx2
-rw-r--r--src/fs/StandardDirectory.hxx2
-rw-r--r--src/fs/Traits.cxx2
-rw-r--r--src/fs/Traits.hxx2
-rw-r--r--src/fs/io/AutoGunzipReader.cxx2
-rw-r--r--src/fs/io/AutoGunzipReader.hxx2
-rw-r--r--src/fs/io/BufferedOutputStream.cxx2
-rw-r--r--src/fs/io/BufferedOutputStream.hxx2
-rw-r--r--src/fs/io/BufferedReader.cxx7
-rw-r--r--src/fs/io/BufferedReader.hxx11
-rw-r--r--src/fs/io/FileOutputStream.cxx81
-rw-r--r--src/fs/io/FileOutputStream.hxx11
-rw-r--r--src/fs/io/FileReader.cxx10
-rw-r--r--src/fs/io/FileReader.hxx2
-rw-r--r--src/fs/io/GunzipReader.cxx2
-rw-r--r--src/fs/io/GunzipReader.hxx2
-rw-r--r--src/fs/io/GzipOutputStream.cxx2
-rw-r--r--src/fs/io/GzipOutputStream.hxx2
-rw-r--r--src/fs/io/OutputStream.hxx2
-rw-r--r--src/fs/io/PeekReader.cxx2
-rw-r--r--src/fs/io/PeekReader.hxx2
-rw-r--r--src/fs/io/Reader.hxx2
-rw-r--r--src/fs/io/StdioOutputStream.hxx2
-rw-r--r--src/fs/io/TextFile.cxx8
-rw-r--r--src/fs/io/TextFile.hxx4
-rw-r--r--src/input/AsyncInputStream.cxx2
-rw-r--r--src/input/AsyncInputStream.hxx6
-rw-r--r--src/input/Domain.cxx2
-rw-r--r--src/input/Domain.hxx2
-rw-r--r--src/input/IcyInputStream.cxx2
-rw-r--r--src/input/IcyInputStream.hxx2
-rw-r--r--src/input/Init.cxx19
-rw-r--r--src/input/Init.hxx2
-rw-r--r--src/input/InputPlugin.hxx6
-rw-r--r--src/input/InputStream.cxx2
-rw-r--r--src/input/InputStream.hxx2
-rw-r--r--src/input/LocalOpen.cxx2
-rw-r--r--src/input/LocalOpen.hxx2
-rw-r--r--src/input/Offset.hxx2
-rw-r--r--src/input/Open.cxx2
-rw-r--r--src/input/ProxyInputStream.cxx2
-rw-r--r--src/input/ProxyInputStream.hxx2
-rw-r--r--src/input/Registry.cxx10
-rw-r--r--src/input/Registry.hxx2
-rw-r--r--src/input/TextInputStream.cxx2
-rw-r--r--src/input/TextInputStream.hxx2
-rw-r--r--src/input/ThreadInputStream.cxx2
-rw-r--r--src/input/ThreadInputStream.hxx2
-rw-r--r--src/input/plugins/AlsaInputPlugin.cxx2
-rw-r--r--src/input/plugins/AlsaInputPlugin.hxx2
-rw-r--r--src/input/plugins/ArchiveInputPlugin.cxx2
-rw-r--r--src/input/plugins/ArchiveInputPlugin.hxx2
-rw-r--r--src/input/plugins/CdioParanoiaInputPlugin.cxx11
-rw-r--r--src/input/plugins/CdioParanoiaInputPlugin.hxx2
-rw-r--r--src/input/plugins/CurlInputPlugin.cxx29
-rw-r--r--src/input/plugins/CurlInputPlugin.hxx2
-rw-r--r--src/input/plugins/FfmpegInputPlugin.cxx8
-rw-r--r--src/input/plugins/FfmpegInputPlugin.hxx2
-rw-r--r--src/input/plugins/FileInputPlugin.cxx2
-rw-r--r--src/input/plugins/FileInputPlugin.hxx2
-rw-r--r--src/input/plugins/MmsInputPlugin.cxx2
-rw-r--r--src/input/plugins/MmsInputPlugin.hxx2
-rw-r--r--src/input/plugins/NfsInputPlugin.cxx8
-rw-r--r--src/input/plugins/NfsInputPlugin.hxx2
-rw-r--r--src/input/plugins/RewindInputPlugin.cxx2
-rw-r--r--src/input/plugins/RewindInputPlugin.hxx2
-rw-r--r--src/input/plugins/SmbclientInputPlugin.cxx6
-rw-r--r--src/input/plugins/SmbclientInputPlugin.hxx2
-rw-r--r--src/lib/expat/ExpatParser.cxx2
-rw-r--r--src/lib/expat/ExpatParser.hxx2
-rw-r--r--src/lib/ffmpeg/Buffer.hxx72
-rw-r--r--src/lib/ffmpeg/Domain.cxx2
-rw-r--r--src/lib/ffmpeg/Domain.hxx2
-rw-r--r--src/lib/ffmpeg/Error.cxx2
-rw-r--r--src/lib/ffmpeg/Error.hxx2
-rw-r--r--src/lib/ffmpeg/Init.cxx38
-rw-r--r--src/lib/ffmpeg/Init.hxx26
-rw-r--r--src/lib/ffmpeg/LogCallback.cxx66
-rw-r--r--src/lib/ffmpeg/LogCallback.hxx30
-rw-r--r--src/lib/ffmpeg/LogError.cxx45
-rw-r--r--src/lib/ffmpeg/LogError.hxx29
-rw-r--r--src/lib/ffmpeg/Time.hxx110
-rw-r--r--src/lib/icu/Collate.cxx47
-rw-r--r--src/lib/icu/Collate.hxx2
-rw-r--r--src/lib/icu/Converter.cxx169
-rw-r--r--src/lib/icu/Converter.hxx95
-rw-r--r--src/lib/icu/Error.cxx2
-rw-r--r--src/lib/icu/Error.hxx2
-rw-r--r--src/lib/icu/Init.cxx2
-rw-r--r--src/lib/icu/Init.hxx2
-rw-r--r--src/lib/icu/Util.cxx72
-rw-r--r--src/lib/icu/Util.hxx44
-rw-r--r--src/lib/nfs/Base.cxx2
-rw-r--r--src/lib/nfs/Base.hxx2
-rw-r--r--src/lib/nfs/Blocking.cxx2
-rw-r--r--src/lib/nfs/Blocking.hxx2
-rw-r--r--src/lib/nfs/Callback.hxx2
-rw-r--r--src/lib/nfs/Cancellable.hxx2
-rw-r--r--src/lib/nfs/Connection.cxx2
-rw-r--r--src/lib/nfs/Connection.hxx2
-rw-r--r--src/lib/nfs/Domain.cxx2
-rw-r--r--src/lib/nfs/Domain.hxx2
-rw-r--r--src/lib/nfs/FileReader.cxx2
-rw-r--r--src/lib/nfs/FileReader.hxx2
-rw-r--r--src/lib/nfs/Glue.cxx2
-rw-r--r--src/lib/nfs/Glue.hxx2
-rw-r--r--src/lib/nfs/Lease.hxx2
-rw-r--r--src/lib/nfs/Manager.cxx2
-rw-r--r--src/lib/nfs/Manager.hxx2
-rw-r--r--src/lib/pulse/Domain.cxx24
-rw-r--r--src/lib/pulse/Domain.hxx27
-rw-r--r--src/lib/pulse/Error.cxx33
-rw-r--r--src/lib/pulse/Error.hxx29
-rw-r--r--src/lib/pulse/LogError.cxx33
-rw-r--r--src/lib/pulse/LogError.hxx28
-rw-r--r--src/lib/smbclient/Domain.cxx2
-rw-r--r--src/lib/smbclient/Domain.hxx2
-rw-r--r--src/lib/smbclient/Init.cxx2
-rw-r--r--src/lib/smbclient/Init.hxx2
-rw-r--r--src/lib/smbclient/Mutex.cxx2
-rw-r--r--src/lib/smbclient/Mutex.hxx2
-rw-r--r--src/lib/sqlite/Domain.cxx24
-rw-r--r--src/lib/sqlite/Domain.hxx27
-rw-r--r--src/lib/sqlite/Util.hxx188
-rw-r--r--src/lib/upnp/Action.hxx2
-rw-r--r--src/lib/upnp/Callback.hxx2
-rw-r--r--src/lib/upnp/ClientInit.cxx2
-rw-r--r--src/lib/upnp/ClientInit.hxx2
-rw-r--r--src/lib/upnp/ContentDirectoryService.cxx2
-rw-r--r--src/lib/upnp/ContentDirectoryService.hxx2
-rw-r--r--src/lib/upnp/Device.cxx2
-rw-r--r--src/lib/upnp/Device.hxx2
-rw-r--r--src/lib/upnp/Discovery.cxx2
-rw-r--r--src/lib/upnp/Discovery.hxx2
-rw-r--r--src/lib/upnp/Domain.cxx2
-rw-r--r--src/lib/upnp/Domain.hxx2
-rw-r--r--src/lib/upnp/Init.cxx2
-rw-r--r--src/lib/upnp/Init.hxx2
-rw-r--r--src/lib/upnp/Util.cxx2
-rw-r--r--src/lib/upnp/Util.hxx2
-rw-r--r--src/lib/upnp/WorkQueue.hxx2
-rw-r--r--src/lib/zlib/Domain.cxx2
-rw-r--r--src/lib/zlib/Domain.hxx2
-rw-r--r--src/ls.cxx14
-rw-r--r--src/ls.hxx2
-rw-r--r--src/mixer/Listener.hxx2
-rw-r--r--src/mixer/MixerAll.cxx5
-rw-r--r--src/mixer/MixerControl.cxx6
-rw-r--r--src/mixer/MixerControl.hxx6
-rw-r--r--src/mixer/MixerInternal.hxx2
-rw-r--r--src/mixer/MixerList.hxx3
-rw-r--r--src/mixer/MixerPlugin.hxx6
-rw-r--r--src/mixer/MixerType.cxx14
-rw-r--r--src/mixer/MixerType.hxx25
-rw-r--r--src/mixer/Volume.cxx2
-rw-r--r--src/mixer/Volume.hxx2
-rw-r--r--src/mixer/plugins/AlsaMixerPlugin.cxx16
-rw-r--r--src/mixer/plugins/NullMixerPlugin.cxx67
-rw-r--r--src/mixer/plugins/OssMixerPlugin.cxx16
-rw-r--r--src/mixer/plugins/PulseMixerPlugin.cxx30
-rw-r--r--src/mixer/plugins/PulseMixerPlugin.hxx2
-rw-r--r--src/mixer/plugins/RoarMixerPlugin.cxx4
-rw-r--r--src/mixer/plugins/SoftwareMixerPlugin.cxx8
-rw-r--r--src/mixer/plugins/SoftwareMixerPlugin.hxx2
-rw-r--r--src/mixer/plugins/WinmmMixerPlugin.cxx4
-rw-r--r--src/neighbor/Explorer.hxx2
-rw-r--r--src/neighbor/Glue.cxx18
-rw-r--r--src/neighbor/Glue.hxx2
-rw-r--r--src/neighbor/Info.hxx2
-rw-r--r--src/neighbor/Listener.hxx2
-rw-r--r--src/neighbor/NeighborPlugin.hxx6
-rw-r--r--src/neighbor/Registry.cxx4
-rw-r--r--src/neighbor/Registry.hxx2
-rw-r--r--src/neighbor/plugins/SmbclientNeighborPlugin.cxx6
-rw-r--r--src/neighbor/plugins/SmbclientNeighborPlugin.hxx2
-rw-r--r--src/neighbor/plugins/UpnpNeighborPlugin.cxx4
-rw-r--r--src/neighbor/plugins/UpnpNeighborPlugin.hxx2
-rw-r--r--src/notify.cxx2
-rw-r--r--src/notify.hxx2
-rw-r--r--src/open.h2
-rw-r--r--src/output/Domain.cxx2
-rw-r--r--src/output/Domain.hxx2
-rw-r--r--src/output/Finish.cxx2
-rw-r--r--src/output/Init.cxx79
-rw-r--r--src/output/Internal.hxx60
-rw-r--r--src/output/MultipleOutputs.cxx16
-rw-r--r--src/output/MultipleOutputs.hxx2
-rw-r--r--src/output/OutputAPI.hxx4
-rw-r--r--src/output/OutputCommand.cxx2
-rw-r--r--src/output/OutputCommand.hxx2
-rw-r--r--src/output/OutputControl.cxx28
-rw-r--r--src/output/OutputControl.hxx2
-rw-r--r--src/output/OutputPlugin.cxx8
-rw-r--r--src/output/OutputPlugin.hxx13
-rw-r--r--src/output/OutputPrint.cxx2
-rw-r--r--src/output/OutputPrint.hxx2
-rw-r--r--src/output/OutputState.cxx2
-rw-r--r--src/output/OutputState.hxx2
-rw-r--r--src/output/OutputThread.cxx40
-rw-r--r--src/output/Registry.cxx12
-rw-r--r--src/output/Registry.hxx2
-rw-r--r--src/output/Timer.cxx2
-rw-r--r--src/output/Timer.hxx2
-rw-r--r--src/output/Wrapper.hxx101
-rw-r--r--src/output/plugins/AlsaOutputPlugin.cxx301
-rw-r--r--src/output/plugins/AlsaOutputPlugin.hxx2
-rw-r--r--src/output/plugins/AoOutputPlugin.cxx44
-rw-r--r--src/output/plugins/AoOutputPlugin.hxx2
-rw-r--r--src/output/plugins/FifoOutputPlugin.cxx15
-rw-r--r--src/output/plugins/FifoOutputPlugin.hxx2
-rw-r--r--src/output/plugins/JackOutputPlugin.cxx728
-rw-r--r--src/output/plugins/JackOutputPlugin.hxx2
-rw-r--r--src/output/plugins/NullOutputPlugin.cxx133
-rw-r--r--src/output/plugins/NullOutputPlugin.hxx2
-rw-r--r--src/output/plugins/OSXOutputPlugin.cxx28
-rw-r--r--src/output/plugins/OSXOutputPlugin.hxx2
-rw-r--r--src/output/plugins/OpenALOutputPlugin.cxx245
-rw-r--r--src/output/plugins/OpenALOutputPlugin.hxx2
-rw-r--r--src/output/plugins/OssOutputPlugin.cxx251
-rw-r--r--src/output/plugins/OssOutputPlugin.hxx2
-rw-r--r--src/output/plugins/PipeOutputPlugin.cxx101
-rw-r--r--src/output/plugins/PipeOutputPlugin.hxx2
-rw-r--r--src/output/plugins/PulseOutputPlugin.cxx882
-rw-r--r--src/output/plugins/PulseOutputPlugin.hxx4
-rw-r--r--src/output/plugins/RecorderOutputPlugin.cxx351
-rw-r--r--src/output/plugins/RecorderOutputPlugin.hxx2
-rw-r--r--src/output/plugins/RoarOutputPlugin.cxx80
-rw-r--r--src/output/plugins/RoarOutputPlugin.hxx2
-rw-r--r--src/output/plugins/ShoutOutputPlugin.cxx71
-rw-r--r--src/output/plugins/ShoutOutputPlugin.hxx2
-rw-r--r--src/output/plugins/SolarisOutputPlugin.cxx12
-rw-r--r--src/output/plugins/SolarisOutputPlugin.hxx2
-rw-r--r--src/output/plugins/WinmmOutputPlugin.cxx33
-rw-r--r--src/output/plugins/WinmmOutputPlugin.hxx2
-rw-r--r--src/output/plugins/httpd/HttpdClient.cxx2
-rw-r--r--src/output/plugins/httpd/HttpdClient.hxx2
-rw-r--r--src/output/plugins/httpd/HttpdInternal.hxx18
-rw-r--r--src/output/plugins/httpd/HttpdOutputPlugin.cxx43
-rw-r--r--src/output/plugins/httpd/HttpdOutputPlugin.hxx2
-rw-r--r--src/output/plugins/httpd/IcyMetaDataServer.cxx58
-rw-r--r--src/output/plugins/httpd/IcyMetaDataServer.hxx2
-rw-r--r--src/output/plugins/httpd/Page.cxx2
-rw-r--r--src/output/plugins/httpd/Page.hxx2
-rw-r--r--src/output/plugins/sles/SlesOutputPlugin.cxx100
-rw-r--r--src/output/plugins/sles/SlesOutputPlugin.hxx2
-rw-r--r--src/pcm/ChannelsConverter.cxx2
-rw-r--r--src/pcm/ChannelsConverter.hxx2
-rw-r--r--src/pcm/ConfiguredResampler.cxx141
-rw-r--r--src/pcm/ConfiguredResampler.hxx2
-rw-r--r--src/pcm/Domain.cxx2
-rw-r--r--src/pcm/Domain.hxx2
-rw-r--r--src/pcm/FallbackResampler.cxx2
-rw-r--r--src/pcm/FallbackResampler.hxx2
-rw-r--r--src/pcm/FloatConvert.hxx2
-rw-r--r--src/pcm/FormatConverter.cxx2
-rw-r--r--src/pcm/FormatConverter.hxx2
-rw-r--r--src/pcm/GlueResampler.cxx2
-rw-r--r--src/pcm/GlueResampler.hxx2
-rw-r--r--src/pcm/LibsamplerateResampler.cxx6
-rw-r--r--src/pcm/LibsamplerateResampler.hxx6
-rw-r--r--src/pcm/Neon.hxx2
-rw-r--r--src/pcm/PcmBuffer.cxx2
-rw-r--r--src/pcm/PcmBuffer.hxx2
-rw-r--r--src/pcm/PcmChannels.cxx2
-rw-r--r--src/pcm/PcmChannels.hxx2
-rw-r--r--src/pcm/PcmConvert.cxx2
-rw-r--r--src/pcm/PcmConvert.hxx2
-rw-r--r--src/pcm/PcmDither.cxx2
-rw-r--r--src/pcm/PcmDither.hxx2
-rw-r--r--src/pcm/PcmDop.cxx2
-rw-r--r--src/pcm/PcmDop.hxx2
-rw-r--r--src/pcm/PcmDsd.cxx2
-rw-r--r--src/pcm/PcmDsd.hxx2
-rw-r--r--src/pcm/PcmExport.cxx2
-rw-r--r--src/pcm/PcmExport.hxx2
-rw-r--r--src/pcm/PcmFormat.cxx2
-rw-r--r--src/pcm/PcmFormat.hxx2
-rw-r--r--src/pcm/PcmMix.cxx2
-rw-r--r--src/pcm/PcmMix.hxx2
-rw-r--r--src/pcm/PcmPack.cxx2
-rw-r--r--src/pcm/PcmPack.hxx2
-rw-r--r--src/pcm/PcmPrng.hxx2
-rw-r--r--src/pcm/PcmUtils.hxx2
-rw-r--r--src/pcm/Resampler.hxx2
-rw-r--r--src/pcm/ShiftConvert.hxx2
-rw-r--r--src/pcm/SoxrResampler.cxx98
-rw-r--r--src/pcm/SoxrResampler.hxx5
-rw-r--r--src/pcm/Traits.hxx2
-rw-r--r--src/pcm/Volume.cxx2
-rw-r--r--src/pcm/Volume.hxx2
-rw-r--r--src/playlist/CloseSongEnumerator.cxx2
-rw-r--r--src/playlist/CloseSongEnumerator.hxx2
-rw-r--r--src/playlist/MemorySongEnumerator.cxx2
-rw-r--r--src/playlist/MemorySongEnumerator.hxx2
-rw-r--r--src/playlist/PlaylistAny.cxx2
-rw-r--r--src/playlist/PlaylistAny.hxx2
-rw-r--r--src/playlist/PlaylistMapper.cxx2
-rw-r--r--src/playlist/PlaylistMapper.hxx2
-rw-r--r--src/playlist/PlaylistPlugin.hxx10
-rw-r--r--src/playlist/PlaylistQueue.cxx2
-rw-r--r--src/playlist/PlaylistQueue.hxx2
-rw-r--r--src/playlist/PlaylistRegistry.cxx19
-rw-r--r--src/playlist/PlaylistRegistry.hxx2
-rw-r--r--src/playlist/PlaylistSong.cxx2
-rw-r--r--src/playlist/PlaylistSong.hxx2
-rw-r--r--src/playlist/PlaylistStream.cxx2
-rw-r--r--src/playlist/PlaylistStream.hxx2
-rw-r--r--src/playlist/Print.cxx2
-rw-r--r--src/playlist/Print.hxx2
-rw-r--r--src/playlist/SongEnumerator.hxx2
-rw-r--r--src/playlist/cue/CueParser.cxx2
-rw-r--r--src/playlist/cue/CueParser.hxx2
-rw-r--r--src/playlist/plugins/AsxPlaylistPlugin.cxx4
-rw-r--r--src/playlist/plugins/AsxPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/CuePlaylistPlugin.cxx2
-rw-r--r--src/playlist/plugins/CuePlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx2
-rw-r--r--src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/ExtM3uPlaylistPlugin.cxx2
-rw-r--r--src/playlist/plugins/ExtM3uPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/M3uPlaylistPlugin.cxx2
-rw-r--r--src/playlist/plugins/M3uPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/PlsPlaylistPlugin.cxx195
-rw-r--r--src/playlist/plugins/PlsPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/RssPlaylistPlugin.cxx4
-rw-r--r--src/playlist/plugins/RssPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/SoundCloudPlaylistPlugin.cxx110
-rw-r--r--src/playlist/plugins/SoundCloudPlaylistPlugin.hxx2
-rw-r--r--src/playlist/plugins/XspfPlaylistPlugin.cxx4
-rw-r--r--src/playlist/plugins/XspfPlaylistPlugin.hxx2
-rw-r--r--src/poison.h2
-rw-r--r--src/protocol/Ack.cxx2
-rw-r--r--src/protocol/Ack.hxx2
-rw-r--r--src/protocol/ArgParser.cxx2
-rw-r--r--src/protocol/ArgParser.hxx2
-rw-r--r--src/protocol/Result.cxx2
-rw-r--r--src/protocol/Result.hxx2
-rw-r--r--src/queue/IdTable.hxx2
-rw-r--r--src/queue/Playlist.cxx84
-rw-r--r--src/queue/Playlist.hxx31
-rw-r--r--src/queue/PlaylistControl.cxx2
-rw-r--r--src/queue/PlaylistEdit.cxx2
-rw-r--r--src/queue/PlaylistState.cxx7
-rw-r--r--src/queue/PlaylistState.hxx2
-rw-r--r--src/queue/PlaylistTag.cxx2
-rw-r--r--src/queue/PlaylistUpdate.cxx2
-rw-r--r--src/queue/Queue.cxx7
-rw-r--r--src/queue/Queue.hxx7
-rw-r--r--src/queue/QueuePrint.cxx2
-rw-r--r--src/queue/QueuePrint.hxx2
-rw-r--r--src/queue/QueueSave.cxx2
-rw-r--r--src/queue/QueueSave.hxx2
-rw-r--r--src/sticker/Match.hxx49
-rw-r--r--src/sticker/SongSticker.cxx41
-rw-r--r--src/sticker/SongSticker.hxx20
-rw-r--r--src/sticker/StickerDatabase.cxx384
-rw-r--r--src/sticker/StickerDatabase.hxx28
-rw-r--r--src/sticker/StickerPrint.cxx2
-rw-r--r--src/sticker/StickerPrint.hxx2
-rw-r--r--src/storage/CompositeStorage.cxx4
-rw-r--r--src/storage/CompositeStorage.hxx2
-rw-r--r--src/storage/Configured.cxx8
-rw-r--r--src/storage/Configured.hxx2
-rw-r--r--src/storage/FileInfo.hxx2
-rw-r--r--src/storage/MemoryDirectoryReader.cxx2
-rw-r--r--src/storage/MemoryDirectoryReader.hxx2
-rw-r--r--src/storage/Registry.cxx2
-rw-r--r--src/storage/Registry.hxx2
-rw-r--r--src/storage/StorageInterface.cxx2
-rw-r--r--src/storage/StorageInterface.hxx2
-rw-r--r--src/storage/StoragePlugin.hxx2
-rw-r--r--src/storage/plugins/LocalStorage.cxx2
-rw-r--r--src/storage/plugins/LocalStorage.hxx2
-rw-r--r--src/storage/plugins/NfsStorage.cxx2
-rw-r--r--src/storage/plugins/NfsStorage.hxx2
-rw-r--r--src/storage/plugins/SmbclientStorage.cxx2
-rw-r--r--src/storage/plugins/SmbclientStorage.hxx2
-rw-r--r--src/system/Clock.cxx2
-rw-r--r--src/system/Clock.hxx2
-rw-r--r--src/system/EPollFD.cxx2
-rw-r--r--src/system/EPollFD.hxx2
-rw-r--r--src/system/EventFD.cxx2
-rw-r--r--src/system/EventFD.hxx2
-rw-r--r--src/system/EventPipe.cxx2
-rw-r--r--src/system/EventPipe.hxx2
-rw-r--r--src/system/FatalError.cxx29
-rw-r--r--src/system/FatalError.hxx14
-rw-r--r--src/system/PeriodClock.hxx2
-rw-r--r--src/system/Resolver.cxx2
-rw-r--r--src/system/Resolver.hxx2
-rw-r--r--src/system/SignalFD.cxx2
-rw-r--r--src/system/SignalFD.hxx2
-rw-r--r--src/system/SocketError.cxx2
-rw-r--r--src/system/SocketError.hxx2
-rw-r--r--src/system/SocketUtil.cxx2
-rw-r--r--src/system/SocketUtil.hxx2
-rw-r--r--src/system/fd_util.c2
-rw-r--r--src/system/fd_util.h4
-rw-r--r--src/tag/Aiff.cxx2
-rw-r--r--src/tag/Aiff.hxx2
-rw-r--r--src/tag/ApeLoader.cxx2
-rw-r--r--src/tag/ApeLoader.hxx2
-rw-r--r--src/tag/ApeReplayGain.cxx2
-rw-r--r--src/tag/ApeReplayGain.hxx2
-rw-r--r--src/tag/ApeTag.cxx3
-rw-r--r--src/tag/ApeTag.hxx2
-rw-r--r--src/tag/Format.cxx133
-rw-r--r--src/tag/Format.hxx32
-rw-r--r--src/tag/MixRamp.cxx2
-rw-r--r--src/tag/MixRamp.hxx2
-rw-r--r--src/tag/ReplayGain.cxx2
-rw-r--r--src/tag/ReplayGain.hxx2
-rw-r--r--src/tag/Riff.cxx2
-rw-r--r--src/tag/Riff.hxx2
-rw-r--r--src/tag/Set.cxx4
-rw-r--r--src/tag/Set.hxx2
-rw-r--r--src/tag/Tag.cxx2
-rw-r--r--src/tag/Tag.hxx2
-rw-r--r--src/tag/TagBuilder.cxx2
-rw-r--r--src/tag/TagBuilder.hxx2
-rw-r--r--src/tag/TagConfig.cxx5
-rw-r--r--src/tag/TagConfig.hxx2
-rw-r--r--src/tag/TagHandler.cxx2
-rw-r--r--src/tag/TagHandler.hxx2
-rw-r--r--src/tag/TagId3.cxx10
-rw-r--r--src/tag/TagId3.hxx4
-rw-r--r--src/tag/TagItem.hxx2
-rw-r--r--src/tag/TagNames.c2
-rw-r--r--src/tag/TagPool.cxx4
-rw-r--r--src/tag/TagPool.hxx2
-rw-r--r--src/tag/TagRva2.cxx2
-rw-r--r--src/tag/TagRva2.hxx2
-rw-r--r--src/tag/TagSettings.c2
-rw-r--r--src/tag/TagSettings.h2
-rw-r--r--src/tag/TagString.cxx2
-rw-r--r--src/tag/TagString.hxx2
-rw-r--r--src/tag/TagTable.cxx2
-rw-r--r--src/tag/TagTable.hxx2
-rw-r--r--src/tag/TagType.h2
-rw-r--r--src/tag/VorbisComment.cxx2
-rw-r--r--src/tag/VorbisComment.hxx2
-rw-r--r--src/thread/Id.hxx2
-rw-r--r--src/thread/Name.hxx2
-rw-r--r--src/thread/Slack.hxx2
-rw-r--r--src/thread/Thread.cxx2
-rw-r--r--src/thread/Thread.hxx2
-rw-r--r--src/unix/Daemon.cxx2
-rw-r--r--src/unix/Daemon.hxx2
-rw-r--r--src/unix/PidFile.hxx2
-rw-r--r--src/unix/SignalHandlers.cxx2
-rw-r--r--src/unix/SignalHandlers.hxx2
-rw-r--r--src/util/Alloc.cxx86
-rw-r--r--src/util/Alloc.hxx21
-rw-r--r--src/util/ByteReverse.cxx2
-rw-r--r--src/util/ByteReverse.hxx2
-rw-r--r--src/util/Cast.hxx4
-rw-r--r--src/util/CharUtil.hxx2
-rw-r--r--src/util/DivideString.cxx48
-rw-r--r--src/util/DivideString.hxx75
-rw-r--r--src/util/Error.cxx8
-rw-r--r--src/util/FormatString.cxx2
-rw-r--r--src/util/FormatString.hxx2
-rw-r--r--src/util/LazyRandomEngine.cxx2
-rw-r--r--src/util/LazyRandomEngine.hxx2
-rw-r--r--src/util/Manual.hxx37
-rw-r--r--src/util/OptionDef.hxx2
-rw-r--r--src/util/OptionParser.cxx2
-rw-r--r--src/util/OptionParser.hxx2
-rw-r--r--src/util/PeakBuffer.cxx2
-rw-r--r--src/util/PeakBuffer.hxx2
-rw-r--r--src/util/RefCount.hxx2
-rw-r--r--src/util/SliceBuffer.hxx2
-rw-r--r--src/util/SplitString.cxx44
-rw-r--r--src/util/SplitString.hxx58
-rw-r--r--src/util/StringUtil.cxx22
-rw-r--r--src/util/StringUtil.hxx10
-rw-r--r--src/util/UriUtil.cxx2
-rw-r--r--src/util/UriUtil.hxx2
-rw-r--r--src/util/bit_reverse.c2
-rw-r--r--src/util/bit_reverse.h2
-rw-r--r--src/util/format.c259
-rw-r--r--src/util/format.h51
-rw-r--r--src/win32/Win32Main.cxx26
-rw-r--r--src/win32/mpd.icobin353118 -> 0 bytes
-rw-r--r--src/win32/mpd_win32_rc.rc.in34
-rw-r--r--src/zeroconf/AvahiPoll.cxx2
-rw-r--r--src/zeroconf/AvahiPoll.hxx2
-rw-r--r--src/zeroconf/ZeroconfAvahi.cxx2
-rw-r--r--src/zeroconf/ZeroconfAvahi.hxx2
-rw-r--r--src/zeroconf/ZeroconfBonjour.cxx2
-rw-r--r--src/zeroconf/ZeroconfBonjour.hxx2
-rw-r--r--src/zeroconf/ZeroconfGlue.cxx7
-rw-r--r--src/zeroconf/ZeroconfGlue.hxx2
-rw-r--r--src/zeroconf/ZeroconfInternal.hxx2
964 files changed, 8608 insertions, 5804 deletions
diff --git a/src/AudioConfig.cxx b/src/AudioConfig.cxx
index d54f59e17..8ee17f301 100644
--- a/src/AudioConfig.cxx
+++ b/src/AudioConfig.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
#include "AudioConfig.hxx"
#include "AudioFormat.hxx"
#include "AudioParser.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "util/Error.hxx"
@@ -39,7 +39,7 @@ getOutputAudioFormat(AudioFormat inAudioFormat)
void initAudioConfig(void)
{
- const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT);
+ const struct config_param *param = config_get_param(ConfigOption::AUDIO_OUTPUT_FORMAT);
if (param == nullptr)
return;
diff --git a/src/AudioConfig.hxx b/src/AudioConfig.hxx
index 471e60e51..430d2f26a 100644
--- a/src/AudioConfig.hxx
+++ b/src/AudioConfig.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/AudioFormat.cxx b/src/AudioFormat.cxx
index edfb9d8fe..fb30dd93d 100644
--- a/src/AudioFormat.cxx
+++ b/src/AudioFormat.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/AudioFormat.hxx b/src/AudioFormat.hxx
index 0937ab8ae..c83e0fda4 100644
--- a/src/AudioFormat.hxx
+++ b/src/AudioFormat.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/AudioParser.cxx b/src/AudioParser.cxx
index 74bb04abc..b7051b4b2 100644
--- a/src/AudioParser.cxx
+++ b/src/AudioParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/AudioParser.hxx b/src/AudioParser.hxx
index 07ad7cb4a..863fa5698 100644
--- a/src/AudioParser.hxx
+++ b/src/AudioParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/BulkEdit.hxx b/src/BulkEdit.hxx
index 422dc4f38..89c148f0c 100644
--- a/src/BulkEdit.hxx
+++ b/src/BulkEdit.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/CheckAudioFormat.cxx b/src/CheckAudioFormat.cxx
index 03e67e07e..3f4176dc1 100644
--- a/src/CheckAudioFormat.cxx
+++ b/src/CheckAudioFormat.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/CheckAudioFormat.hxx b/src/CheckAudioFormat.hxx
index 67bd88a61..25d82cd5b 100644
--- a/src/CheckAudioFormat.hxx
+++ b/src/CheckAudioFormat.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Chrono.hxx b/src/Chrono.hxx
index cc87c5ba1..d71202841 100644
--- a/src/Chrono.hxx
+++ b/src/Chrono.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include <utility>
#include <cstdint>
-#if defined(__GNUC__) && !GCC_CHECK_VERSION(4,7) && !defined(__clang__)
+#if GCC_OLDER_THAN(4,7)
/* std::chrono::duration operators are "constexpr" since gcc 4.7 */
#define chrono_constexpr gcc_pure
#else
diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx
index c6e9c69c5..33d8117fb 100644
--- a/src/CommandLine.cxx
+++ b/src/CommandLine.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -98,40 +98,44 @@ static constexpr Domain cmdline_domain("cmdline");
gcc_noreturn
static void version(void)
{
- puts("Music Player Daemon " VERSION
+ printf("Music Player Daemon " VERSION
#ifdef GIT_COMMIT
- " (" GIT_COMMIT ")"
+ " (" GIT_COMMIT ")"
#endif
- "\n"
- "\n"
- "Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\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"
+ "\n"
+ "Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\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"
#ifdef ENABLE_DATABASE
- puts("\n"
- "Database plugins:");
+ "\n"
+ "Database plugins:\n");
for (auto i = database_plugins; *i != nullptr; ++i)
printf(" %s", (*i)->name);
- puts("\n\n"
- "Storage plugins:");
+ printf("\n\n"
+ "Storage plugins:\n");
for (auto i = storage_plugins; *i != nullptr; ++i)
printf(" %s", (*i)->name);
+
+ printf("\n"
#endif
#ifdef ENABLE_NEIGHBOR_PLUGINS
- puts("\n\n"
- "Neighbor plugins:");
+ "\n"
+ "Neighbor plugins:\n");
for (auto i = neighbor_plugins; *i != nullptr; ++i)
printf(" %s", (*i)->name);
+
+ printf("\n"
#endif
- puts("\n\n"
- "Decoders plugins:");
+ "\n"
+ "Decoders plugins:\n");
decoder_plugins_for_each([](const DecoderPlugin &plugin){
printf(" [%s]", plugin.name);
@@ -141,26 +145,31 @@ static void version(void)
for (; *suffixes != nullptr; ++suffixes)
printf(" %s", *suffixes);
- puts("");
+ printf("\n");
});
- puts("\n"
- "Output plugins:");
+ printf("\n"
+ "Tag plugins:\n"
+#ifdef ENABLE_ID3TAG
+ " id3tag"
+#endif
+ "\n\n"
+ "Output plugins:\n");
audio_output_plugins_for_each(plugin)
printf(" %s", plugin->name);
- puts("");
+ printf("\n"
#ifdef ENABLE_ENCODER
- puts("\n"
- "Encoder plugins:");
+ "\n"
+ "Encoder plugins:\n");
encoder_plugins_for_each(plugin)
printf(" %s", plugin->name);
- puts("");
+ printf("\n"
#endif
#ifdef ENABLE_ARCHIVE
- puts("\n"
- "Archive plugins:");
+ "\n"
+ "Archive plugins:\n");
archive_plugins_for_each(plugin) {
printf(" [%s]", plugin->name);
@@ -169,22 +178,24 @@ static void version(void)
for (; *suffixes != nullptr; ++suffixes)
printf(" %s", *suffixes);
- puts("");
+ printf("\n");
}
+
+ printf(""
#endif
- puts("\n"
- "Input plugins:");
+ "\n"
+ "Input plugins:\n");
input_plugins_for_each(plugin)
printf(" %s", plugin->name);
- puts("\n\n"
- "Playlist plugins:");
+ printf("\n\n"
+ "Playlist plugins:\n");
playlist_plugins_for_each(plugin)
printf(" %s", plugin->name);
- puts("\n\n"
- "Protocols:");
+ printf("\n\n"
+ "Protocols:\n");
print_supported_uri_schemes_to_fp(stdout);
exit(EXIT_SUCCESS);
@@ -206,12 +217,12 @@ static void PrintOption(const OptionDef &opt)
gcc_noreturn
static void help(void)
{
- puts("Usage:\n"
- " mpd [OPTION...] [path/to/mpd.conf]\n"
- "\n"
- "Music Player Daemon - a daemon for playing music.\n"
- "\n"
- "Options:");
+ printf("Usage:\n"
+ " mpd [OPTION...] [path/to/mpd.conf]\n"
+ "\n"
+ "Music Player Daemon - a daemon for playing music.\n"
+ "\n"
+ "Options:\n");
PrintOption(opt_help);
PrintOption(opt_kill);
diff --git a/src/CommandLine.hxx b/src/CommandLine.hxx
index d8dedb1fb..38adfdc4d 100644
--- a/src/CommandLine.hxx
+++ b/src/CommandLine.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Compiler.h b/src/Compiler.h
index fea971526..87142fa08 100644
--- a/src/Compiler.h
+++ b/src/Compiler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,8 +28,20 @@
#define GCC_VERSION 0
#endif
+/**
+ * Are we building with the specified version of gcc (not clang or any
+ * other compiler) or newer?
+ */
#define GCC_CHECK_VERSION(major, minor) \
- (defined(__GNUC__) && GCC_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
+ (defined(__GNUC__) && !defined(__clang__) && \
+ GCC_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
+
+/**
+ * Are we building with clang (any version) or at least the specified
+ * gcc version?
+ */
+#define CLANG_OR_GCC_VERSION(major, minor) \
+ (defined(__clang__) || GCC_CHECK_VERSION(major, minor))
/**
* Are we building with gcc (not clang or any other compiler) and a
@@ -59,7 +71,7 @@
(defined(__clang__) && \
CLANG_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
-#if GCC_CHECK_VERSION(4,0)
+#if CLANG_OR_GCC_VERSION(4,0)
/* GCC 4.x */
@@ -119,7 +131,7 @@
#endif
-#if GCC_CHECK_VERSION(4,3)
+#if CLANG_OR_GCC_VERSION(4,3)
#define gcc_hot __attribute__((hot))
#define gcc_cold __attribute__((cold))
@@ -131,7 +143,7 @@
#endif /* ! GCC_UNUSED >= 40300 */
-#if GCC_CHECK_VERSION(4,6) && !defined(__clang__)
+#if GCC_CHECK_VERSION(4,6)
#define gcc_flatten __attribute__((flatten))
#else
#define gcc_flatten
@@ -140,7 +152,7 @@
#ifndef __cplusplus
/* plain C99 has "restrict" */
#define gcc_restrict restrict
-#elif GCC_CHECK_VERSION(4,0)
+#elif CLANG_OR_GCC_VERSION(4,0)
/* "__restrict__" is a GCC extension for C++ */
#define gcc_restrict __restrict__
#else
@@ -158,7 +170,7 @@
#define final
#endif
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
#define gcc_alignas(T, fallback) alignas(T)
#else
#define gcc_alignas(T, fallback) gcc_aligned(fallback)
diff --git a/src/CrossFade.cxx b/src/CrossFade.cxx
index e3cc95b0d..6d7b41440 100644
--- a/src/CrossFade.cxx
+++ b/src/CrossFade.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/CrossFade.hxx b/src/CrossFade.hxx
index 81e96e8d3..672abb718 100644
--- a/src/CrossFade.hxx
+++ b/src/CrossFade.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/DetachedSong.cxx b/src/DetachedSong.cxx
index 906e29bba..ca914498b 100644
--- a/src/DetachedSong.cxx
+++ b/src/DetachedSong.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/DetachedSong.hxx b/src/DetachedSong.hxx
index 021b5de29..c3d9f6289 100644
--- a/src/DetachedSong.hxx
+++ b/src/DetachedSong.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,6 @@ struct LightSong;
class Storage;
class DetachedSong {
- friend DetachedSong map_song_detach(const LightSong &song);
friend DetachedSong DatabaseDetachSong(const Storage &db,
const LightSong &song);
diff --git a/src/GlobalEvents.cxx b/src/GlobalEvents.cxx
index 9c60f6357..8cbb85861 100644
--- a/src/GlobalEvents.cxx
+++ b/src/GlobalEvents.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/GlobalEvents.hxx b/src/GlobalEvents.hxx
index a9df03724..15ef58a89 100644
--- a/src/GlobalEvents.hxx
+++ b/src/GlobalEvents.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/IOThread.cxx b/src/IOThread.cxx
index e21ede4f3..654433c06 100644
--- a/src/IOThread.cxx
+++ b/src/IOThread.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/IOThread.hxx b/src/IOThread.hxx
index f6f5dffec..99dc696a7 100644
--- a/src/IOThread.hxx
+++ b/src/IOThread.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/IcyMetaDataParser.cxx b/src/IcyMetaDataParser.cxx
index 4c13c2c2c..4fdb81aa1 100644
--- a/src/IcyMetaDataParser.cxx
+++ b/src/IcyMetaDataParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/IcyMetaDataParser.hxx b/src/IcyMetaDataParser.hxx
index 3075485b2..75aa1a9da 100644
--- a/src/IcyMetaDataParser.hxx
+++ b/src/IcyMetaDataParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Idle.cxx b/src/Idle.cxx
index 0b66065de..ee0e3c3da 100644
--- a/src/Idle.cxx
+++ b/src/Idle.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Idle.hxx b/src/Idle.hxx
index fb7150f98..95773d8d1 100644
--- a/src/Idle.hxx
+++ b/src/Idle.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Instance.cxx b/src/Instance.cxx
index 232cd21df..77059c26c 100644
--- a/src/Instance.cxx
+++ b/src/Instance.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include "Partition.hxx"
#include "Idle.hxx"
#include "Stats.hxx"
+#include "util/Error.hxx"
#ifdef ENABLE_DATABASE
#include "db/DatabaseError.hxx"
@@ -76,7 +77,7 @@ Instance::OnDatabaseSongRemoved(const LightSong &song)
#ifdef ENABLE_SQLITE
/* if the song has a sticker, remove it */
if (sticker_enabled())
- sticker_song_delete(song);
+ sticker_song_delete(song, IgnoreError());
#endif
const auto uri = song.GetURI();
diff --git a/src/Instance.hxx b/src/Instance.hxx
index fa7711ab9..d8e485c74 100644
--- a/src/Instance.hxx
+++ b/src/Instance.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Listen.cxx b/src/Listen.cxx
index d48d795d1..c360b9650 100644
--- a/src/Listen.cxx
+++ b/src/Listen.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#include "config.h"
#include "Listen.hxx"
#include "client/Client.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "event/ServerSocket.hxx"
@@ -103,9 +103,9 @@ listen_systemd_activation(Error &error_r)
bool
listen_global_init(EventLoop &loop, Partition &partition, Error &error)
{
- int port = config_get_positive(CONF_PORT, DEFAULT_PORT);
+ int port = config_get_positive(ConfigOption::PORT, DEFAULT_PORT);
const struct config_param *param =
- config_get_param(CONF_BIND_TO_ADDRESS);
+ config_get_param(ConfigOption::BIND_TO_ADDRESS);
listen_socket = new ClientListener(loop, partition);
diff --git a/src/Listen.hxx b/src/Listen.hxx
index d74c1d233..b644c3a8d 100644
--- a/src/Listen.hxx
+++ b/src/Listen.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Log.cxx b/src/Log.cxx
index ba691581b..585e51f7c 100644
--- a/src/Log.cxx
+++ b/src/Log.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Log.hxx b/src/Log.hxx
index 15077e374..684d5c394 100644
--- a/src/Log.hxx
+++ b/src/Log.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/LogBackend.cxx b/src/LogBackend.cxx
index 04c2e6324..64d523443 100644
--- a/src/LogBackend.cxx
+++ b/src/LogBackend.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/LogBackend.hxx b/src/LogBackend.hxx
index 23df2037e..c6fe797f1 100644
--- a/src/LogBackend.hxx
+++ b/src/LogBackend.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/LogInit.cxx b/src/LogInit.cxx
index 117c6d8dc..f0f00495f 100644
--- a/src/LogInit.cxx
+++ b/src/LogInit.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
#include "LogInit.hxx"
#include "LogBackend.hxx"
#include "Log.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "system/FatalError.hxx"
@@ -72,14 +72,14 @@ open_log_file(void)
}
static bool
-log_init_file(unsigned line, Error &error)
+log_init_file(int line, Error &error)
{
assert(!out_path.IsNull());
out_fd = open_log_file();
if (out_fd < 0) {
const std::string out_path_utf8 = out_path.ToUTF8();
- error.FormatErrno("failed to open log file \"%s\" (config line %u)",
+ error.FormatErrno("failed to open log file \"%s\" (config line %d)",
out_path_utf8.c_str(), line);
return false;
}
@@ -89,7 +89,7 @@ log_init_file(unsigned line, Error &error)
}
static inline LogLevel
-parse_log_level(const char *value, unsigned line)
+parse_log_level(const char *value, int line)
{
if (0 == strcmp(value, "default"))
return LogLevel::DEFAULT;
@@ -98,7 +98,7 @@ parse_log_level(const char *value, unsigned line)
else if (0 == strcmp(value, "verbose"))
return LogLevel::DEBUG;
else {
- FormatFatalError("unknown log level \"%s\" at line %u",
+ FormatFatalError("unknown log level \"%s\" at line %d",
value, line);
}
}
@@ -139,14 +139,14 @@ log_init(bool verbose, bool use_stdout, Error &error)
if (verbose)
SetLogThreshold(LogLevel::DEBUG);
- else if ((param = config_get_param(CONF_LOG_LEVEL)) != nullptr)
+ else if ((param = config_get_param(ConfigOption::LOG_LEVEL)) != nullptr)
SetLogThreshold(parse_log_level(param->value.c_str(),
param->line));
if (use_stdout) {
return true;
} else {
- param = config_get_param(CONF_LOG_FILE);
+ param = config_get_param(ConfigOption::LOG_FILE);
if (param == nullptr) {
#ifdef HAVE_SYSLOG
/* no configuration: default to syslog (if
@@ -164,7 +164,7 @@ log_init(bool verbose, bool use_stdout, Error &error)
return true;
#endif
} else {
- out_path = config_get_path(CONF_LOG_FILE, error);
+ out_path = config_get_path(ConfigOption::LOG_FILE, error);
return !out_path.IsNull() &&
log_init_file(param->line, error);
}
diff --git a/src/LogInit.hxx b/src/LogInit.hxx
index d0bcb40f2..b29c0a847 100644
--- a/src/LogInit.hxx
+++ b/src/LogInit.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/LogLevel.hxx b/src/LogLevel.hxx
index 2614a67d1..64c12e009 100644
--- a/src/LogLevel.hxx
+++ b/src/LogLevel.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/LogV.hxx b/src/LogV.hxx
index 6b16f82b4..7b108936d 100644
--- a/src/LogV.hxx
+++ b/src/LogV.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Main.cxx b/src/Main.cxx
index 26d4e7ae4..9b7679369 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -50,7 +50,6 @@
#include "AudioConfig.hxx"
#include "pcm/PcmConvert.hxx"
#include "unix/SignalHandlers.hxx"
-#include "unix/Daemon.hxx"
#include "system/FatalError.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
@@ -59,12 +58,16 @@
#include "thread/Slack.hxx"
#include "lib/icu/Init.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigDefaults.hxx"
#include "config/ConfigOption.hxx"
#include "config/ConfigError.hxx"
#include "Stats.hxx"
+#ifdef ENABLE_DAEMON
+#include "unix/Daemon.hxx"
+#endif
+
#ifdef ENABLE_DATABASE
#include "db/update/Service.hxx"
#include "db/Configured.hxx"
@@ -133,17 +136,17 @@ Instance *instance;
static StateFile *state_file;
-#ifndef ANDROID
+#ifdef ENABLE_DAEMON
static bool
glue_daemonize_init(const struct options *options, Error &error)
{
- auto pid_file = config_get_path(CONF_PID_FILE, error);
+ auto pid_file = config_get_path(ConfigOption::PID_FILE, error);
if (pid_file.IsNull() && error.IsDefined())
return false;
- daemonize_init(config_get_string(CONF_USER, nullptr),
- config_get_string(CONF_GROUP, nullptr),
+ daemonize_init(config_get_string(ConfigOption::USER, nullptr),
+ config_get_string(ConfigOption::GROUP, nullptr),
std::move(pid_file));
if (options->kill)
@@ -157,7 +160,7 @@ glue_daemonize_init(const struct options *options, Error &error)
static bool
glue_mapper_init(Error &error)
{
- auto playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error);
+ auto playlist_dir = config_get_path(ConfigOption::PLAYLIST_DIR, error);
if (playlist_dir.IsNull() && error.IsDefined())
return false;
@@ -252,7 +255,7 @@ glue_sticker_init(void)
{
#ifdef ENABLE_SQLITE
Error error;
- auto sticker_file = config_get_path(CONF_STICKER_FILE, error);
+ auto sticker_file = config_get_path(ConfigOption::STICKER_FILE, error);
if (sticker_file.IsNull()) {
if (error.IsDefined())
FatalError(error);
@@ -267,7 +270,7 @@ glue_sticker_init(void)
static bool
glue_state_file_init(Error &error)
{
- auto path_fs = config_get_path(CONF_STATE_FILE, error);
+ auto path_fs = config_get_path(ConfigOption::STATE_FILE, error);
if (path_fs.IsNull()) {
if (error.IsDefined())
return false;
@@ -283,8 +286,9 @@ glue_state_file_init(Error &error)
#endif
}
- unsigned interval = config_get_unsigned(CONF_STATE_FILE_INTERVAL,
- StateFile::DEFAULT_INTERVAL);
+ const unsigned interval =
+ config_get_unsigned(ConfigOption::STATE_FILE_INTERVAL,
+ StateFile::DEFAULT_INTERVAL);
state_file = new StateFile(std::move(path_fs), interval,
*instance->partition,
@@ -321,7 +325,7 @@ initialize_decoder_and_player(void)
const struct config_param *param;
size_t buffer_size;
- param = config_get_param(CONF_AUDIO_BUFFER_SIZE);
+ param = config_get_param(ConfigOption::AUDIO_BUFFER_SIZE);
if (param != nullptr) {
char *test;
long tmp = strtol(param->value.c_str(), &test, 10);
@@ -342,7 +346,7 @@ initialize_decoder_and_player(void)
(unsigned long)buffer_size);
float perc;
- param = config_get_param(CONF_BUFFER_BEFORE_PLAY);
+ param = config_get_param(ConfigOption::BUFFER_BEFORE_PLAY);
if (param != nullptr) {
char *test;
perc = strtod(param->value.c_str(), &test);
@@ -360,7 +364,7 @@ initialize_decoder_and_player(void)
buffered_before_play = buffered_chunks;
const unsigned max_length =
- config_get_positive(CONF_MAX_PLAYLIST_LENGTH,
+ config_get_positive(ConfigOption::MAX_PLAYLIST_LENGTH,
DEFAULT_PLAYLIST_MAX_LENGTH);
instance->partition = new Partition(*instance,
@@ -422,9 +426,11 @@ int mpd_main(int argc, char *argv[])
struct options options;
Error error;
-#ifndef ANDROID
+#ifdef ENABLE_DAEMON
daemonize_close_stdin();
+#endif
+#ifndef ANDROID
#ifdef HAVE_LOCALE_H
/* initialize locale */
setlocale(LC_CTYPE,"");
@@ -432,11 +438,6 @@ int mpd_main(int argc, char *argv[])
#ifdef HAVE_GLIB
g_set_application_name("Music Player Daemon");
-
-#if !GLIB_CHECK_VERSION(2,32,0)
- /* enable GLib's thread safety code */
- g_thread_init(nullptr);
-#endif
#endif
#endif
@@ -470,7 +471,9 @@ int mpd_main(int argc, char *argv[])
LogError(error);
return EXIT_FAILURE;
}
+#endif
+#ifdef ENABLE_DAEMON
if (!glue_daemonize_init(&options, error)) {
LogError(error);
return EXIT_FAILURE;
@@ -501,7 +504,8 @@ int mpd_main(int argc, char *argv[])
}
#endif
- const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10);
+ const unsigned max_clients =
+ config_get_positive(ConfigOption::MAX_CONN, 10);
instance->client_list = new ClientList(max_clients);
initialize_decoder_and_player();
@@ -512,7 +516,7 @@ int mpd_main(int argc, char *argv[])
return EXIT_FAILURE;
}
-#ifndef ANDROID
+#ifdef ENABLE_DAEMON
daemonize_set_user();
daemonize_begin(options.daemon);
#endif
@@ -544,7 +548,10 @@ static int mpd_main_after_fork(struct options options)
GlobalEvents::Register(GlobalEvents::SHUTDOWN, shutdown_event_emitted);
#endif
- ConfigureFS();
+ if (!ConfigureFS(error)) {
+ LogError(error);
+ return EXIT_FAILURE;
+ }
if (!glue_mapper_init(error)) {
LogError(error);
@@ -585,9 +592,11 @@ static int mpd_main_after_fork(struct options options)
playlist_list_global_init();
-#ifndef ANDROID
+#ifdef ENABLE_DAEMON
daemonize_commit();
+#endif
+#ifndef ANDROID
setup_log_output(options.log_stderr);
SignalHandlersInit(*instance->event_loop);
@@ -623,14 +632,14 @@ static int mpd_main_after_fork(struct options options)
instance->partition->outputs.SetReplayGainMode(replay_gain_get_real_mode(instance->partition->playlist.queue.random));
#ifdef ENABLE_DATABASE
- if (config_get_bool(CONF_AUTO_UPDATE, false)) {
+ if (config_get_bool(ConfigOption::AUTO_UPDATE, false)) {
#ifdef ENABLE_INOTIFY
if (instance->storage != nullptr &&
instance->update != nullptr)
mpd_inotify_init(*instance->event_loop,
*instance->storage,
*instance->update,
- config_get_unsigned(CONF_AUTO_UPDATE_DEPTH,
+ config_get_unsigned(ConfigOption::AUTO_UPDATE_DEPTH,
INT_MAX));
#else
FormatWarning(main_domain,
@@ -710,6 +719,8 @@ static int mpd_main_after_fork(struct options options)
mapper_finish();
#endif
+ DeinitFS();
+
delete instance->partition;
command_finish();
decoder_plugin_deinit_all();
@@ -724,9 +735,11 @@ static int mpd_main_after_fork(struct options options)
delete instance->event_loop;
delete instance;
instance = nullptr;
-#ifndef ANDROID
+
+#ifdef ENABLE_DAEMON
daemonize_finish();
#endif
+
#ifdef WIN32
WSACleanup();
#endif
diff --git a/src/Main.hxx b/src/Main.hxx
index 7e3fecd0b..84a0c41a1 100644
--- a/src/Main.hxx
+++ b/src/Main.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Mapper.cxx b/src/Mapper.cxx
index 7baad9459..1dff3949c 100644
--- a/src/Mapper.cxx
+++ b/src/Mapper.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Mapper.hxx b/src/Mapper.hxx
index 7ff41f239..95bd81a49 100644
--- a/src/Mapper.hxx
+++ b/src/Mapper.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MixRampInfo.hxx b/src/MixRampInfo.hxx
index 90c2c984a..297adfe07 100644
--- a/src/MixRampInfo.hxx
+++ b/src/MixRampInfo.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicBuffer.cxx b/src/MusicBuffer.cxx
index 709b40413..5de94508a 100644
--- a/src/MusicBuffer.cxx
+++ b/src/MusicBuffer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicBuffer.hxx b/src/MusicBuffer.hxx
index cf7c90f91..60b792f3a 100644
--- a/src/MusicBuffer.hxx
+++ b/src/MusicBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicChunk.cxx b/src/MusicChunk.cxx
index 3cfd232c0..9f09b35c5 100644
--- a/src/MusicChunk.cxx
+++ b/src/MusicChunk.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicChunk.hxx b/src/MusicChunk.hxx
index 805112d02..9d7fda146 100644
--- a/src/MusicChunk.hxx
+++ b/src/MusicChunk.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicPipe.cxx b/src/MusicPipe.cxx
index 43ce2dbb2..cd874eb33 100644
--- a/src/MusicPipe.cxx
+++ b/src/MusicPipe.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/MusicPipe.hxx b/src/MusicPipe.hxx
index 4f29d0728..078530abb 100644
--- a/src/MusicPipe.hxx
+++ b/src/MusicPipe.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Partition.cxx b/src/Partition.cxx
index de1170557..31a64a355 100644
--- a/src/Partition.cxx
+++ b/src/Partition.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Partition.hxx b/src/Partition.hxx
index d89c4b41f..6f340d0d9 100644
--- a/src/Partition.hxx
+++ b/src/Partition.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Permission.cxx b/src/Permission.cxx
index d6c267ab7..b6ff39bdb 100644
--- a/src/Permission.cxx
+++ b/src/Permission.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,7 @@
#include "config.h"
#include "Permission.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "system/FatalError.hxx"
@@ -92,7 +92,7 @@ void initPermissions(void)
permission_default = PERMISSION_READ | PERMISSION_ADD |
PERMISSION_CONTROL | PERMISSION_ADMIN;
- param = config_get_param(CONF_PASSWORD);
+ param = config_get_param(ConfigOption::PASSWORD);
if (param) {
permission_default = 0;
@@ -118,7 +118,7 @@ void initPermissions(void)
} while ((param = param->next) != nullptr);
}
- param = config_get_param(CONF_DEFAULT_PERMS);
+ param = config_get_param(ConfigOption::DEFAULT_PERMS);
if (param)
permission_default = parsePermissions(param->value.c_str());
diff --git a/src/Permission.hxx b/src/Permission.hxx
index 60761c696..b77fef4e8 100644
--- a/src/Permission.hxx
+++ b/src/Permission.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlayerControl.cxx b/src/PlayerControl.cxx
index 4f1c3d2ac..972b33361 100644
--- a/src/PlayerControl.cxx
+++ b/src/PlayerControl.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlayerControl.hxx b/src/PlayerControl.hxx
index 4d06a1827..a2807a9a1 100644
--- a/src/PlayerControl.hxx
+++ b/src/PlayerControl.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlayerListener.hxx b/src/PlayerListener.hxx
index 06f00a4f5..e10f2547b 100644
--- a/src/PlayerListener.hxx
+++ b/src/PlayerListener.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlayerThread.cxx b/src/PlayerThread.cxx
index c5308e612..a320e81fb 100644
--- a/src/PlayerThread.cxx
+++ b/src/PlayerThread.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlayerThread.hxx b/src/PlayerThread.hxx
index 537e38399..128273aa7 100644
--- a/src/PlayerThread.hxx
+++ b/src/PlayerThread.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx
index 3421ecb02..75cb699b8 100644
--- a/src/PlaylistDatabase.cxx
+++ b/src/PlaylistDatabase.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistDatabase.hxx b/src/PlaylistDatabase.hxx
index 17f82f64b..078530c75 100644
--- a/src/PlaylistDatabase.hxx
+++ b/src/PlaylistDatabase.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistError.cxx b/src/PlaylistError.cxx
index 085246f15..d069dd3a3 100644
--- a/src/PlaylistError.cxx
+++ b/src/PlaylistError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistError.hxx b/src/PlaylistError.hxx
index 0f2424f41..500acd711 100644
--- a/src/PlaylistError.hxx
+++ b/src/PlaylistError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx
index ab269378a..f77d1930f 100644
--- a/src/PlaylistFile.cxx
+++ b/src/PlaylistFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -53,11 +53,12 @@ bool playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
void
spl_global_init(void)
{
- playlist_max_length = config_get_positive(CONF_MAX_PLAYLIST_LENGTH,
- DEFAULT_PLAYLIST_MAX_LENGTH);
+ playlist_max_length =
+ config_get_positive(ConfigOption::MAX_PLAYLIST_LENGTH,
+ DEFAULT_PLAYLIST_MAX_LENGTH);
playlist_saveAbsolutePaths =
- config_get_bool(CONF_SAVE_ABSOLUTE_PATHS,
+ config_get_bool(ConfigOption::SAVE_ABSOLUTE_PATHS,
DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS);
}
diff --git a/src/PlaylistFile.hxx b/src/PlaylistFile.hxx
index 7154b1f84..eacc54be7 100644
--- a/src/PlaylistFile.hxx
+++ b/src/PlaylistFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistGlobal.cxx b/src/PlaylistGlobal.cxx
index dacfad0c7..fb65843f5 100644
--- a/src/PlaylistGlobal.cxx
+++ b/src/PlaylistGlobal.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistGlobal.hxx b/src/PlaylistGlobal.hxx
index a2e3bb030..244eed702 100644
--- a/src/PlaylistGlobal.hxx
+++ b/src/PlaylistGlobal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx
index cfa56c7b3..069fbf430 100644
--- a/src/PlaylistPrint.cxx
+++ b/src/PlaylistPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistPrint.hxx b/src/PlaylistPrint.hxx
index 38a4cc7cf..e0fcc2c2d 100644
--- a/src/PlaylistPrint.hxx
+++ b/src/PlaylistPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx
index 67f05267f..0653da44c 100644
--- a/src/PlaylistSave.cxx
+++ b/src/PlaylistSave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/PlaylistSave.hxx b/src/PlaylistSave.hxx
index 914c8c086..5b2a84dfb 100644
--- a/src/PlaylistSave.hxx
+++ b/src/PlaylistSave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/ReplayGainConfig.cxx b/src/ReplayGainConfig.cxx
index c3bbcac3c..b8a907cdc 100644
--- a/src/ReplayGainConfig.cxx
+++ b/src/ReplayGainConfig.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#include "config.h"
#include "ReplayGainConfig.hxx"
#include "Idle.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigGlobal.hxx"
#include "system/FatalError.hxx"
@@ -81,7 +81,8 @@ replay_gain_set_mode_string(const char *p)
void replay_gain_global_init(void)
{
- const struct config_param *param = config_get_param(CONF_REPLAYGAIN);
+ const struct config_param *param =
+ config_get_param(ConfigOption::REPLAYGAIN);
if (param != nullptr &&
!replay_gain_set_mode_string(param->value.c_str())) {
@@ -89,7 +90,7 @@ void replay_gain_global_init(void)
param->value.c_str(), param->line);
}
- param = config_get_param(CONF_REPLAYGAIN_PREAMP);
+ param = config_get_param(ConfigOption::REPLAYGAIN_PREAMP);
if (param) {
char *test;
@@ -110,7 +111,7 @@ void replay_gain_global_init(void)
replay_gain_preamp = pow(10, f / 20.0);
}
- param = config_get_param(CONF_REPLAYGAIN_MISSING_PREAMP);
+ param = config_get_param(ConfigOption::REPLAYGAIN_MISSING_PREAMP);
if (param) {
char *test;
@@ -131,7 +132,8 @@ void replay_gain_global_init(void)
replay_gain_missing_preamp = pow(10, f / 20.0);
}
- replay_gain_limit = config_get_bool(CONF_REPLAYGAIN_LIMIT, DEFAULT_REPLAYGAIN_LIMIT);
+ replay_gain_limit = config_get_bool(ConfigOption::REPLAYGAIN_LIMIT,
+ DEFAULT_REPLAYGAIN_LIMIT);
}
ReplayGainMode
diff --git a/src/ReplayGainConfig.hxx b/src/ReplayGainConfig.hxx
index e498a56dd..1f36a28e5 100644
--- a/src/ReplayGainConfig.hxx
+++ b/src/ReplayGainConfig.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/ReplayGainInfo.cxx b/src/ReplayGainInfo.cxx
index 580773521..98aa3360d 100644
--- a/src/ReplayGainInfo.cxx
+++ b/src/ReplayGainInfo.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/ReplayGainInfo.hxx b/src/ReplayGainInfo.hxx
index 37815c933..c94cb1fa8 100644
--- a/src/ReplayGainInfo.hxx
+++ b/src/ReplayGainInfo.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -39,8 +39,7 @@ struct ReplayGainTuple {
peak = 0.0;
}
- gcc_pure
- bool IsDefined() const {
+ constexpr bool IsDefined() const {
return gain > -100;
}
@@ -52,6 +51,11 @@ struct ReplayGainTuple {
struct ReplayGainInfo {
ReplayGainTuple tuples[2];
+ constexpr bool IsDefined() const {
+ return tuples[REPLAY_GAIN_ALBUM].IsDefined() ||
+ tuples[REPLAY_GAIN_TRACK].IsDefined();
+ }
+
void Clear() {
tuples[REPLAY_GAIN_ALBUM].Clear();
tuples[REPLAY_GAIN_TRACK].Clear();
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index dc0a63df3..d979267ef 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index f51bd85c6..8801f35ea 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongLoader.cxx b/src/SongLoader.cxx
index 43e57e93b..e66e60e70 100644
--- a/src/SongLoader.cxx
+++ b/src/SongLoader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongLoader.hxx b/src/SongLoader.hxx
index 229703972..73f9b1f7b 100644
--- a/src/SongLoader.hxx
+++ b/src/SongLoader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx
index 05d462b6d..e5e5ebb76 100644
--- a/src/SongPrint.cxx
+++ b/src/SongPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -122,5 +122,8 @@ song_print_info(Client &client, const DetachedSong &song, bool base)
const auto duration = song.GetDuration();
if (!duration.IsNegative())
- client_printf(client, "Time: %u\n", duration.RoundS());
+ client_printf(client, "Time: %i\n"
+ "duration: %1.3f\n",
+ duration.RoundS(),
+ duration.ToDoubleS());
}
diff --git a/src/SongPrint.hxx b/src/SongPrint.hxx
index 5e4c93a74..5b9a507ac 100644
--- a/src/SongPrint.hxx
+++ b/src/SongPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongSave.cxx b/src/SongSave.cxx
index 895e9805b..8cf3a17ba 100644
--- a/src/SongSave.cxx
+++ b/src/SongSave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongSave.hxx b/src/SongSave.hxx
index 28c217249..318f3cf33 100644
--- a/src/SongSave.hxx
+++ b/src/SongSave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx
index 0245b9117..f3ef5f8e8 100644
--- a/src/SongUpdate.cxx
+++ b/src/SongUpdate.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/StateFile.cxx b/src/StateFile.cxx
index 7e9e35cc3..ebf6cf576 100644
--- a/src/StateFile.cxx
+++ b/src/StateFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/StateFile.hxx b/src/StateFile.hxx
index 15ba13b97..b96b89dfb 100644
--- a/src/StateFile.hxx
+++ b/src/StateFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Stats.cxx b/src/Stats.cxx
index 39d371ace..cb33ecad3 100644
--- a/src/Stats.cxx
+++ b/src/Stats.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/Stats.hxx b/src/Stats.hxx
index 0d36ec0b2..d3f24c632 100644
--- a/src/Stats.hxx
+++ b/src/Stats.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagFile.cxx b/src/TagFile.cxx
index 7655b96ff..e4e9914e4 100644
--- a/src/TagFile.cxx
+++ b/src/TagFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagFile.hxx b/src/TagFile.hxx
index b11a8ac1c..6c2c5b4bf 100644
--- a/src/TagFile.hxx
+++ b/src/TagFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagPrint.cxx b/src/TagPrint.cxx
index 4937fa622..39027ba11 100644
--- a/src/TagPrint.cxx
+++ b/src/TagPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,8 +23,6 @@
#include "tag/TagSettings.h"
#include "client/Client.hxx"
-#define SONG_TIME "Time: "
-
void tag_print_types(Client &client)
{
int i;
@@ -53,7 +51,10 @@ tag_print_values(Client &client, const Tag &tag)
void tag_print(Client &client, const Tag &tag)
{
if (!tag.duration.IsNegative())
- client_printf(client, SONG_TIME "%i\n", tag.duration.RoundS());
+ client_printf(client, "Time: %i\n"
+ "duration: %1.3f\n",
+ tag.duration.RoundS(),
+ tag.duration.ToDoubleS());
tag_print_values(client, tag);
}
diff --git a/src/TagPrint.hxx b/src/TagPrint.hxx
index 6675bb7d8..70cb6323a 100644
--- a/src/TagPrint.hxx
+++ b/src/TagPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagSave.cxx b/src/TagSave.cxx
index 107aca7db..e81de8dfd 100644
--- a/src/TagSave.cxx
+++ b/src/TagSave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagSave.hxx b/src/TagSave.hxx
index fd4b91f98..9b71849b9 100644
--- a/src/TagSave.hxx
+++ b/src/TagSave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagStream.cxx b/src/TagStream.cxx
index 6201028f6..dd5d8f7ec 100644
--- a/src/TagStream.cxx
+++ b/src/TagStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TagStream.hxx b/src/TagStream.hxx
index 71dd71ff7..e1bd25b56 100644
--- a/src/TagStream.hxx
+++ b/src/TagStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TimePrint.cxx b/src/TimePrint.cxx
index 5526ec7d6..326743869 100644
--- a/src/TimePrint.cxx
+++ b/src/TimePrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/TimePrint.hxx b/src/TimePrint.hxx
index afdb3c1c9..8f1f21050 100644
--- a/src/TimePrint.hxx
+++ b/src/TimePrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/android/Context.cxx b/src/android/Context.cxx
index f75e1503e..eba00363c 100644
--- a/src/android/Context.cxx
+++ b/src/android/Context.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/android/Context.hxx b/src/android/Context.hxx
index b8a47777d..0dd1cc124 100644
--- a/src/android/Context.hxx
+++ b/src/android/Context.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/android/Environment.cxx b/src/android/Environment.cxx
index 9813b0b79..29b2a9841 100644
--- a/src/android/Environment.cxx
+++ b/src/android/Environment.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/android/Environment.hxx b/src/android/Environment.hxx
index 5a54ea361..c2e5ff3bd 100644
--- a/src/android/Environment.hxx
+++ b/src/android/Environment.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveDomain.cxx b/src/archive/ArchiveDomain.cxx
index 4adf4a886..801b3879a 100644
--- a/src/archive/ArchiveDomain.cxx
+++ b/src/archive/ArchiveDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveDomain.hxx b/src/archive/ArchiveDomain.hxx
index 817ae5835..50ac7235e 100644
--- a/src/archive/ArchiveDomain.hxx
+++ b/src/archive/ArchiveDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveFile.hxx b/src/archive/ArchiveFile.hxx
index 473eef70b..2afd9f7f7 100644
--- a/src/archive/ArchiveFile.hxx
+++ b/src/archive/ArchiveFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveList.cxx b/src/archive/ArchiveList.cxx
index 79c3a16fe..709db4dc0 100644
--- a/src/archive/ArchiveList.cxx
+++ b/src/archive/ArchiveList.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,13 +29,13 @@
#include <string.h>
const ArchivePlugin *const archive_plugins[] = {
-#ifdef HAVE_BZ2
+#ifdef ENABLE_BZ2
&bz2_archive_plugin,
#endif
-#ifdef HAVE_ZZIP
+#ifdef ENABLE_ZZIP
&zzip_archive_plugin,
#endif
-#ifdef HAVE_ISO9660
+#ifdef ENABLE_ISO9660
&iso9660_archive_plugin,
#endif
nullptr
diff --git a/src/archive/ArchiveList.hxx b/src/archive/ArchiveList.hxx
index 1f1b0ae96..7efe03914 100644
--- a/src/archive/ArchiveList.hxx
+++ b/src/archive/ArchiveList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveLookup.cxx b/src/archive/ArchiveLookup.cxx
index 53730c504..78e2c48d0 100644
--- a/src/archive/ArchiveLookup.cxx
+++ b/src/archive/ArchiveLookup.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveLookup.hxx b/src/archive/ArchiveLookup.hxx
index 0c08951a9..4154e4e2f 100644
--- a/src/archive/ArchiveLookup.hxx
+++ b/src/archive/ArchiveLookup.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchivePlugin.cxx b/src/archive/ArchivePlugin.cxx
index 67f469e08..ff16c0dd5 100644
--- a/src/archive/ArchivePlugin.cxx
+++ b/src/archive/ArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchivePlugin.hxx b/src/archive/ArchivePlugin.hxx
index eb24bbdf9..87b1a6ba0 100644
--- a/src/archive/ArchivePlugin.hxx
+++ b/src/archive/ArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/ArchiveVisitor.hxx b/src/archive/ArchiveVisitor.hxx
index 6759695ca..c0b09da28 100644
--- a/src/archive/ArchiveVisitor.hxx
+++ b/src/archive/ArchiveVisitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx
index 2b92049dd..3b40e0b36 100644
--- a/src/archive/plugins/Bzip2ArchivePlugin.cxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ public:
Bzip2ArchiveFile(Path path, InputStream *_is)
:ArchiveFile(bz2_archive_plugin),
- name(PathTraitsFS::GetBase(path.c_str())),
+ name(path.GetBase().c_str()),
istream(_is) {
// remove .bz2 suffix
const size_t len = name.length();
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.hxx b/src/archive/plugins/Bzip2ArchivePlugin.hxx
index 1a0a578d1..6bb439d7a 100644
--- a/src/archive/plugins/Bzip2ArchivePlugin.hxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx
index ba415d3c5..e25cd0af7 100644
--- a/src/archive/plugins/Iso9660ArchivePlugin.cxx
+++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/plugins/Iso9660ArchivePlugin.hxx b/src/archive/plugins/Iso9660ArchivePlugin.hxx
index 9335e83b3..baec9c407 100644
--- a/src/archive/plugins/Iso9660ArchivePlugin.hxx
+++ b/src/archive/plugins/Iso9660ArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/plugins/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx
index 21cb693d8..4be12b7ed 100644
--- a/src/archive/plugins/ZzipArchivePlugin.cxx
+++ b/src/archive/plugins/ZzipArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/archive/plugins/ZzipArchivePlugin.hxx b/src/archive/plugins/ZzipArchivePlugin.hxx
index cc92b7c52..f214584bc 100644
--- a/src/archive/plugins/ZzipArchivePlugin.hxx
+++ b/src/archive/plugins/ZzipArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/check.h b/src/check.h
index efb4556d1..72826a1dc 100644
--- a/src/check.h
+++ b/src/check.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/Client.cxx b/src/client/Client.cxx
index 01ead4645..d5d153a46 100644
--- a/src/client/Client.cxx
+++ b/src/client/Client.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/Client.hxx b/src/client/Client.hxx
index c0a940ded..ef7f4c406 100644
--- a/src/client/Client.hxx
+++ b/src/client/Client.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientEvent.cxx b/src/client/ClientEvent.cxx
index fd9f24b0d..cfc638f63 100644
--- a/src/client/ClientEvent.cxx
+++ b/src/client/ClientEvent.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientExpire.cxx b/src/client/ClientExpire.cxx
index 5891756b6..70527312d 100644
--- a/src/client/ClientExpire.cxx
+++ b/src/client/ClientExpire.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientFile.cxx b/src/client/ClientFile.cxx
index 3ea8034d2..9bf977704 100644
--- a/src/client/ClientFile.cxx
+++ b/src/client/ClientFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientGlobal.cxx b/src/client/ClientGlobal.cxx
index 8d90721e9..078fd0981 100644
--- a/src/client/ClientGlobal.cxx
+++ b/src/client/ClientGlobal.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -31,15 +31,15 @@ size_t client_max_output_buffer_size;
void client_manager_init(void)
{
- client_timeout = config_get_positive(CONF_CONN_TIMEOUT,
+ client_timeout = config_get_positive(ConfigOption::CONN_TIMEOUT,
CLIENT_TIMEOUT_DEFAULT);
client_max_command_list_size =
- config_get_positive(CONF_MAX_COMMAND_LIST_SIZE,
+ config_get_positive(ConfigOption::MAX_COMMAND_LIST_SIZE,
CLIENT_MAX_COMMAND_LIST_DEFAULT / 1024)
* 1024;
client_max_output_buffer_size =
- config_get_positive(CONF_MAX_OUTPUT_BUFFER_SIZE,
+ config_get_positive(ConfigOption::MAX_OUTPUT_BUFFER_SIZE,
CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT / 1024)
* 1024;
}
diff --git a/src/client/ClientIdle.cxx b/src/client/ClientIdle.cxx
index 0b4fa5751..b43647b6c 100644
--- a/src/client/ClientIdle.cxx
+++ b/src/client/ClientIdle.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientInternal.hxx b/src/client/ClientInternal.hxx
index a819d64b8..66bdfbb0f 100644
--- a/src/client/ClientInternal.hxx
+++ b/src/client/ClientInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientList.cxx b/src/client/ClientList.cxx
index a1f286928..43a35798f 100644
--- a/src/client/ClientList.cxx
+++ b/src/client/ClientList.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientList.hxx b/src/client/ClientList.hxx
index 7d20a8737..68292097c 100644
--- a/src/client/ClientList.hxx
+++ b/src/client/ClientList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientMessage.cxx b/src/client/ClientMessage.cxx
index be6d2f007..84838219e 100644
--- a/src/client/ClientMessage.cxx
+++ b/src/client/ClientMessage.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientMessage.hxx b/src/client/ClientMessage.hxx
index bc6a4cd41..3c39fb9d5 100644
--- a/src/client/ClientMessage.hxx
+++ b/src/client/ClientMessage.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientNew.cxx b/src/client/ClientNew.cxx
index a080e9ec6..c820fc584 100644
--- a/src/client/ClientNew.cxx
+++ b/src/client/ClientNew.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientProcess.cxx b/src/client/ClientProcess.cxx
index 0b6953371..2aec79297 100644
--- a/src/client/ClientProcess.cxx
+++ b/src/client/ClientProcess.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientRead.cxx b/src/client/ClientRead.cxx
index 9cfb1271f..7a1e937ed 100644
--- a/src/client/ClientRead.cxx
+++ b/src/client/ClientRead.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientSubscribe.cxx b/src/client/ClientSubscribe.cxx
index 8ea2e363b..ebc4848f5 100644
--- a/src/client/ClientSubscribe.cxx
+++ b/src/client/ClientSubscribe.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/client/ClientWrite.cxx b/src/client/ClientWrite.cxx
index b5d172a8d..a06719770 100644
--- a/src/client/ClientWrite.cxx
+++ b/src/client/ClientWrite.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx
index 6a4b18198..0662cff64 100644
--- a/src/command/AllCommands.cxx
+++ b/src/command/AllCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,8 +35,10 @@
#include "protocol/Result.hxx"
#include "Partition.hxx"
#include "client/Client.hxx"
+#include "util/Macros.hxx"
#include "util/Tokenizer.hxx"
#include "util/Error.hxx"
+#include "util/ConstBuffer.hxx"
#ifdef ENABLE_SQLITE
#include "StickerCommands.hxx"
@@ -60,22 +62,22 @@ struct command {
unsigned permission;
int min;
int max;
- CommandResult (*handler)(Client &client, unsigned argc, char **argv);
+ CommandResult (*handler)(Client &client, ConstBuffer<const char *> args);
};
/* don't be fooled, this is the command handler for "commands" command */
static CommandResult
-handle_commands(Client &client, unsigned argc, char *argv[]);
+handle_commands(Client &client, ConstBuffer<const char *> args);
static CommandResult
-handle_not_commands(Client &client, unsigned argc, char *argv[]);
+handle_not_commands(Client &client, ConstBuffer<const char *> args);
/**
* The command registry.
*
* This array must be sorted!
*/
-static const struct command commands[] = {
+static constexpr struct command commands[] = {
{ "add", PERMISSION_ADD, 1, 1, handle_add },
{ "addid", PERMISSION_ADD, 1, 2, handle_addid },
{ "addtagid", PERMISSION_ADD, 3, 3, handle_addtagid },
@@ -194,7 +196,7 @@ static const struct command commands[] = {
{ "volume", PERMISSION_CONTROL, 1, 1, handle_volume },
};
-static const unsigned num_commands = sizeof(commands) / sizeof(commands[0]);
+static constexpr unsigned num_commands = ARRAY_SIZE(commands);
static bool
command_available(gcc_unused const Partition &partition,
@@ -210,19 +212,27 @@ command_available(gcc_unused const Partition &partition,
return neighbor_commands_available(partition.instance);
#endif
+ if (strcmp(cmd->cmd, "save") == 0 ||
+ strcmp(cmd->cmd, "rm") == 0 ||
+ strcmp(cmd->cmd, "rename") == 0 ||
+ strcmp(cmd->cmd, "playlistdelete") == 0 ||
+ strcmp(cmd->cmd, "playlistmove") == 0 ||
+ strcmp(cmd->cmd, "playlistclear") == 0 ||
+ strcmp(cmd->cmd, "playlistadd") == 0 ||
+ strcmp(cmd->cmd, "listplaylists") == 0)
+ return playlist_commands_available();
+
return true;
}
/* don't be fooled, this is the command handler for "commands" command */
static CommandResult
-handle_commands(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_commands(Client &client, gcc_unused ConstBuffer<const char *> args)
{
const unsigned permission = client.GetPermission();
- const struct command *cmd;
for (unsigned i = 0; i < num_commands; ++i) {
- cmd = &commands[i];
+ const struct command *cmd = &commands[i];
if (cmd->permission == (permission & cmd->permission) &&
command_available(client.partition, cmd))
@@ -233,14 +243,12 @@ handle_commands(Client &client,
}
static CommandResult
-handle_not_commands(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_not_commands(Client &client, gcc_unused ConstBuffer<const char *> args)
{
const unsigned permission = client.GetPermission();
- const struct command *cmd;
for (unsigned i = 0; i < num_commands; ++i) {
- cmd = &commands[i];
+ const struct command *cmd = &commands[i];
if (cmd->permission != (permission & cmd->permission))
client_printf(client, "command: %s\n", cmd->cmd);
@@ -266,13 +274,12 @@ static const struct command *
command_lookup(const char *name)
{
unsigned a = 0, b = num_commands, i;
- int cmp;
/* binary search */
do {
i = (a + b) / 2;
- cmp = strcmp(name, commands[i].cmd);
+ const auto cmp = strcmp(name, commands[i].cmd);
if (cmp == 0)
return &commands[i];
else if (cmp < 0)
@@ -286,11 +293,8 @@ command_lookup(const char *name)
static bool
command_check_request(const struct command *cmd, Client &client,
- unsigned permission, unsigned argc, char *argv[])
+ unsigned permission, ConstBuffer<const char *> args)
{
- const unsigned min = cmd->min + 1;
- const unsigned max = cmd->max + 1;
-
if (cmd->permission != (permission & cmd->permission)) {
command_error(client, ACK_ERROR_PERMISSION,
"you don't have permission for \"%s\"",
@@ -298,21 +302,24 @@ command_check_request(const struct command *cmd, Client &client,
return false;
}
- if (min == 0)
+ const int min = cmd->min;
+ const int max = cmd->max;
+
+ if (min < 0)
return true;
- if (min == max && max != argc) {
+ if (min == max && unsigned(max) != args.size) {
command_error(client, ACK_ERROR_ARG,
"wrong number of arguments for \"%s\"",
- argv[0]);
+ cmd->cmd);
return false;
- } else if (argc < min) {
+ } else if (args.size < unsigned(min)) {
command_error(client, ACK_ERROR_ARG,
- "too few arguments for \"%s\"", argv[0]);
+ "too few arguments for \"%s\"", cmd->cmd);
return false;
- } else if (argc > max && max /* != 0 */ ) {
+ } else if (max >= 0 && args.size > unsigned(max)) {
command_error(client, ACK_ERROR_ARG,
- "too many arguments for \"%s\"", argv[0]);
+ "too many arguments for \"%s\"", cmd->cmd);
return false;
} else
return true;
@@ -320,25 +327,20 @@ command_check_request(const struct command *cmd, Client &client,
static const struct command *
command_checked_lookup(Client &client, unsigned permission,
- unsigned argc, char *argv[])
+ const char *cmd_name, ConstBuffer<const char *> args)
{
- const struct command *cmd;
-
current_command = "";
- if (argc == 0)
- return nullptr;
-
- cmd = command_lookup(argv[0]);
+ const struct command *cmd = command_lookup(cmd_name);
if (cmd == nullptr) {
command_error(client, ACK_ERROR_UNKNOWN,
- "unknown command \"%s\"", argv[0]);
+ "unknown command \"%s\"", cmd_name);
return nullptr;
}
current_command = cmd->cmd;
- if (!command_check_request(cmd, client, permission, argc, argv))
+ if (!command_check_request(cmd, client, permission, args))
return nullptr;
return cmd;
@@ -348,17 +350,18 @@ CommandResult
command_process(Client &client, unsigned num, char *line)
{
Error error;
- char *argv[COMMAND_ARGV_MAX] = { nullptr };
- const struct command *cmd;
- CommandResult ret = CommandResult::ERROR;
command_list_num = num;
/* get the command name (first word on the line) */
+ /* we have to set current_command because command_error()
+ expects it to be set */
Tokenizer tokenizer(line);
- argv[0] = tokenizer.NextWord(error);
- if (argv[0] == nullptr) {
+
+ const char *const cmd_name = current_command =
+ tokenizer.NextWord(error);
+ if (cmd_name == nullptr) {
current_command = "";
if (tokenizer.IsEnd())
command_error(client, ACK_ERROR_UNKNOWN,
@@ -374,38 +377,41 @@ command_process(Client &client, unsigned num, char *line)
return CommandResult::FINISH;
}
- unsigned argc = 1;
+ char *argv[COMMAND_ARGV_MAX];
+ ConstBuffer<const char *> args(argv, 0);
/* now parse the arguments (quoted or unquoted) */
- while (argc < COMMAND_ARGV_MAX &&
- (argv[argc] =
- tokenizer.NextParam(error)) != nullptr)
- ++argc;
-
- /* some error checks; we have to set current_command because
- command_error() expects it to be set */
-
- current_command = argv[0];
-
- if (argc >= COMMAND_ARGV_MAX) {
- command_error(client, ACK_ERROR_ARG, "Too many arguments");
- current_command = nullptr;
- return CommandResult::ERROR;
- }
-
- if (!tokenizer.IsEnd()) {
- command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage());
- current_command = nullptr;
- return CommandResult::ERROR;
+ while (true) {
+ if (args.size == COMMAND_ARGV_MAX) {
+ command_error(client, ACK_ERROR_ARG,
+ "Too many arguments");
+ current_command = nullptr;
+ return CommandResult::ERROR;
+ }
+
+ char *a = tokenizer.NextParam(error);
+ if (a == nullptr) {
+ if (tokenizer.IsEnd())
+ break;
+
+ command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage());
+ current_command = nullptr;
+ return CommandResult::ERROR;
+ }
+
+ argv[args.size++] = a;
}
/* look up and invoke the command handler */
- cmd = command_checked_lookup(client, client.GetPermission(),
- argc, argv);
- if (cmd)
- ret = cmd->handler(client, argc, argv);
+ const struct command *cmd =
+ command_checked_lookup(client, client.GetPermission(),
+ cmd_name, args);
+
+ CommandResult ret = cmd
+ ? cmd->handler(client, args)
+ : CommandResult::ERROR;
current_command = nullptr;
command_list_num = 0;
diff --git a/src/command/AllCommands.hxx b/src/command/AllCommands.hxx
index b7834a8de..ce3b905c4 100644
--- a/src/command/AllCommands.hxx
+++ b/src/command/AllCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/CommandError.cxx b/src/command/CommandError.cxx
index 89085fc68..da0571295 100644
--- a/src/command/CommandError.cxx
+++ b/src/command/CommandError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/CommandError.hxx b/src/command/CommandError.hxx
index b48baa5bf..6c42ed960 100644
--- a/src/command/CommandError.hxx
+++ b/src/command/CommandError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/CommandListBuilder.cxx b/src/command/CommandListBuilder.cxx
index 477c246ff..e2c7f95a5 100644
--- a/src/command/CommandListBuilder.cxx
+++ b/src/command/CommandListBuilder.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/CommandListBuilder.hxx b/src/command/CommandListBuilder.hxx
index 0747c4697..d2ca9d914 100644
--- a/src/command/CommandListBuilder.hxx
+++ b/src/command/CommandListBuilder.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/CommandResult.hxx b/src/command/CommandResult.hxx
index a2e968fb6..13641ec39 100644
--- a/src/command/CommandResult.hxx
+++ b/src/command/CommandResult.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx
index a3ea8d0ae..66ca2c279 100644
--- a/src/command/DatabaseCommands.cxx
+++ b/src/command/DatabaseCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -32,6 +32,7 @@
#include "util/Error.hxx"
#include "SongFilter.hxx"
#include "protocol/Result.hxx"
+#include "protocol/ArgParser.hxx"
#include "BulkEdit.hxx"
#include <string.h>
@@ -49,12 +50,10 @@ handle_listfiles_db(Client &client, const char *uri)
}
CommandResult
-handle_lsinfo2(Client &client, unsigned argc, char *argv[])
+handle_lsinfo2(Client &client, ConstBuffer<const char *> args)
{
- const char *const uri = argc == 2
- ? argv[1]
- /* default is root directory */
- : "";
+ /* default is root directory */
+ const char *const uri = args.IsEmpty() ? "" : args.front();
const DatabaseSelection selection(uri, false);
@@ -66,9 +65,17 @@ handle_lsinfo2(Client &client, unsigned argc, char *argv[])
}
static CommandResult
-handle_match(Client &client, unsigned argc, char *argv[], bool fold_case)
+handle_match(Client &client, ConstBuffer<const char *> args, bool fold_case)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
+ unsigned window_start = 0, window_end = std::numeric_limits<int>::max();
+ if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) {
+ if (!check_range(client, &window_start, &window_end,
+ args.back()))
+ return CommandResult::ERROR;
+
+ args.pop_back();
+ args.pop_back();
+ }
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
@@ -79,28 +86,27 @@ handle_match(Client &client, unsigned argc, char *argv[], bool fold_case)
const DatabaseSelection selection("", true, &filter);
Error error;
- return db_selection_print(client, selection, true, false, error)
+ return db_selection_print(client, selection, true, false,
+ window_start, window_end, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_find(Client &client, unsigned argc, char *argv[])
+handle_find(Client &client, ConstBuffer<const char *> args)
{
- return handle_match(client, argc, argv, false);
+ return handle_match(client, args, false);
}
CommandResult
-handle_search(Client &client, unsigned argc, char *argv[])
+handle_search(Client &client, ConstBuffer<const char *> args)
{
- return handle_match(client, argc, argv, true);
+ return handle_match(client, args, true);
}
static CommandResult
-handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case)
+handle_match_add(Client &client, ConstBuffer<const char *> args, bool fold_case)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
-
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
@@ -117,21 +123,20 @@ handle_match_add(Client &client, unsigned argc, char *argv[], bool fold_case)
}
CommandResult
-handle_findadd(Client &client, unsigned argc, char *argv[])
+handle_findadd(Client &client, ConstBuffer<const char *> args)
{
- return handle_match_add(client, argc, argv, false);
+ return handle_match_add(client, args, false);
}
CommandResult
-handle_searchadd(Client &client, unsigned argc, char *argv[])
+handle_searchadd(Client &client, ConstBuffer<const char *> args)
{
- return handle_match_add(client, argc, argv, true);
+ return handle_match_add(client, args, true);
}
CommandResult
-handle_searchaddpl(Client &client, unsigned argc, char *argv[])
+handle_searchaddpl(Client &client, ConstBuffer<const char *> args)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
const char *playlist = args.shift();
SongFilter filter;
@@ -152,10 +157,8 @@ handle_searchaddpl(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_count(Client &client, unsigned argc, char *argv[])
+handle_count(Client &client, ConstBuffer<const char *> args)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
-
TagType group = TAG_NUM_OF_ITEM_TYPES;
if (args.size >= 2 && strcmp(args[args.size - 2], "group") == 0) {
const char *s = args[args.size - 1];
@@ -183,24 +186,21 @@ handle_count(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_listall(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_listall(Client &client, ConstBuffer<const char *> args)
{
- const char *directory = "";
-
- if (argc == 2)
- directory = argv[1];
+ /* default is root directory */
+ const char *const uri = args.IsEmpty() ? "" : args.front();
Error error;
- return db_selection_print(client, DatabaseSelection(directory, true),
+ return db_selection_print(client, DatabaseSelection(uri, true),
false, false, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_list(Client &client, unsigned argc, char *argv[])
+handle_list(Client &client, ConstBuffer<const char *> args)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
const char *tag_name = args.shift();
unsigned tagType = locate_parse_type(tag_name);
@@ -271,15 +271,13 @@ handle_list(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_listallinfo(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_listallinfo(Client &client, ConstBuffer<const char *> args)
{
- const char *directory = "";
-
- if (argc == 2)
- directory = argv[1];
+ /* default is root directory */
+ const char *const uri = args.IsEmpty() ? "" : args.front();
Error error;
- return db_selection_print(client, DatabaseSelection(directory, true),
+ return db_selection_print(client, DatabaseSelection(uri, true),
true, false, error)
? CommandResult::OK
: print_error(client, error);
diff --git a/src/command/DatabaseCommands.hxx b/src/command/DatabaseCommands.hxx
index 7abf89e0c..b731517f5 100644
--- a/src/command/DatabaseCommands.hxx
+++ b/src/command/DatabaseCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,38 +23,39 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
handle_listfiles_db(Client &client, const char *uri);
CommandResult
-handle_lsinfo2(Client &client, unsigned argc, char *argv[]);
+handle_lsinfo2(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_find(Client &client, unsigned argc, char *argv[]);
+handle_find(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_findadd(Client &client, unsigned argc, char *argv[]);
+handle_findadd(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_search(Client &client, unsigned argc, char *argv[]);
+handle_search(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_searchadd(Client &client, unsigned argc, char *argv[]);
+handle_searchadd(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_searchaddpl(Client &client, unsigned argc, char *argv[]);
+handle_searchaddpl(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_count(Client &client, unsigned argc, char *argv[]);
+handle_count(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listall(Client &client, unsigned argc, char *argv[]);
+handle_listall(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_list(Client &client, unsigned argc, char *argv[]);
+handle_list(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listallinfo(Client &client, unsigned argc, char *argv[]);
+handle_listallinfo(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index 1b6a11cf5..789aa1f28 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
#include "protocol/Ack.hxx"
#include "protocol/Result.hxx"
#include "client/Client.hxx"
+#include "util/ConstBuffer.hxx"
#include "util/CharUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
@@ -202,11 +203,10 @@ read_file_comments(Client &client, const Path path_fs)
}
CommandResult
-handle_read_comments(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_read_comments(Client &client, ConstBuffer<const char *> args)
{
- assert(argc == 2);
-
- const char *const uri = argv[1];
+ assert(args.size == 1);
+ const char *const uri = args.front();
if (memcmp(uri, "file:///", 8) == 0) {
/* read comments from arbitrary local file */
diff --git a/src/command/FileCommands.hxx b/src/command/FileCommands.hxx
index 62835a82c..b5bc7b8b2 100644
--- a/src/command/FileCommands.hxx
+++ b/src/command/FileCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,11 +23,12 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
handle_listfiles_local(Client &client, const char *path_utf8);
CommandResult
-handle_read_comments(Client &client, unsigned argc, char *argv[]);
+handle_read_comments(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/MessageCommands.cxx b/src/command/MessageCommands.cxx
index a86bdf30c..9f8f3d1d4 100644
--- a/src/command/MessageCommands.cxx
+++ b/src/command/MessageCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
#include "Instance.hxx"
#include "Partition.hxx"
#include "protocol/Result.hxx"
+#include "util/ConstBuffer.hxx"
#include <set>
#include <string>
@@ -31,11 +32,12 @@
#include <assert.h>
CommandResult
-handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_subscribe(Client &client, ConstBuffer<const char *> args)
{
- assert(argc == 2);
+ assert(args.size == 1);
+ const char *const channel_name = args[0];
- switch (client.Subscribe(argv[1])) {
+ switch (client.Subscribe(channel_name)) {
case Client::SubscribeResult::OK:
return CommandResult::OK;
@@ -61,11 +63,12 @@ handle_subscribe(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_unsubscribe(Client &client, ConstBuffer<const char *> args)
{
- assert(argc == 2);
+ assert(args.size == 1);
+ const char *const channel_name = args[0];
- if (client.Unsubscribe(argv[1]))
+ if (client.Unsubscribe(channel_name))
return CommandResult::OK;
else {
command_error(client, ACK_ERROR_NO_EXIST,
@@ -75,10 +78,9 @@ handle_unsubscribe(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_channels(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_channels(Client &client, gcc_unused ConstBuffer<const char *> args)
{
- assert(argc == 1);
+ assert(args.IsEmpty());
std::set<std::string> channels;
for (const auto &c : *client.partition.instance.client_list)
@@ -93,9 +95,9 @@ handle_channels(Client &client,
CommandResult
handle_read_messages(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+ gcc_unused ConstBuffer<const char *> args)
{
- assert(argc == 1);
+ assert(args.IsEmpty());
while (!client.messages.empty()) {
const ClientMessage &msg = client.messages.front();
@@ -109,19 +111,21 @@ handle_read_messages(Client &client,
}
CommandResult
-handle_send_message(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_send_message(Client &client, ConstBuffer<const char *> args)
{
- assert(argc == 3);
+ assert(args.size == 2);
- if (!client_message_valid_channel_name(argv[1])) {
+ const char *const channel_name = args[0];
+ const char *const message_text = args[1];
+
+ if (!client_message_valid_channel_name(channel_name)) {
command_error(client, ACK_ERROR_ARG,
"invalid channel name");
return CommandResult::ERROR;
}
bool sent = false;
- const ClientMessage msg(argv[1], argv[2]);
+ const ClientMessage msg(channel_name, message_text);
for (auto &c : *client.partition.instance.client_list)
if (c.PushMessage(msg))
sent = true;
diff --git a/src/command/MessageCommands.hxx b/src/command/MessageCommands.hxx
index ac8afe2fb..44dbfbddf 100644
--- a/src/command/MessageCommands.hxx
+++ b/src/command/MessageCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,20 +23,21 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_subscribe(Client &client, unsigned argc, char *argv[]);
+handle_subscribe(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_unsubscribe(Client &client, unsigned argc, char *argv[]);
+handle_unsubscribe(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_channels(Client &client, unsigned argc, char *argv[]);
+handle_channels(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_read_messages(Client &client, unsigned argc, char *argv[]);
+handle_read_messages(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_send_message(Client &client, unsigned argc, char *argv[]);
+handle_send_message(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/NeighborCommands.cxx b/src/command/NeighborCommands.cxx
index 22e8adf9e..3c171bddb 100644
--- a/src/command/NeighborCommands.cxx
+++ b/src/command/NeighborCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
#include "protocol/Result.hxx"
#include "neighbor/Glue.hxx"
#include "neighbor/Info.hxx"
+#include "util/ConstBuffer.hxx"
#include <set>
#include <string>
@@ -38,8 +39,7 @@ neighbor_commands_available(const Instance &instance)
}
CommandResult
-handle_listneighbors(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_listneighbors(Client &client, gcc_unused ConstBuffer<const char *> args)
{
const NeighborGlue *const neighbors =
client.partition.instance.neighbors;
diff --git a/src/command/NeighborCommands.hxx b/src/command/NeighborCommands.hxx
index 7fb309aeb..c0f2a86b9 100644
--- a/src/command/NeighborCommands.hxx
+++ b/src/command/NeighborCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,12 +25,13 @@
struct Instance;
class Client;
+template<typename T> struct ConstBuffer;
gcc_pure
bool
neighbor_commands_available(const Instance &instance);
CommandResult
-handle_listneighbors(Client &client, unsigned argc, char *argv[]);
+handle_listneighbors(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index a924f77b5..9ca7567b9 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -37,6 +37,7 @@
#include "mixer/Volume.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
+#include "util/ConstBuffer.hxx"
#include "fs/AllocatedPath.hxx"
#include "Stats.hxx"
#include "Permission.hxx"
@@ -68,8 +69,7 @@ print_spl_list(Client &client, const PlaylistVector &list)
}
CommandResult
-handle_urlhandlers(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_urlhandlers(Client &client, gcc_unused ConstBuffer<const char *> args)
{
if (client.IsLocal())
client_puts(client, "handler: file://\n");
@@ -78,31 +78,27 @@ handle_urlhandlers(Client &client,
}
CommandResult
-handle_decoders(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_decoders(Client &client, gcc_unused ConstBuffer<const char *> args)
{
decoder_list_print(client);
return CommandResult::OK;
}
CommandResult
-handle_tagtypes(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_tagtypes(Client &client, gcc_unused ConstBuffer<const char *> args)
{
tag_print_types(client);
return CommandResult::OK;
}
CommandResult
-handle_kill(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_kill(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
{
return CommandResult::KILL;
}
CommandResult
-handle_close(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_close(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
{
return CommandResult::FINISH;
}
@@ -116,12 +112,10 @@ print_tag(TagType type, const char *value, void *ctx)
}
CommandResult
-handle_listfiles(Client &client, unsigned argc, char *argv[])
+handle_listfiles(Client &client, ConstBuffer<const char *> args)
{
- const char *const uri = argc == 2
- ? argv[1]
- /* default is root directory */
- : "";
+ /* default is root directory */
+ const char *const uri = args.IsEmpty() ? "" : args.front();
if (memcmp(uri, "file:///", 8) == 0)
/* list local directory */
@@ -157,12 +151,10 @@ static constexpr tag_handler print_tag_handler = {
};
CommandResult
-handle_lsinfo(Client &client, unsigned argc, char *argv[])
+handle_lsinfo(Client &client, ConstBuffer<const char *> args)
{
- const char *const uri = argc == 2
- ? argv[1]
- /* default is root directory */
- : "";
+ /* default is root directory */
+ const char *const uri = args.IsEmpty() ? "" : args.front();
if (memcmp(uri, "file:///", 8) == 0) {
/* print information about an arbitrary local file */
@@ -207,7 +199,7 @@ handle_lsinfo(Client &client, unsigned argc, char *argv[])
}
#ifdef ENABLE_DATABASE
- CommandResult result = handle_lsinfo2(client, argc, argv);
+ CommandResult result = handle_lsinfo2(client, args);
if (result != CommandResult::OK)
return result;
#endif
@@ -265,14 +257,14 @@ handle_update(Client &client, Database &db,
#endif
static CommandResult
-handle_update(Client &client, unsigned argc, char *argv[], bool discard)
+handle_update(Client &client, ConstBuffer<const char *> args, bool discard)
{
#ifdef ENABLE_DATABASE
const char *path = "";
- assert(argc <= 2);
- if (argc == 2) {
- path = argv[1];
+ assert(args.size <= 1);
+ if (!args.IsEmpty()) {
+ path = args.front();
if (*path == 0 || strcmp(path, "/") == 0)
/* backwards compatibility with MPD 0.15 */
@@ -292,8 +284,7 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard)
if (db != nullptr)
return handle_update(client, *db, path, discard);
#else
- (void)argc;
- (void)argv;
+ (void)args;
(void)discard;
#endif
@@ -302,24 +293,24 @@ handle_update(Client &client, unsigned argc, char *argv[], bool discard)
}
CommandResult
-handle_update(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_update(Client &client, gcc_unused ConstBuffer<const char *> args)
{
- return handle_update(client, argc, argv, false);
+ return handle_update(client, args, false);
}
CommandResult
-handle_rescan(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_rescan(Client &client, gcc_unused ConstBuffer<const char *> args)
{
- return handle_update(client, argc, argv, true);
+ return handle_update(client, args, true);
}
CommandResult
-handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_setvol(Client &client, ConstBuffer<const char *> args)
{
unsigned level;
bool success;
- if (!check_unsigned(client, &level, argv[1]))
+ if (!check_unsigned(client, &level, args.front()))
return CommandResult::ERROR;
if (level > 100) {
@@ -338,10 +329,10 @@ handle_setvol(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_volume(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_volume(Client &client, ConstBuffer<const char *> args)
{
int relative;
- if (!check_int(client, &relative, argv[1]))
+ if (!check_int(client, &relative, args.front()))
return CommandResult::ERROR;
if (relative < -100 || relative > 100) {
@@ -372,26 +363,24 @@ handle_volume(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_stats(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_stats(Client &client, gcc_unused ConstBuffer<const char *> args)
{
stats_print(client);
return CommandResult::OK;
}
CommandResult
-handle_ping(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_ping(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
{
return CommandResult::OK;
}
CommandResult
-handle_password(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_password(Client &client, ConstBuffer<const char *> args)
{
unsigned permission = 0;
- if (getPermissionFromPassword(argv[1], &permission) < 0) {
+ if (getPermissionFromPassword(args.front(), &permission) < 0) {
command_error(client, ACK_ERROR_PASSWORD, "incorrect password");
return CommandResult::ERROR;
}
@@ -402,8 +391,7 @@ handle_password(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_config(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_config(Client &client, gcc_unused ConstBuffer<const char *> args)
{
if (!client.IsLocal()) {
command_error(client, ACK_ERROR_PERMISSION,
@@ -423,17 +411,16 @@ handle_config(Client &client,
}
CommandResult
-handle_idle(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_idle(Client &client, ConstBuffer<const char *> args)
{
unsigned flags = 0;
- for (unsigned i = 1; i < argc; ++i) {
- unsigned event = idle_parse_name(argv[i]);
+ for (const char *i : args) {
+ unsigned event = idle_parse_name(i);
if (event == 0) {
command_error(client, ACK_ERROR_ARG,
"Unrecognized idle event: %s",
- argv[i]);
+ i);
return CommandResult::ERROR;
}
diff --git a/src/command/OtherCommands.hxx b/src/command/OtherCommands.hxx
index 7cfa35dfb..c0b25dece 100644
--- a/src/command/OtherCommands.hxx
+++ b/src/command/OtherCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,53 +23,54 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_urlhandlers(Client &client, unsigned argc, char *argv[]);
+handle_urlhandlers(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_decoders(Client &client, unsigned argc, char *argv[]);
+handle_decoders(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_tagtypes(Client &client, unsigned argc, char *argv[]);
+handle_tagtypes(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_kill(Client &client, unsigned argc, char *argv[]);
+handle_kill(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_close(Client &client, unsigned argc, char *argv[]);
+handle_close(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listfiles(Client &client, unsigned argc, char *argv[]);
+handle_listfiles(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_lsinfo(Client &client, unsigned argc, char *argv[]);
+handle_lsinfo(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_update(Client &client, unsigned argc, char *argv[]);
+handle_update(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_rescan(Client &client, unsigned argc, char *argv[]);
+handle_rescan(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_setvol(Client &client, unsigned argc, char *argv[]);
+handle_setvol(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_volume(Client &client, unsigned argc, char *argv[]);
+handle_volume(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_stats(Client &client, unsigned argc, char *argv[]);
+handle_stats(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_ping(Client &client, unsigned argc, char *argv[]);
+handle_ping(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_password(Client &client, unsigned argc, char *argv[]);
+handle_password(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_config(Client &client, unsigned argc, char *argv[]);
+handle_config(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_idle(Client &client, unsigned argc, char *argv[]);
+handle_idle(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/OutputCommands.cxx b/src/command/OutputCommands.cxx
index c69a0dd65..23eb7be5e 100644
--- a/src/command/OutputCommands.cxx
+++ b/src/command/OutputCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,12 +25,15 @@
#include "protocol/ArgParser.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
+#include "util/ConstBuffer.hxx"
CommandResult
-handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_enableoutput(Client &client, ConstBuffer<const char *> args)
{
+ assert(args.size == 1);
+
unsigned device;
- if (!check_unsigned(client, &device, argv[1]))
+ if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR;
if (!audio_output_enable_index(client.partition.outputs, device)) {
@@ -43,10 +46,12 @@ handle_enableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_disableoutput(Client &client, ConstBuffer<const char *> args)
{
+ assert(args.size == 1);
+
unsigned device;
- if (!check_unsigned(client, &device, argv[1]))
+ if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR;
if (!audio_output_disable_index(client.partition.outputs, device)) {
@@ -59,10 +64,12 @@ handle_disableoutput(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_toggleoutput(Client &client, ConstBuffer<const char *> args)
{
+ assert(args.size == 1);
+
unsigned device;
- if (!check_unsigned(client, &device, argv[1]))
+ if (!check_unsigned(client, &device, args.front()))
return CommandResult::ERROR;
if (!audio_output_toggle_index(client.partition.outputs, device)) {
@@ -75,9 +82,10 @@ handle_toggleoutput(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_devices(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_devices(Client &client, gcc_unused ConstBuffer<const char *> args)
{
+ assert(args.IsEmpty());
+
printAudioDevices(client, client.partition.outputs);
return CommandResult::OK;
diff --git a/src/command/OutputCommands.hxx b/src/command/OutputCommands.hxx
index 8d6be0511..985f27416 100644
--- a/src/command/OutputCommands.hxx
+++ b/src/command/OutputCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,17 +23,18 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_enableoutput(Client &client, unsigned argc, char *argv[]);
+handle_enableoutput(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_disableoutput(Client &client, unsigned argc, char *argv[]);
+handle_disableoutput(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_toggleoutput(Client &client, unsigned argc, char *argv[]);
+handle_toggleoutput(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_devices(Client &client, unsigned argc, char *argv[]);
+handle_devices(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/PlayerCommands.cxx b/src/command/PlayerCommands.cxx
index cd7f42289..3686e7b90 100644
--- a/src/command/PlayerCommands.cxx
+++ b/src/command/PlayerCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#include "protocol/ArgParser.hxx"
#include "AudioFormat.hxx"
#include "ReplayGainConfig.hxx"
+#include "util/ConstBuffer.hxx"
#ifdef ENABLE_DATABASE
#include "db/update/Service.hxx"
@@ -56,22 +57,22 @@
#define COMMAND_STATUS_UPDATING_DB "updating_db"
CommandResult
-handle_play(Client &client, unsigned argc, char *argv[])
+handle_play(Client &client, ConstBuffer<const char *> args)
{
int song = -1;
- if (argc == 2 && !check_int(client, &song, argv[1]))
+ if (!args.IsEmpty() && !check_int(client, &song, args.front()))
return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayPosition(song);
return print_playlist_result(client, result);
}
CommandResult
-handle_playid(Client &client, unsigned argc, char *argv[])
+handle_playid(Client &client, ConstBuffer<const char *> args)
{
int id = -1;
- if (argc == 2 && !check_int(client, &id, argv[1]))
+ if (!args.IsEmpty() && !check_int(client, &id, args.front()))
return CommandResult::ERROR;
PlaylistResult result = client.partition.PlayId(id);
@@ -79,28 +80,25 @@ handle_playid(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_stop(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_stop(Client &client, gcc_unused ConstBuffer<const char *> args)
{
client.partition.Stop();
return CommandResult::OK;
}
CommandResult
-handle_currentsong(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_currentsong(Client &client, gcc_unused ConstBuffer<const char *> args)
{
playlist_print_current(client, client.playlist);
return CommandResult::OK;
}
CommandResult
-handle_pause(Client &client,
- unsigned argc, char *argv[])
+handle_pause(Client &client, ConstBuffer<const char *> args)
{
- if (argc == 2) {
+ if (!args.IsEmpty()) {
bool pause_flag;
- if (!check_bool(client, &pause_flag, argv[1]))
+ if (!check_bool(client, &pause_flag, args.front()))
return CommandResult::ERROR;
client.player_control.SetPause(pause_flag);
@@ -111,8 +109,7 @@ handle_pause(Client &client,
}
CommandResult
-handle_status(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_status(Client &client, gcc_unused ConstBuffer<const char *> args)
{
const char *state = nullptr;
int song;
@@ -182,6 +179,10 @@ handle_status(Client &client,
player_status.elapsed_time.ToDoubleS(),
player_status.bit_rate);
+ if (!player_status.total_time.IsNegative())
+ client_printf(client, "duration: %1.3f\n",
+ player_status.total_time.ToDoubleS());
+
if (player_status.audio_format.IsDefined()) {
struct audio_format_string af_string;
@@ -222,8 +223,7 @@ handle_status(Client &client,
}
CommandResult
-handle_next(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_next(Client &client, gcc_unused ConstBuffer<const char *> args)
{
playlist &playlist = client.playlist;
@@ -239,18 +239,17 @@ handle_next(Client &client,
}
CommandResult
-handle_previous(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_previous(Client &client, gcc_unused ConstBuffer<const char *> args)
{
client.partition.PlayPrevious();
return CommandResult::OK;
}
CommandResult
-handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_repeat(Client &client, ConstBuffer<const char *> args)
{
bool status;
- if (!check_bool(client, &status, argv[1]))
+ if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR;
client.partition.SetRepeat(status);
@@ -258,10 +257,10 @@ handle_repeat(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_single(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_single(Client &client, ConstBuffer<const char *> args)
{
bool status;
- if (!check_bool(client, &status, argv[1]))
+ if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR;
client.partition.SetSingle(status);
@@ -269,10 +268,10 @@ handle_single(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_consume(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_consume(Client &client, ConstBuffer<const char *> args)
{
bool status;
- if (!check_bool(client, &status, argv[1]))
+ if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR;
client.partition.SetConsume(status);
@@ -280,10 +279,10 @@ handle_consume(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_random(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_random(Client &client, ConstBuffer<const char *> args)
{
bool status;
- if (!check_bool(client, &status, argv[1]))
+ if (!check_bool(client, &status, args.front()))
return CommandResult::ERROR;
client.partition.SetRandom(status);
@@ -292,22 +291,21 @@ handle_random(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_clearerror(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_clearerror(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
{
client.player_control.ClearError();
return CommandResult::OK;
}
CommandResult
-handle_seek(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_seek(Client &client, ConstBuffer<const char *> args)
{
unsigned song;
SongTime seek_time;
- if (!check_unsigned(client, &song, argv[1]))
+ if (!check_unsigned(client, &song, args[0]))
return CommandResult::ERROR;
- if (!ParseCommandArg(client, seek_time, argv[2]))
+ if (!ParseCommandArg(client, seek_time, args[1]))
return CommandResult::ERROR;
PlaylistResult result =
@@ -316,14 +314,14 @@ handle_seek(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_seekid(Client &client, ConstBuffer<const char *> args)
{
unsigned id;
SongTime seek_time;
- if (!check_unsigned(client, &id, argv[1]))
+ if (!check_unsigned(client, &id, args[0]))
return CommandResult::ERROR;
- if (!ParseCommandArg(client, seek_time, argv[2]))
+ if (!ParseCommandArg(client, seek_time, args[1]))
return CommandResult::ERROR;
PlaylistResult result =
@@ -332,9 +330,9 @@ handle_seekid(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_seekcur(Client &client, ConstBuffer<const char *> args)
{
- const char *p = argv[1];
+ const char *p = args.front();
bool relative = *p == '+' || *p == '-';
SignedSongTime seek_time;
if (!ParseCommandArg(client, seek_time, p))
@@ -346,11 +344,11 @@ handle_seekcur(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_crossfade(Client &client, ConstBuffer<const char *> args)
{
unsigned xfade_time;
- if (!check_unsigned(client, &xfade_time, argv[1]))
+ if (!check_unsigned(client, &xfade_time, args.front()))
return CommandResult::ERROR;
client.player_control.SetCrossFade(xfade_time);
@@ -358,11 +356,11 @@ handle_crossfade(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_mixrampdb(Client &client, ConstBuffer<const char *> args)
{
float db;
- if (!check_float(client, &db, argv[1]))
+ if (!check_float(client, &db, args.front()))
return CommandResult::ERROR;
client.player_control.SetMixRampDb(db);
@@ -370,11 +368,11 @@ handle_mixrampdb(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_mixrampdelay(Client &client, ConstBuffer<const char *> args)
{
float delay_secs;
- if (!check_float(client, &delay_secs, argv[1]))
+ if (!check_float(client, &delay_secs, args.front()))
return CommandResult::ERROR;
client.player_control.SetMixRampDelay(delay_secs);
@@ -382,10 +380,9 @@ handle_mixrampdelay(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_replay_gain_mode(Client &client,
- gcc_unused unsigned argc, char *argv[])
+handle_replay_gain_mode(Client &client, ConstBuffer<const char *> args)
{
- if (!replay_gain_set_mode_string(argv[1])) {
+ if (!replay_gain_set_mode_string(args.front())) {
command_error(client, ACK_ERROR_ARG,
"Unrecognized replay gain mode");
return CommandResult::ERROR;
@@ -396,8 +393,7 @@ handle_replay_gain_mode(Client &client,
}
CommandResult
-handle_replay_gain_status(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_replay_gain_status(Client &client, gcc_unused ConstBuffer<const char *> args)
{
client_printf(client, "replay_gain_mode: %s\n",
replay_gain_get_mode_string());
diff --git a/src/command/PlayerCommands.hxx b/src/command/PlayerCommands.hxx
index da7083f1e..1d7bfa366 100644
--- a/src/command/PlayerCommands.hxx
+++ b/src/command/PlayerCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,68 +23,69 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_play(Client &client, unsigned argc, char *argv[]);
+handle_play(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playid(Client &client, unsigned argc, char *argv[]);
+handle_playid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_stop(Client &client, unsigned argc, char *argv[]);
+handle_stop(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_currentsong(Client &client, unsigned argc, char *argv[]);
+handle_currentsong(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_pause(Client &client, unsigned argc, char *argv[]);
+handle_pause(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_status(Client &client, unsigned argc, char *argv[]);
+handle_status(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_next(Client &client, unsigned argc, char *argv[]);
+handle_next(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_previous(Client &client, unsigned argc, char *avg[]);
+handle_previous(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_repeat(Client &client, unsigned argc, char *argv[]);
+handle_repeat(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_single(Client &client, unsigned argc, char *argv[]);
+handle_single(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_consume(Client &client, unsigned argc, char *argv[]);
+handle_consume(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_random(Client &client, unsigned argc, char *argv[]);
+handle_random(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_clearerror(Client &client, unsigned argc, char *argv[]);
+handle_clearerror(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_seek(Client &client, unsigned argc, char *argv[]);
+handle_seek(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_seekid(Client &client, unsigned argc, char *argv[]);
+handle_seekid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_seekcur(Client &client, unsigned argc, char *argv[]);
+handle_seekcur(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_crossfade(Client &client, unsigned argc, char *argv[]);
+handle_crossfade(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_mixrampdb(Client &client, unsigned argc, char *argv[]);
+handle_mixrampdb(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_mixrampdelay(Client &client, unsigned argc, char *argv[]);
+handle_mixrampdelay(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_replay_gain_mode(Client &client, unsigned argc, char *argv[]);
+handle_replay_gain_mode(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_replay_gain_status(Client &client, unsigned argc, char *argv[]);
+handle_replay_gain_status(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx
index c2b18064c..9d870b021 100644
--- a/src/command/PlaylistCommands.cxx
+++ b/src/command/PlaylistCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,8 +35,17 @@
#include "protocol/ArgParser.hxx"
#include "protocol/Result.hxx"
#include "ls.hxx"
+#include "Mapper.hxx"
+#include "fs/AllocatedPath.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
+#include "util/ConstBuffer.hxx"
+
+bool
+playlist_commands_available()
+{
+ return !map_spl_path().IsNull();
+}
static void
print_spl_list(Client &client, const PlaylistVector &list)
@@ -50,28 +59,28 @@ print_spl_list(Client &client, const PlaylistVector &list)
}
CommandResult
-handle_save(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_save(Client &client, ConstBuffer<const char *> args)
{
- PlaylistResult result = spl_save_playlist(argv[1], client.playlist);
+ PlaylistResult result = spl_save_playlist(args.front(), client.playlist);
return print_playlist_result(client, result);
}
CommandResult
-handle_load(Client &client, unsigned argc, char *argv[])
+handle_load(Client &client, ConstBuffer<const char *> args)
{
unsigned start_index, end_index;
- if (argc < 3) {
+ if (args.size < 2) {
start_index = 0;
end_index = unsigned(-1);
- } else if (!check_range(client, &start_index, &end_index, argv[2]))
+ } else if (!check_range(client, &start_index, &end_index, args[1]))
return CommandResult::ERROR;
const ScopeBulkEdit bulk_edit(client.partition);
Error error;
const SongLoader loader(client);
- if (!playlist_open_into_queue(argv[1],
+ if (!playlist_open_into_queue(args.front(),
start_index, end_index,
client.playlist,
client.player_control, loader, error))
@@ -81,94 +90,104 @@ handle_load(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_listplaylist(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_listplaylist(Client &client, ConstBuffer<const char *> args)
{
- if (playlist_file_print(client, argv[1], false))
+ const char *const name = args.front();
+
+ if (playlist_file_print(client, name, false))
return CommandResult::OK;
Error error;
- return spl_print(client, argv[1], false, error)
+ return spl_print(client, name, false, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_listplaylistinfo(Client &client,
- gcc_unused unsigned argc, char *argv[])
+handle_listplaylistinfo(Client &client, ConstBuffer<const char *> args)
{
- if (playlist_file_print(client, argv[1], true))
+ const char *const name = args.front();
+
+ if (playlist_file_print(client, name, true))
return CommandResult::OK;
Error error;
- return spl_print(client, argv[1], true, error)
+ return spl_print(client, name, true, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_rm(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_rm(Client &client, ConstBuffer<const char *> args)
{
+ const char *const name = args.front();
+
Error error;
- return spl_delete(argv[1], error)
+ return spl_delete(name, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_rename(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_rename(Client &client, ConstBuffer<const char *> args)
{
+ const char *const old_name = args[0];
+ const char *const new_name = args[1];
+
Error error;
- return spl_rename(argv[1], argv[2], error)
+ return spl_rename(old_name, new_name, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_playlistdelete(Client &client,
- gcc_unused unsigned argc, char *argv[]) {
- char *playlist = argv[1];
+handle_playlistdelete(Client &client, ConstBuffer<const char *> args)
+{
+ const char *const name = args[0];
unsigned from;
- if (!check_unsigned(client, &from, argv[2]))
+ if (!check_unsigned(client, &from, args[1]))
return CommandResult::ERROR;
Error error;
- return spl_remove_index(playlist, from, error)
+ return spl_remove_index(name, from, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_playlistmove(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_playlistmove(Client &client, ConstBuffer<const char *> args)
{
- char *playlist = argv[1];
+ const char *const name = args.front();
unsigned from, to;
- if (!check_unsigned(client, &from, argv[2]))
+ if (!check_unsigned(client, &from, args[1]))
return CommandResult::ERROR;
- if (!check_unsigned(client, &to, argv[3]))
+ if (!check_unsigned(client, &to, args[2]))
return CommandResult::ERROR;
Error error;
- return spl_move_index(playlist, from, to, error)
+ return spl_move_index(name, from, to, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_playlistclear(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_playlistclear(Client &client, ConstBuffer<const char *> args)
{
+ const char *const name = args.front();
+
Error error;
- return spl_clear(argv[1], error)
+ return spl_clear(name, error)
? CommandResult::OK
: print_error(client, error);
}
CommandResult
-handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_playlistadd(Client &client, ConstBuffer<const char *> args)
{
- char *playlist = argv[1];
- char *uri = argv[2];
+ const char *const playlist = args[0];
+ const char *const uri = args[1];
bool success;
Error error;
@@ -199,8 +218,7 @@ handle_playlistadd(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_listplaylists(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_listplaylists(Client &client, gcc_unused ConstBuffer<const char *> args)
{
Error error;
const auto list = ListPlaylistFiles(error);
diff --git a/src/command/PlaylistCommands.hxx b/src/command/PlaylistCommands.hxx
index fba4e1318..5ac345e57 100644
--- a/src/command/PlaylistCommands.hxx
+++ b/src/command/PlaylistCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,40 +21,46 @@
#define MPD_PLAYLIST_COMMANDS_HXX
#include "CommandResult.hxx"
+#include "Compiler.h"
class Client;
+template<typename T> struct ConstBuffer;
+
+gcc_const
+bool
+playlist_commands_available();
CommandResult
-handle_save(Client &client, unsigned argc, char *argv[]);
+handle_save(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_load(Client &client, unsigned argc, char *argv[]);
+handle_load(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listplaylist(Client &client, unsigned argc, char *argv[]);
+handle_listplaylist(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listplaylistinfo(Client &client, unsigned argc, char *argv[]);
+handle_listplaylistinfo(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_rm(Client &client, unsigned argc, char *argv[]);
+handle_rm(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_rename(Client &client, unsigned argc, char *argv[]);
+handle_rename(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistdelete(Client &client, unsigned argc, char *argv[]);
+handle_playlistdelete(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistmove(Client &client, unsigned argc, char *argv[]);
+handle_playlistmove(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistclear(Client &client, unsigned argc, char *argv[]);
+handle_playlistclear(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistadd(Client &client, unsigned argc, char *argv[]);
+handle_playlistadd(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_listplaylists(Client &client, unsigned argc, char *argv[]);
+handle_listplaylists(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx
index d0b789eb1..20634652a 100644
--- a/src/command/QueueCommands.cxx
+++ b/src/command/QueueCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -59,9 +59,9 @@ translate_uri(Client &client, const char *uri)
}
CommandResult
-handle_add(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_add(Client &client, ConstBuffer<const char *> args)
{
- const char *uri = argv[1];
+ const char *uri = args.front();
if (memcmp(uri, "/", 2) == 0)
/* this URI is malformed, but some clients are buggy
and use "add /" to add the whole database, which
@@ -99,9 +99,9 @@ handle_add(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_addid(Client &client, unsigned argc, char *argv[])
+handle_addid(Client &client, ConstBuffer<const char *> args)
{
- const char *const uri = translate_uri(client, argv[1]);
+ const char *const uri = translate_uri(client, args.front());
if (uri == nullptr)
return CommandResult::ERROR;
@@ -111,9 +111,9 @@ handle_addid(Client &client, unsigned argc, char *argv[])
if (added_id == 0)
return print_error(client, error);
- if (argc == 3) {
+ if (args.size == 2) {
unsigned to;
- if (!check_unsigned(client, &to, argv[2]))
+ if (!check_unsigned(client, &to, args[1]))
return CommandResult::ERROR;
PlaylistResult result = client.partition.MoveId(added_id, to);
if (result != PlaylistResult::SUCCESS) {
@@ -160,14 +160,14 @@ parse_time_range(const char *p, SongTime &start_r, SongTime &end_r)
}
CommandResult
-handle_rangeid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_rangeid(Client &client, ConstBuffer<const char *> args)
{
unsigned id;
- if (!check_unsigned(client, &id, argv[1]))
+ if (!check_unsigned(client, &id, args.front()))
return CommandResult::ERROR;
SongTime start, end;
- if (!parse_time_range(argv[2], start, end)) {
+ if (!parse_time_range(args[1], start, end)) {
command_error(client, ACK_ERROR_ARG, "Bad range");
return CommandResult::ERROR;
}
@@ -182,11 +182,11 @@ handle_rangeid(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_delete(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_delete(Client &client, ConstBuffer<const char *> args)
{
unsigned start, end;
- if (!check_range(client, &start, &end, argv[1]))
+ if (!check_range(client, &start, &end, args.front()))
return CommandResult::ERROR;
PlaylistResult result = client.partition.DeleteRange(start, end);
@@ -194,11 +194,11 @@ handle_delete(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_deleteid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_deleteid(Client &client, ConstBuffer<const char *> args)
{
unsigned id;
- if (!check_unsigned(client, &id, argv[1]))
+ if (!check_unsigned(client, &id, args.front()))
return CommandResult::ERROR;
PlaylistResult result = client.partition.DeleteId(id);
@@ -206,19 +206,17 @@ handle_deleteid(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_playlist(Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_playlist(Client &client, gcc_unused ConstBuffer<const char *> args)
{
playlist_print_uris(client, client.playlist);
return CommandResult::OK;
}
CommandResult
-handle_shuffle(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_shuffle(gcc_unused Client &client, ConstBuffer<const char *> args)
{
unsigned start = 0, end = client.playlist.queue.GetLength();
- if (argc == 2 && !check_range(client, &start, &end, argv[1]))
+ if (args.size == 1 && !check_range(client, &start, &end, args.front()))
return CommandResult::ERROR;
client.partition.Shuffle(start, end);
@@ -226,19 +224,18 @@ handle_shuffle(gcc_unused Client &client,
}
CommandResult
-handle_clear(gcc_unused Client &client,
- gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_clear(gcc_unused Client &client, gcc_unused ConstBuffer<const char *> args)
{
client.partition.ClearQueue();
return CommandResult::OK;
}
CommandResult
-handle_plchanges(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_plchanges(Client &client, ConstBuffer<const char *> args)
{
uint32_t version;
- if (!check_uint32(client, &version, argv[1]))
+ if (!check_uint32(client, &version, args.front()))
return CommandResult::ERROR;
playlist_print_changes_info(client, client.playlist, version);
@@ -246,11 +243,11 @@ handle_plchanges(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_plchangesposid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_plchangesposid(Client &client, ConstBuffer<const char *> args)
{
uint32_t version;
- if (!check_uint32(client, &version, argv[1]))
+ if (!check_uint32(client, &version, args.front()))
return CommandResult::ERROR;
playlist_print_changes_position(client, client.playlist, version);
@@ -258,12 +255,12 @@ handle_plchangesposid(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_playlistinfo(Client &client, unsigned argc, char *argv[])
+handle_playlistinfo(Client &client, ConstBuffer<const char *> args)
{
unsigned start = 0, end = std::numeric_limits<unsigned>::max();
bool ret;
- if (argc == 2 && !check_range(client, &start, &end, argv[1]))
+ if (args.size == 1 && !check_range(client, &start, &end, args.front()))
return CommandResult::ERROR;
ret = playlist_print_info(client, client.playlist, start, end);
@@ -275,11 +272,11 @@ handle_playlistinfo(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_playlistid(Client &client, unsigned argc, char *argv[])
+handle_playlistid(Client &client, ConstBuffer<const char *> args)
{
- if (argc >= 2) {
+ if (!args.IsEmpty()) {
unsigned id;
- if (!check_unsigned(client, &id, argv[1]))
+ if (!check_unsigned(client, &id, args.front()))
return CommandResult::ERROR;
bool ret = playlist_print_id(client, client.playlist, id);
@@ -295,11 +292,9 @@ handle_playlistid(Client &client, unsigned argc, char *argv[])
}
static CommandResult
-handle_playlist_match(Client &client, unsigned argc, char *argv[],
+handle_playlist_match(Client &client, ConstBuffer<const char *> args,
bool fold_case)
{
- ConstBuffer<const char *> args(argv + 1, argc - 1);
-
SongFilter filter;
if (!filter.Parse(args, fold_case)) {
command_error(client, ACK_ERROR_ARG, "incorrect arguments");
@@ -311,35 +306,35 @@ handle_playlist_match(Client &client, unsigned argc, char *argv[],
}
CommandResult
-handle_playlistfind(Client &client, unsigned argc, char *argv[])
+handle_playlistfind(Client &client, ConstBuffer<const char *> args)
{
- return handle_playlist_match(client, argc, argv, false);
+ return handle_playlist_match(client, args, false);
}
CommandResult
-handle_playlistsearch(Client &client, unsigned argc, char *argv[])
+handle_playlistsearch(Client &client, ConstBuffer<const char *> args)
{
- return handle_playlist_match(client, argc, argv, true);
+ return handle_playlist_match(client, args, true);
}
CommandResult
-handle_prio(Client &client, unsigned argc, char *argv[])
+handle_prio(Client &client, ConstBuffer<const char *> args)
{
+ const char *const priority_string = args.shift();
unsigned priority;
- if (!check_unsigned(client, &priority, argv[1]))
+ if (!check_unsigned(client, &priority, priority_string))
return CommandResult::ERROR;
if (priority > 0xff) {
command_error(client, ACK_ERROR_ARG,
- "Priority out of range: %s", argv[1]);
+ "Priority out of range: %s", priority_string);
return CommandResult::ERROR;
}
- for (unsigned i = 2; i < argc; ++i) {
+ for (const char *i : args) {
unsigned start_position, end_position;
- if (!check_range(client, &start_position, &end_position,
- argv[i]))
+ if (!check_range(client, &start_position, &end_position, i))
return CommandResult::ERROR;
PlaylistResult result =
@@ -354,22 +349,23 @@ handle_prio(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_prioid(Client &client, unsigned argc, char *argv[])
+handle_prioid(Client &client, ConstBuffer<const char *> args)
{
+ const char *const priority_string = args.shift();
unsigned priority;
- if (!check_unsigned(client, &priority, argv[1]))
+ if (!check_unsigned(client, &priority, priority_string))
return CommandResult::ERROR;
if (priority > 0xff) {
command_error(client, ACK_ERROR_ARG,
- "Priority out of range: %s", argv[1]);
+ "Priority out of range: %s", priority_string);
return CommandResult::ERROR;
}
- for (unsigned i = 2; i < argc; ++i) {
+ for (const char *i : args) {
unsigned song_id;
- if (!check_unsigned(client, &song_id, argv[i]))
+ if (!check_unsigned(client, &song_id, i))
return CommandResult::ERROR;
PlaylistResult result =
@@ -382,14 +378,14 @@ handle_prioid(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_move(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_move(Client &client, ConstBuffer<const char *> args)
{
unsigned start, end;
int to;
- if (!check_range(client, &start, &end, argv[1]))
+ if (!check_range(client, &start, &end, args[0]))
return CommandResult::ERROR;
- if (!check_int(client, &to, argv[2]))
+ if (!check_int(client, &to, args[1]))
return CommandResult::ERROR;
PlaylistResult result =
@@ -398,27 +394,27 @@ handle_move(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_moveid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_moveid(Client &client, ConstBuffer<const char *> args)
{
unsigned id;
int to;
- if (!check_unsigned(client, &id, argv[1]))
+ if (!check_unsigned(client, &id, args[0]))
return CommandResult::ERROR;
- if (!check_int(client, &to, argv[2]))
+ if (!check_int(client, &to, args[1]))
return CommandResult::ERROR;
PlaylistResult result = client.partition.MoveId(id, to);
return print_playlist_result(client, result);
}
CommandResult
-handle_swap(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_swap(Client &client, ConstBuffer<const char *> args)
{
unsigned song1, song2;
- if (!check_unsigned(client, &song1, argv[1]))
+ if (!check_unsigned(client, &song1, args[0]))
return CommandResult::ERROR;
- if (!check_unsigned(client, &song2, argv[2]))
+ if (!check_unsigned(client, &song2, args[1]))
return CommandResult::ERROR;
PlaylistResult result =
@@ -427,13 +423,13 @@ handle_swap(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_swapid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_swapid(Client &client, ConstBuffer<const char *> args)
{
unsigned id1, id2;
- if (!check_unsigned(client, &id1, argv[1]))
+ if (!check_unsigned(client, &id1, args[0]))
return CommandResult::ERROR;
- if (!check_unsigned(client, &id2, argv[2]))
+ if (!check_unsigned(client, &id2, args[1]))
return CommandResult::ERROR;
PlaylistResult result = client.partition.SwapIds(id1, id2);
diff --git a/src/command/QueueCommands.hxx b/src/command/QueueCommands.hxx
index f98f7bad2..48641d2d1 100644
--- a/src/command/QueueCommands.hxx
+++ b/src/command/QueueCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,65 +23,66 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_add(Client &client, unsigned argc, char *argv[]);
+handle_add(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_addid(Client &client, unsigned argc, char *argv[]);
+handle_addid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_rangeid(Client &client, unsigned argc, char *argv[]);
+handle_rangeid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_delete(Client &client, unsigned argc, char *argv[]);
+handle_delete(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_deleteid(Client &client, unsigned argc, char *argv[]);
+handle_deleteid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlist(Client &client, unsigned argc, char *argv[]);
+handle_playlist(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_shuffle(Client &client, unsigned argc, char *argv[]);
+handle_shuffle(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_clear(Client &client, unsigned argc, char *argv[]);
+handle_clear(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_plchanges(Client &client, unsigned argc, char *argv[]);
+handle_plchanges(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_plchangesposid(Client &client, unsigned argc, char *argv[]);
+handle_plchangesposid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistinfo(Client &client, unsigned argc, char *argv[]);
+handle_playlistinfo(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistid(Client &client, unsigned argc, char *argv[]);
+handle_playlistid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistfind(Client &client, unsigned argc, char *argv[]);
+handle_playlistfind(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_playlistsearch(Client &client, unsigned argc, char *argv[]);
+handle_playlistsearch(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_prio(Client &client, unsigned argc, char *argv[]);
+handle_prio(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_prioid(Client &client, unsigned argc, char *argv[]);
+handle_prioid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_move(Client &client, unsigned argc, char *argv[]);
+handle_move(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_moveid(Client &client, unsigned argc, char *argv[]);
+handle_moveid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_swap(Client &client, unsigned argc, char *argv[]);
+handle_swap(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_swapid(Client &client, unsigned argc, char *argv[]);
+handle_swapid(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/StickerCommands.cxx b/src/command/StickerCommands.cxx
index 37506d51b..9dfe6f80d 100644
--- a/src/command/StickerCommands.cxx
+++ b/src/command/StickerCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -31,6 +31,7 @@
#include "Partition.hxx"
#include "Instance.hxx"
#include "util/Error.hxx"
+#include "util/ConstBuffer.hxx"
#include <string.h>
@@ -51,53 +52,64 @@ sticker_song_find_print_cb(const LightSong &song, const char *value,
}
static CommandResult
-handle_sticker_song(Client &client, unsigned argc, char *argv[])
+handle_sticker_song(Client &client, ConstBuffer<const char *> args)
{
Error error;
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return print_error(client, error);
+ const char *const cmd = args.front();
+
/* get song song_id key */
- if (argc == 5 && strcmp(argv[1], "get") == 0) {
- const LightSong *song = db->GetSong(argv[3], error);
+ if (args.size == 4 && strcmp(cmd, "get") == 0) {
+ const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
return print_error(client, error);
- const auto value = sticker_song_get_value(*song, argv[4]);
+ const auto value = sticker_song_get_value(*song, args[3],
+ error);
db->ReturnSong(song);
if (value.empty()) {
+ if (error.IsDefined())
+ return print_error(client, error);
+
command_error(client, ACK_ERROR_NO_EXIST,
"no such sticker");
return CommandResult::ERROR;
}
- sticker_print_value(client, argv[4], value.c_str());
+ sticker_print_value(client, args[3], value.c_str());
return CommandResult::OK;
/* list song song_id */
- } else if (argc == 4 && strcmp(argv[1], "list") == 0) {
- const LightSong *song = db->GetSong(argv[3], error);
+ } else if (args.size == 3 && strcmp(cmd, "list") == 0) {
+ const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
return print_error(client, error);
- sticker *sticker = sticker_song_get(*song);
+ sticker *sticker = sticker_song_get(*song, error);
db->ReturnSong(song);
if (sticker) {
sticker_print(client, *sticker);
sticker_free(sticker);
- }
+ } else if (error.IsDefined())
+ return print_error(client, error);
return CommandResult::OK;
/* set song song_id id key */
- } else if (argc == 6 && strcmp(argv[1], "set") == 0) {
- const LightSong *song = db->GetSong(argv[3], error);
+ } else if (args.size == 5 && strcmp(cmd, "set") == 0) {
+ const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
return print_error(client, error);
- bool ret = sticker_song_set_value(*song, argv[4], argv[5]);
+ bool ret = sticker_song_set_value(*song, args[3], args[4],
+ error);
db->ReturnSong(song);
if (!ret) {
+ if (error.IsDefined())
+ return print_error(client, error);
+
command_error(client, ACK_ERROR_SYSTEM,
"failed to set sticker value");
return CommandResult::ERROR;
@@ -105,17 +117,20 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::OK;
/* delete song song_id [key] */
- } else if ((argc == 4 || argc == 5) &&
- strcmp(argv[1], "delete") == 0) {
- const LightSong *song = db->GetSong(argv[3], error);
+ } else if ((args.size == 3 || args.size == 4) &&
+ strcmp(cmd, "delete") == 0) {
+ const LightSong *song = db->GetSong(args[2], error);
if (song == nullptr)
return print_error(client, error);
- bool ret = argc == 4
- ? sticker_song_delete(*song)
- : sticker_song_delete_value(*song, argv[4]);
+ bool ret = args.size == 3
+ ? sticker_song_delete(*song, error)
+ : sticker_song_delete_value(*song, args[3], error);
db->ReturnSong(song);
if (!ret) {
+ if (error.IsDefined())
+ return print_error(client, error);
+
command_error(client, ACK_ERROR_SYSTEM,
"no such sticker");
return CommandResult::ERROR;
@@ -123,20 +138,48 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
return CommandResult::OK;
/* find song dir key */
- } else if (argc == 5 && strcmp(argv[1], "find") == 0) {
+ } else if ((args.size == 4 || args.size == 6) &&
+ strcmp(cmd, "find") == 0) {
/* "sticker find song a/directory name" */
- const char *const base_uri = argv[3];
+ const char *const base_uri = args[2];
+
+ StickerOperator op = StickerOperator::EXISTS;
+ const char *value = nullptr;
+
+ if (args.size == 6) {
+ /* match the value */
+
+ const char *op_s = args[4];
+ value = args[5];
+
+ if (strcmp(op_s, "=") == 0)
+ op = StickerOperator::EQUALS;
+ else if (strcmp(op_s, "<") == 0)
+ op = StickerOperator::LESS_THAN;
+ else if (strcmp(op_s, ">") == 0)
+ op = StickerOperator::GREATER_THAN;
+ else {
+ command_error(client, ACK_ERROR_ARG,
+ "bad operator");
+ return CommandResult::ERROR;
+ }
+ }
bool success;
struct sticker_song_find_data data = {
client,
- argv[4],
+ args[3],
};
success = sticker_song_find(*db, base_uri, data.name,
- sticker_song_find_print_cb, &data);
+ op, value,
+ sticker_song_find_print_cb, &data,
+ error);
if (!success) {
+ if (error.IsDefined())
+ return print_error(client, error);
+
command_error(client, ACK_ERROR_SYSTEM,
"failed to set search sticker database");
return CommandResult::ERROR;
@@ -150,9 +193,9 @@ handle_sticker_song(Client &client, unsigned argc, char *argv[])
}
CommandResult
-handle_sticker(Client &client, unsigned argc, char *argv[])
+handle_sticker(Client &client, ConstBuffer<const char *> args)
{
- assert(argc >= 4);
+ assert(args.size >= 3);
if (!sticker_enabled()) {
command_error(client, ACK_ERROR_UNKNOWN,
@@ -160,8 +203,8 @@ handle_sticker(Client &client, unsigned argc, char *argv[])
return CommandResult::ERROR;
}
- if (strcmp(argv[2], "song") == 0)
- return handle_sticker_song(client, argc, argv);
+ if (strcmp(args[1], "song") == 0)
+ return handle_sticker_song(client, args);
else {
command_error(client, ACK_ERROR_ARG,
"unknown sticker domain");
diff --git a/src/command/StickerCommands.hxx b/src/command/StickerCommands.hxx
index cf46cd034..8b7a8f7bf 100644
--- a/src/command/StickerCommands.hxx
+++ b/src/command/StickerCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,8 +23,9 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_sticker(Client &client, unsigned argc, char *argv[]);
+handle_sticker(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx
index ee51c573e..a138ee2fe 100644
--- a/src/command/StorageCommands.cxx
+++ b/src/command/StorageCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
#include "protocol/Result.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
+#include "util/ConstBuffer.hxx"
#include "fs/Traits.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
@@ -167,7 +168,7 @@ print_storage_uri(Client &client, const Storage &storage)
}
CommandResult
-handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *argv[])
+handle_listmounts(Client &client, gcc_unused ConstBuffer<const char *> args)
{
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
@@ -189,7 +190,7 @@ handle_listmounts(Client &client, gcc_unused unsigned argc, gcc_unused char *arg
}
CommandResult
-handle_mount(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_mount(Client &client, ConstBuffer<const char *> args)
{
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
@@ -199,8 +200,8 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[])
CompositeStorage &composite = *(CompositeStorage *)_composite;
- const char *const local_uri = argv[1];
- const char *const remote_uri = argv[2];
+ const char *const local_uri = args[0];
+ const char *const remote_uri = args[1];
if (*local_uri == 0) {
command_error(client, ACK_ERROR_ARG, "Bad mount point");
@@ -252,7 +253,7 @@ handle_mount(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_unmount(Client &client, ConstBuffer<const char *> args)
{
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
@@ -262,7 +263,7 @@ handle_unmount(Client &client, gcc_unused unsigned argc, char *argv[])
CompositeStorage &composite = *(CompositeStorage *)_composite;
- const char *const local_uri = argv[1];
+ const char *const local_uri = args.front();
if (*local_uri == 0) {
command_error(client, ACK_ERROR_ARG, "Bad mount point");
diff --git a/src/command/StorageCommands.hxx b/src/command/StorageCommands.hxx
index a3636d54a..4a96b4058 100644
--- a/src/command/StorageCommands.hxx
+++ b/src/command/StorageCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
class Client;
class Storage;
+template<typename T> struct ConstBuffer;
CommandResult
handle_listfiles_storage(Client &client, Storage &storage, const char *uri);
@@ -32,12 +33,12 @@ CommandResult
handle_listfiles_storage(Client &client, const char *uri);
CommandResult
-handle_listmounts(Client &client, unsigned argc, char *argv[]);
+handle_listmounts(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_mount(Client &client, unsigned argc, char *argv[]);
+handle_mount(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_unmount(Client &client, unsigned argc, char *argv[]);
+handle_unmount(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/command/TagCommands.cxx b/src/command/TagCommands.cxx
index 2d537671c..bf5b67511 100644
--- a/src/command/TagCommands.cxx
+++ b/src/command/TagCommands.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,15 +25,16 @@
#include "protocol/Result.hxx"
#include "tag/Tag.hxx"
#include "Partition.hxx"
+#include "util/ConstBuffer.hxx"
CommandResult
-handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[])
+handle_addtagid(Client &client, ConstBuffer<const char *> args)
{
unsigned song_id;
- if (!check_unsigned(client, &song_id, argv[1]))
+ if (!check_unsigned(client, &song_id, args.front()))
return CommandResult::ERROR;
- const char *const tag_name = argv[2];
+ const char *const tag_name = args[1];
const TagType tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
command_error(client, ACK_ERROR_ARG,
@@ -41,7 +42,7 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[])
return CommandResult::ERROR;
}
- const char *const value = argv[3];
+ const char *const value = args[2];
Error error;
if (!client.partition.playlist.AddSongIdTag(song_id, tag_type, value,
@@ -52,15 +53,15 @@ handle_addtagid(Client &client, gcc_unused unsigned argc, char *argv[])
}
CommandResult
-handle_cleartagid(Client &client, unsigned argc, char *argv[])
+handle_cleartagid(Client &client, ConstBuffer<const char *> args)
{
unsigned song_id;
- if (!check_unsigned(client, &song_id, argv[1]))
+ if (!check_unsigned(client, &song_id, args.front()))
return CommandResult::ERROR;
TagType tag_type = TAG_NUM_OF_ITEM_TYPES;
- if (argc >= 3) {
- const char *const tag_name = argv[2];
+ if (args.size >= 2) {
+ const char *const tag_name = args[1];
tag_type = tag_name_parse_i(tag_name);
if (tag_type == TAG_NUM_OF_ITEM_TYPES) {
command_error(client, ACK_ERROR_ARG,
diff --git a/src/command/TagCommands.hxx b/src/command/TagCommands.hxx
index 748838e68..ee7c27bb9 100644
--- a/src/command/TagCommands.hxx
+++ b/src/command/TagCommands.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,11 +23,12 @@
#include "CommandResult.hxx"
class Client;
+template<typename T> struct ConstBuffer;
CommandResult
-handle_addtagid(Client &client, unsigned argc, char *argv[]);
+handle_addtagid(Client &client, ConstBuffer<const char *> args);
CommandResult
-handle_cleartagid(Client &client, unsigned argc, char *argv[]);
+handle_cleartagid(Client &client, ConstBuffer<const char *> args);
#endif
diff --git a/src/config/ConfigData.cxx b/src/config/Block.cxx
index 70e1e55ed..a74903b10 100644
--- a/src/config/ConfigData.cxx
+++ b/src/config/Block.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,18 +18,18 @@
*/
#include "config.h"
-#include "ConfigData.hxx"
+#include "Block.hxx"
#include "ConfigParser.hxx"
#include "ConfigPath.hxx"
-#include "util/Error.hxx"
-#include "fs/AllocatedPath.hxx"
#include "system/FatalError.hxx"
+#include "fs/AllocatedPath.hxx"
+#include "util/Error.hxx"
#include <assert.h>
#include <stdlib.h>
int
-block_param::GetIntValue() const
+BlockParam::GetIntValue() const
{
char *endptr;
long value2 = strtol(value.c_str(), &endptr, 0);
@@ -40,7 +40,7 @@ block_param::GetIntValue() const
}
unsigned
-block_param::GetUnsignedValue() const
+BlockParam::GetUnsignedValue() const
{
char *endptr;
unsigned long value2 = strtoul(value.c_str(), &endptr, 0);
@@ -51,7 +51,7 @@ block_param::GetUnsignedValue() const
}
bool
-block_param::GetBoolValue() const
+BlockParam::GetBoolValue() const
{
bool value2;
if (!get_bool(value.c_str(), &value2))
@@ -62,16 +62,13 @@ block_param::GetBoolValue() const
return value2;
}
-config_param::config_param(const char *_value, int _line)
- :next(nullptr), value(_value), line(_line), used(false) {}
-
-config_param::~config_param()
+ConfigBlock::~ConfigBlock()
{
delete next;
}
-const block_param *
-config_param::GetBlockParam(const char *name) const
+const BlockParam *
+ConfigBlock::GetBlockParam(const char *name) const
{
for (const auto &i : block_params) {
if (i.name == name) {
@@ -80,13 +77,13 @@ config_param::GetBlockParam(const char *name) const
}
}
- return NULL;
+ return nullptr;
}
const char *
-config_param::GetBlockValue(const char *name, const char *default_value) const
+ConfigBlock::GetBlockValue(const char *name, const char *default_value) const
{
- const block_param *bp = GetBlockParam(name);
+ const BlockParam *bp = GetBlockParam(name);
if (bp == nullptr)
return default_value;
@@ -94,7 +91,7 @@ config_param::GetBlockValue(const char *name, const char *default_value) const
}
AllocatedPath
-config_param::GetBlockPath(const char *name, const char *default_value,
+ConfigBlock::GetBlockPath(const char *name, const char *default_value,
Error &error) const
{
assert(!error.IsDefined());
@@ -102,7 +99,7 @@ config_param::GetBlockPath(const char *name, const char *default_value,
int line2 = line;
const char *s;
- const block_param *bp = GetBlockParam(name);
+ const BlockParam *bp = GetBlockParam(name);
if (bp != nullptr) {
line2 = bp->line;
s = bp->value.c_str();
@@ -122,15 +119,15 @@ config_param::GetBlockPath(const char *name, const char *default_value,
}
AllocatedPath
-config_param::GetBlockPath(const char *name, Error &error) const
+ConfigBlock::GetBlockPath(const char *name, Error &error) const
{
return GetBlockPath(name, nullptr, error);
}
int
-config_param::GetBlockValue(const char *name, int default_value) const
+ConfigBlock::GetBlockValue(const char *name, int default_value) const
{
- const block_param *bp = GetBlockParam(name);
+ const BlockParam *bp = GetBlockParam(name);
if (bp == nullptr)
return default_value;
@@ -138,9 +135,9 @@ config_param::GetBlockValue(const char *name, int default_value) const
}
unsigned
-config_param::GetBlockValue(const char *name, unsigned default_value) const
+ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const
{
- const block_param *bp = GetBlockParam(name);
+ const BlockParam *bp = GetBlockParam(name);
if (bp == nullptr)
return default_value;
@@ -149,10 +146,10 @@ config_param::GetBlockValue(const char *name, unsigned default_value) const
gcc_pure
bool
-config_param::GetBlockValue(const char *name, bool default_value) const
+ConfigBlock::GetBlockValue(const char *name, bool default_value) const
{
- const block_param *bp = GetBlockParam(name);
- if (bp == NULL)
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp == nullptr)
return default_value;
return bp->GetBoolValue();
diff --git a/src/config/ConfigData.hxx b/src/config/Block.hxx
index e42d674ba..9e72018ca 100644
--- a/src/config/ConfigData.hxx
+++ b/src/config/Block.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,20 +17,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_CONFIG_DATA_HXX
-#define MPD_CONFIG_DATA_HXX
+#ifndef MPD_CONFIG_BLOCK_HXX
+#define MPD_CONFIG_BLOCK_HXX
-#include "ConfigOption.hxx"
+#include "check.h"
+#include "Param.hxx"
#include "Compiler.h"
#include <string>
-#include <array>
#include <vector>
-class AllocatedPath;
class Error;
+class AllocatedPath;
-struct block_param {
+struct BlockParam {
std::string name;
std::string value;
int line;
@@ -42,7 +42,7 @@ struct block_param {
mutable bool used;
gcc_nonnull_all
- block_param(const char *_name, const char *_value, int _line=-1)
+ BlockParam(const char *_name, const char *_value, int _line=-1)
:name(_name), value(_value), line(_line), used(false) {}
gcc_pure
@@ -55,18 +55,16 @@ struct block_param {
bool GetBoolValue() const;
};
-struct config_param {
+struct ConfigBlock {
/**
- * The next config_param with the same name. The destructor
+ * The next #ConfigBlock with the same name. The destructor
* deletes the whole chain.
*/
- struct config_param *next;
-
- std::string value;
+ ConfigBlock *next;
- unsigned int line;
+ int line;
- std::vector<block_param> block_params;
+ std::vector<BlockParam> block_params;
/**
* This flag is false when nobody has queried the value of
@@ -74,17 +72,14 @@ struct config_param {
*/
bool used;
- config_param(int _line=-1)
+ explicit ConfigBlock(int _line=-1)
:next(nullptr), line(_line), used(false) {}
- gcc_nonnull_all
- config_param(const char *_value, int _line=-1);
-
- config_param(const config_param &) = delete;
+ ConfigBlock(const ConfigBlock &) = delete;
- ~config_param();
+ ~ConfigBlock();
- config_param &operator=(const config_param &) = delete;
+ ConfigBlock &operator=(const ConfigBlock &) = delete;
/**
* Determine if this is a "null" instance, i.e. an empty
@@ -92,7 +87,12 @@ struct config_param {
* configuration file.
*/
bool IsNull() const {
- return line == unsigned(-1);
+ return line < 0;
+ }
+
+ gcc_pure
+ bool IsEmpty() const {
+ return block_params.empty();
}
gcc_nonnull_all
@@ -102,14 +102,14 @@ struct config_param {
}
gcc_nonnull_all gcc_pure
- const block_param *GetBlockParam(const char *_name) const;
+ const BlockParam *GetBlockParam(const char *_name) const;
gcc_pure
const char *GetBlockValue(const char *name,
const char *default_value=nullptr) const;
/**
- * Same as config_dup_path(), but looks up the setting in the
+ * Same as config_get_path(), but looks up the setting in the
* specified block.
*/
AllocatedPath GetBlockPath(const char *name, const char *default_value,
@@ -127,8 +127,4 @@ struct config_param {
bool GetBlockValue(const char *name, bool default_value) const;
};
-struct ConfigData {
- std::array<config_param *, std::size_t(CONF_MAX)> params;
-};
-
#endif
diff --git a/src/config/ConfigDefaults.hxx b/src/config/ConfigDefaults.hxx
index c50f28c91..2dca5d469 100644
--- a/src/config/ConfigDefaults.hxx
+++ b/src/config/ConfigDefaults.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigError.cxx b/src/config/ConfigError.cxx
index 70aff7175..b2a773b15 100644
--- a/src/config/ConfigError.cxx
+++ b/src/config/ConfigError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigError.hxx b/src/config/ConfigError.hxx
index cbfa79df3..89543599d 100644
--- a/src/config/ConfigError.hxx
+++ b/src/config/ConfigError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigFile.cxx b/src/config/ConfigFile.cxx
index 1329c4cd4..b6164b8bc 100644
--- a/src/config/ConfigFile.cxx
+++ b/src/config/ConfigFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,28 +19,27 @@
#include "config.h"
#include "ConfigFile.hxx"
-#include "ConfigData.hxx"
+#include "Data.hxx"
+#include "Param.hxx"
+#include "Block.hxx"
#include "ConfigTemplates.hxx"
#include "util/Tokenizer.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#include "fs/Limits.hxx"
#include "fs/Path.hxx"
-#include "fs/FileSystem.hxx"
+#include "fs/io/FileReader.hxx"
+#include "fs/io/BufferedReader.hxx"
#include "Log.hxx"
#include <assert.h>
-#include <stdio.h>
-#define MAX_STRING_SIZE MPD_PATH_MAX+80
-
-#define CONF_COMMENT '#'
+static constexpr char CONF_COMMENT = '#';
static constexpr Domain config_file_domain("config_file");
static bool
-config_read_name_value(struct config_param *param, char *input, unsigned line,
+config_read_name_value(ConfigBlock &block, char *input, unsigned line,
Error &error)
{
Tokenizer tokenizer(input);
@@ -67,7 +66,7 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
return false;
}
- const struct block_param *bp = param->GetBlockParam(name);
+ const BlockParam *bp = block.GetBlockParam(name);
if (bp != nullptr) {
error.Format(config_file_domain,
"\"%s\" is duplicate, first defined on line %i",
@@ -75,27 +74,26 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
return false;
}
- param->AddBlockParam(name, value, line);
+ block.AddBlockParam(name, value, line);
return true;
}
-static struct config_param *
-config_read_block(FILE *fp, int *count, char *string, Error &error)
+static ConfigBlock *
+config_read_block(BufferedReader &reader, Error &error)
{
- struct config_param *ret = new config_param(*count);
+ auto *ret = new ConfigBlock(reader.GetLineNumber());
while (true) {
- char *line;
-
- line = fgets(string, MAX_STRING_SIZE, fp);
+ char *line = reader.ReadLine();
if (line == nullptr) {
delete ret;
- error.Set(config_file_domain,
- "Expected '}' before end-of-file");
+
+ if (reader.Check(error))
+ error.Set(config_file_domain,
+ "Expected '}' before end-of-file");
return nullptr;
}
- (*count)++;
line = StripLeft(line);
if (*line == 0 || *line == CONF_COMMENT)
continue;
@@ -108,8 +106,8 @@ config_read_block(FILE *fp, int *count, char *string, Error &error)
if (*line != 0 && *line != CONF_COMMENT) {
delete ret;
error.Format(config_file_domain,
- "line %i: Unknown tokens after '}'",
- *count);
+ "line %y: Unknown tokens after '}'",
+ reader.GetLineNumber());
return nullptr;
}
@@ -118,10 +116,11 @@ config_read_block(FILE *fp, int *count, char *string, Error &error)
/* parse name and value */
- if (!config_read_name_value(ret, line, *count, error)) {
+ if (!config_read_name_value(*ret, line, reader.GetLineNumber(),
+ error)) {
assert(*line != 0);
delete ret;
- error.FormatPrefix("line %i: ", *count);
+ error.FormatPrefix("line %u: ", reader.GetLineNumber());
return nullptr;
}
}
@@ -129,6 +128,64 @@ config_read_block(FILE *fp, int *count, char *string, Error &error)
gcc_nonnull_all
static void
+Append(ConfigBlock *&head, ConfigBlock *p)
+{
+ assert(p->next == nullptr);
+
+ auto **i = &head;
+ while (*i != nullptr)
+ i = &(*i)->next;
+
+ *i = p;
+}
+
+static bool
+ReadConfigBlock(ConfigData &config_data, BufferedReader &reader,
+ const char *name, ConfigBlockOption o,
+ Tokenizer &tokenizer,
+ Error &error)
+{
+ const unsigned i = unsigned(o);
+ const ConfigTemplate &option = config_block_templates[i];
+ ConfigBlock *&head = config_data.blocks[i];
+
+ if (head != nullptr && !option.repeatable) {
+ ConfigBlock *block = head;
+ error.Format(config_file_domain,
+ "config parameter \"%s\" is first defined "
+ "on line %d and redefined on line %u\n",
+ name, block->line,
+ reader.GetLineNumber());
+ return false;
+ }
+
+ /* now parse the block or the value */
+
+ if (tokenizer.CurrentChar() != '{') {
+ error.Format(config_file_domain,
+ "line %u: '{' expected",
+ reader.GetLineNumber());
+ return false;
+ }
+
+ char *line = StripLeft(tokenizer.Rest() + 1);
+ if (*line != 0 && *line != CONF_COMMENT) {
+ error.Format(config_file_domain,
+ "line %u: Unknown tokens after '{'",
+ reader.GetLineNumber());
+ return false;
+ }
+
+ auto *param = config_read_block(reader, error);
+ if (param == nullptr)
+ return false;
+
+ Append(head, param);
+ return true;
+}
+
+gcc_nonnull_all
+static void
Append(config_param *&head, config_param *p)
{
assert(p->next == nullptr);
@@ -141,21 +198,62 @@ Append(config_param *&head, config_param *p)
}
static bool
-ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error)
+ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
+ const char *name, ConfigOption o,
+ Tokenizer &tokenizer,
+ Error &error)
{
- assert(fp != nullptr);
+ const unsigned i = unsigned(o);
+ const ConfigTemplate &option = config_param_templates[i];
+ config_param *&head = config_data.params[i];
- char string[MAX_STRING_SIZE + 1];
- int count = 0;
- struct config_param *param;
+ if (head != nullptr && !option.repeatable) {
+ struct config_param *param = head;
+ error.Format(config_file_domain,
+ "config parameter \"%s\" is first defined "
+ "on line %d and redefined on line %u\n",
+ name, param->line,
+ reader.GetLineNumber());
+ return false;
+ }
- while (fgets(string, MAX_STRING_SIZE, fp)) {
- char *line;
- const char *name, *value;
+ /* now parse the block or the value */
- count++;
+ const char *value = tokenizer.NextString(error);
+ if (value == nullptr) {
+ if (tokenizer.IsEnd())
+ error.Format(config_file_domain,
+ "line %u: Value missing",
+ reader.GetLineNumber());
+ else
+ error.FormatPrefix("line %u: ",
+ reader.GetLineNumber());
- line = StripLeft(string);
+ return false;
+ }
+
+ if (!tokenizer.IsEnd() &&
+ tokenizer.CurrentChar() != CONF_COMMENT) {
+ error.Format(config_file_domain,
+ "line %u: Unknown tokens after value",
+ reader.GetLineNumber());
+ return false;
+ }
+
+ auto *param = new config_param(value, reader.GetLineNumber());
+ Append(head, param);
+ return true;
+}
+
+static bool
+ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
+{
+ while (true) {
+ char *line = reader.ReadLine();
+ if (line == nullptr)
+ return true;
+
+ line = StripLeft(line);
if (*line == 0 || *line == CONF_COMMENT)
continue;
@@ -163,10 +261,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error)
by either the value or '{' */
Tokenizer tokenizer(line);
- name = tokenizer.NextWord(error);
+ const char *name = tokenizer.NextWord(error);
if (name == nullptr) {
assert(!tokenizer.IsEnd());
- error.FormatPrefix("line %i: ", count);
+ error.FormatPrefix("line %u: ", reader.GetLineNumber());
return false;
}
@@ -174,79 +272,23 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error)
"repeatable" flag */
const ConfigOption o = ParseConfigOptionName(name);
- if (o == CONF_MAX) {
- error.Format(config_file_domain,
- "unrecognized parameter in config file at "
- "line %i: %s\n", count, name);
- return false;
- }
-
- const unsigned i = unsigned(o);
- const ConfigTemplate &option = config_templates[i];
- config_param *&head = config_data.params[i];
-
- if (head != nullptr && !option.repeatable) {
- param = head;
- error.Format(config_file_domain,
- "config parameter \"%s\" is first defined "
- "on line %i and redefined on line %i\n",
- name, param->line, count);
- return false;
- }
-
- /* now parse the block or the value */
-
- if (option.block) {
- /* it's a block, call config_read_block() */
-
- if (tokenizer.CurrentChar() != '{') {
- error.Format(config_file_domain,
- "line %i: '{' expected", count);
- return false;
- }
-
- line = StripLeft(tokenizer.Rest() + 1);
- if (*line != 0 && *line != CONF_COMMENT) {
- error.Format(config_file_domain,
- "line %i: Unknown tokens after '{'",
- count);
+ ConfigBlockOption bo;
+ if (o != ConfigOption::MAX) {
+ if (!ReadConfigParam(config_data, reader, name, o,
+ tokenizer, error))
return false;
- }
-
- param = config_read_block(fp, &count, string, error);
- if (param == nullptr) {
+ } else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) {
+ if (!ReadConfigBlock(config_data, reader, name, bo,
+ tokenizer, error))
return false;
- }
} else {
- /* a string value */
-
- value = tokenizer.NextString(error);
- if (value == nullptr) {
- if (tokenizer.IsEnd())
- error.Format(config_file_domain,
- "line %i: Value missing",
- count);
- else
- error.FormatPrefix("line %i: ", count);
-
- return false;
- }
-
- if (!tokenizer.IsEnd() &&
- tokenizer.CurrentChar() != CONF_COMMENT) {
- error.Format(config_file_domain,
- "line %i: Unknown tokens after value",
- count);
- return false;
- }
-
- param = new config_param(value, count);
+ error.Format(config_file_domain,
+ "unrecognized parameter in config file at "
+ "line %u: %s\n",
+ reader.GetLineNumber(), name);
+ return false;
}
-
- Append(head, param);
}
-
- return true;
}
bool
@@ -257,13 +299,11 @@ ReadConfigFile(ConfigData &config_data, Path path, Error &error)
FormatDebug(config_file_domain, "loading file %s", path_utf8.c_str());
- FILE *fp = FOpen(path, FOpenMode::ReadText);
- if (fp == nullptr) {
- error.FormatErrno("Failed to open %s", path_utf8.c_str());
+ FileReader file(path, error);
+ if (!file.IsDefined())
return false;
- }
- bool result = ReadConfigFile(config_data, fp, error);
- fclose(fp);
- return result;
+ BufferedReader reader(file);
+ return ReadConfigFile(config_data, reader, error) &&
+ reader.Check(error);
}
diff --git a/src/config/ConfigFile.hxx b/src/config/ConfigFile.hxx
index b87182c6a..30bee0614 100644
--- a/src/config/ConfigFile.hxx
+++ b/src/config/ConfigFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigGlobal.cxx b/src/config/ConfigGlobal.cxx
index 9bc83398c..192baffec 100644
--- a/src/config/ConfigGlobal.cxx
+++ b/src/config/ConfigGlobal.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,9 @@
#include "config.h"
#include "ConfigGlobal.hxx"
#include "ConfigParser.hxx"
-#include "ConfigData.hxx"
+#include "Data.hxx"
+#include "Param.hxx"
+#include "Block.hxx"
#include "ConfigFile.hxx"
#include "ConfigPath.hxx"
#include "ConfigError.hxx"
@@ -36,8 +38,7 @@ static ConfigData config_data;
void config_global_finish(void)
{
- for (auto i : config_data.params)
- delete i;
+ config_data.Clear();
}
void config_global_init(void)
@@ -51,15 +52,15 @@ ReadConfigFile(Path path, Error &error)
}
static void
-Check(const config_param *param)
+Check(const ConfigBlock &block)
{
- if (!param->used)
- /* this whole config_param was not queried at all -
+ if (!block.used)
+ /* this whole block was not queried at all -
the feature might be disabled at compile time?
Silently ignore it here. */
return;
- for (const auto &i : param->block_params) {
+ for (const auto &i : block.block_params) {
if (!i.used)
FormatWarning(config_domain,
"option '%s' on line %i was not recognized",
@@ -69,9 +70,9 @@ Check(const config_param *param)
void config_global_check(void)
{
- for (auto i : config_data.params)
- for (const config_param *p = i; p != nullptr; p = p->next)
- Check(p);
+ for (auto i : config_data.blocks)
+ for (const auto *p = i; p != nullptr; p = p->next)
+ Check(*p);
}
const config_param *
@@ -83,18 +84,27 @@ config_get_param(ConfigOption option)
return param;
}
-const config_param *
-config_find_block(ConfigOption option, const char *key, const char *value)
+const ConfigBlock *
+config_get_block(ConfigBlockOption option)
+{
+ ConfigBlock *block = config_data.blocks[unsigned(option)];
+ if (block != nullptr)
+ block->used = true;
+ return block;
+}
+
+const ConfigBlock *
+config_find_block(ConfigBlockOption option, const char *key, const char *value)
{
- for (const config_param *param = config_get_param(option);
- param != nullptr; param = param->next) {
- const char *value2 = param->GetBlockValue(key);
+ for (const auto *block = config_get_block(option);
+ block != nullptr; block = block->next) {
+ const char *value2 = block->GetBlockValue(key);
if (value2 == nullptr)
FormatFatalError("block without '%s' name in line %d",
- key, param->line);
+ key, block->line);
if (strcmp(value2, value) == 0)
- return param;
+ return block;
}
return nullptr;
diff --git a/src/config/ConfigGlobal.hxx b/src/config/ConfigGlobal.hxx
index 831418d03..3c6a938a6 100644
--- a/src/config/ConfigGlobal.hxx
+++ b/src/config/ConfigGlobal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@ class Error;
class Path;
class AllocatedPath;
struct config_param;
+struct ConfigBlock;
void config_global_init(void);
void config_global_finish(void);
@@ -44,6 +45,10 @@ gcc_pure
const config_param *
config_get_param(enum ConfigOption option);
+gcc_pure
+const ConfigBlock *
+config_get_block(enum ConfigBlockOption option);
+
/**
* Find a block with a matching attribute.
*
@@ -52,8 +57,8 @@ config_get_param(enum ConfigOption option);
* @param value the expected attribute value
*/
gcc_pure
-const config_param *
-config_find_block(ConfigOption option, const char *key, const char *value);
+const ConfigBlock *
+config_find_block(ConfigBlockOption option, const char *key, const char *value);
/* Note on gcc_pure: Some of the functions declared pure are not
really pure in strict sense. They have side effect such that they
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index 8eb4c7eaf..5acd6fd49 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,71 +22,93 @@
#include "Compiler.h"
-enum ConfigOption {
- CONF_MUSIC_DIR,
- CONF_PLAYLIST_DIR,
- CONF_FOLLOW_INSIDE_SYMLINKS,
- CONF_FOLLOW_OUTSIDE_SYMLINKS,
- CONF_DB_FILE,
- CONF_STICKER_FILE,
- CONF_LOG_FILE,
- CONF_PID_FILE,
- CONF_STATE_FILE,
- CONF_STATE_FILE_INTERVAL,
- CONF_RESTORE_PAUSED,
- CONF_USER,
- CONF_GROUP,
- CONF_BIND_TO_ADDRESS,
- CONF_PORT,
- CONF_LOG_LEVEL,
- CONF_ZEROCONF_NAME,
- CONF_ZEROCONF_ENABLED,
- CONF_PASSWORD,
- CONF_DEFAULT_PERMS,
- CONF_AUDIO_OUTPUT,
- CONF_AUDIO_OUTPUT_FORMAT,
- CONF_MIXER_TYPE,
- CONF_REPLAYGAIN,
- CONF_REPLAYGAIN_PREAMP,
- CONF_REPLAYGAIN_MISSING_PREAMP,
- CONF_REPLAYGAIN_LIMIT,
- CONF_VOLUME_NORMALIZATION,
- CONF_SAMPLERATE_CONVERTER,
- CONF_AUDIO_BUFFER_SIZE,
- CONF_BUFFER_BEFORE_PLAY,
- CONF_HTTP_PROXY_HOST,
- CONF_HTTP_PROXY_PORT,
- CONF_HTTP_PROXY_USER,
- CONF_HTTP_PROXY_PASSWORD,
- CONF_CONN_TIMEOUT,
- CONF_MAX_CONN,
- CONF_MAX_PLAYLIST_LENGTH,
- CONF_MAX_COMMAND_LIST_SIZE,
- CONF_MAX_OUTPUT_BUFFER_SIZE,
- CONF_FS_CHARSET,
- CONF_ID3V1_ENCODING,
- CONF_METADATA_TO_USE,
- CONF_SAVE_ABSOLUTE_PATHS,
- CONF_DECODER,
- CONF_INPUT,
- CONF_GAPLESS_MP3_PLAYBACK,
- CONF_PLAYLIST_PLUGIN,
- CONF_AUTO_UPDATE,
- CONF_AUTO_UPDATE_DEPTH,
- CONF_DESPOTIFY_USER,
- CONF_DESPOTIFY_PASSWORD,
- CONF_DESPOTIFY_HIGH_BITRATE,
- CONF_AUDIO_FILTER,
- CONF_DATABASE,
- CONF_NEIGHBORS,
- CONF_MAX
+#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7)
+/* "INPUT" is declared by winuser.h */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#endif
+
+enum class ConfigOption {
+ MUSIC_DIR,
+ PLAYLIST_DIR,
+ FOLLOW_INSIDE_SYMLINKS,
+ FOLLOW_OUTSIDE_SYMLINKS,
+ DB_FILE,
+ STICKER_FILE,
+ LOG_FILE,
+ PID_FILE,
+ STATE_FILE,
+ STATE_FILE_INTERVAL,
+ RESTORE_PAUSED,
+ USER,
+ GROUP,
+ BIND_TO_ADDRESS,
+ PORT,
+ LOG_LEVEL,
+ ZEROCONF_NAME,
+ ZEROCONF_ENABLED,
+ PASSWORD,
+ DEFAULT_PERMS,
+ AUDIO_OUTPUT_FORMAT,
+ MIXER_TYPE,
+ REPLAYGAIN,
+ REPLAYGAIN_PREAMP,
+ REPLAYGAIN_MISSING_PREAMP,
+ REPLAYGAIN_LIMIT,
+ VOLUME_NORMALIZATION,
+ SAMPLERATE_CONVERTER,
+ AUDIO_BUFFER_SIZE,
+ BUFFER_BEFORE_PLAY,
+ HTTP_PROXY_HOST,
+ HTTP_PROXY_PORT,
+ HTTP_PROXY_USER,
+ HTTP_PROXY_PASSWORD,
+ CONN_TIMEOUT,
+ MAX_CONN,
+ MAX_PLAYLIST_LENGTH,
+ MAX_COMMAND_LIST_SIZE,
+ MAX_OUTPUT_BUFFER_SIZE,
+ FS_CHARSET,
+ ID3V1_ENCODING,
+ METADATA_TO_USE,
+ SAVE_ABSOLUTE_PATHS,
+ GAPLESS_MP3_PLAYBACK,
+ AUTO_UPDATE,
+ AUTO_UPDATE_DEPTH,
+ DESPOTIFY_USER,
+ DESPOTIFY_PASSWORD,
+ DESPOTIFY_HIGH_BITRATE,
+ MAX
};
+enum class ConfigBlockOption {
+ AUDIO_OUTPUT,
+ DECODER,
+ INPUT,
+ PLAYLIST_PLUGIN,
+ RESAMPLER,
+ AUDIO_FILTER,
+ DATABASE,
+ NEIGHBORS,
+ MAX
+};
+
+#if defined(WIN32) && CLANG_OR_GCC_VERSION(4,7)
+#pragma GCC diagnostic pop
+#endif
+
/**
- * @return #CONF_MAX if not found
+ * @return #ConfigOption::MAX if not found
*/
gcc_pure
enum ConfigOption
ParseConfigOptionName(const char *name);
+/**
+ * @return #ConfigOption::MAX if not found
+ */
+gcc_pure
+enum ConfigBlockOption
+ParseConfigBlockOptionName(const char *name);
+
#endif
diff --git a/src/config/ConfigParser.cxx b/src/config/ConfigParser.cxx
index 3535c9a13..40afe1edd 100644
--- a/src/config/ConfigParser.cxx
+++ b/src/config/ConfigParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,8 +23,8 @@
bool
get_bool(const char *value, bool *value_r)
{
- static const char *t[] = { "yes", "true", "1", nullptr };
- static const char *f[] = { "no", "false", "0", nullptr };
+ static const char *const t[] = { "yes", "true", "1", nullptr };
+ static const char *const f[] = { "no", "false", "0", nullptr };
if (string_array_contains(t, value)) {
*value_r = true;
diff --git a/src/config/ConfigParser.hxx b/src/config/ConfigParser.hxx
index 06151b0bd..c696801f5 100644
--- a/src/config/ConfigParser.hxx
+++ b/src/config/ConfigParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigPath.cxx b/src/config/ConfigPath.cxx
index a3b3f83a5..fe42fdf60 100644
--- a/src/config/ConfigPath.cxx
+++ b/src/config/ConfigPath.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -70,7 +70,7 @@ GetHome(Error &error)
static AllocatedPath
GetConfiguredHome(Error &error)
{
- const char *user = config_get_string(CONF_USER, nullptr);
+ const char *user = config_get_string(ConfigOption::USER, nullptr);
return user != nullptr
? GetHome(user, error)
: GetHome(error);
diff --git a/src/config/ConfigPath.hxx b/src/config/ConfigPath.hxx
index a5518a497..afd3e0435 100644
--- a/src/config/ConfigPath.hxx
+++ b/src/config/ConfigPath.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 58ee56425..6fbf025fc 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,80 +19,110 @@
#include "ConfigTemplates.hxx"
#include "ConfigOption.hxx"
+#include "util/Macros.hxx"
#include <string.h>
-const ConfigTemplate config_templates[] = {
- { "music_directory", false, false },
- { "playlist_directory", false, false },
- { "follow_inside_symlinks", false, false },
- { "follow_outside_symlinks", false, false },
- { "db_file", false, false },
- { "sticker_file", false, false },
- { "log_file", false, false },
- { "pid_file", false, false },
- { "state_file", false, false },
- { "state_file_interval", false, false },
- { "restore_paused", false, false },
- { "user", false, false },
- { "group", false, false },
- { "bind_to_address", true, false },
- { "port", false, false },
- { "log_level", false, false },
- { "zeroconf_name", false, false },
- { "zeroconf_enabled", false, false },
- { "password", true, false },
- { "default_permissions", false, false },
- { "audio_output", true, true },
- { "audio_output_format", false, false },
- { "mixer_type", false, false },
- { "replaygain", false, false },
- { "replaygain_preamp", false, false },
- { "replaygain_missing_preamp", false, false },
- { "replaygain_limit", false, false },
- { "volume_normalization", false, false },
- { "samplerate_converter", false, false },
- { "audio_buffer_size", false, false },
- { "buffer_before_play", false, false },
- { "http_proxy_host", false, false },
- { "http_proxy_port", false, false },
- { "http_proxy_user", false, false },
- { "http_proxy_password", false, false },
- { "connection_timeout", false, false },
- { "max_connections", false, false },
- { "max_playlist_length", false, false },
- { "max_command_list_size", false, false },
- { "max_output_buffer_size", false, false },
- { "filesystem_charset", false, false },
- { "id3v1_encoding", false, false },
- { "metadata_to_use", false, false },
- { "save_absolute_paths_in_playlists", false, false },
- { "decoder", true, true },
- { "input", true, true },
- { "gapless_mp3_playback", false, false },
- { "playlist_plugin", true, true },
- { "auto_update", false, false },
- { "auto_update_depth", false, false },
- { "despotify_user", false, false },
- { "despotify_password", false, false},
- { "despotify_high_bitrate", false, false },
- { "filter", true, true },
- { "database", false, true },
- { "neighbors", true, true },
+const ConfigTemplate config_param_templates[] = {
+ { "music_directory", false },
+ { "playlist_directory", false },
+ { "follow_inside_symlinks", false },
+ { "follow_outside_symlinks", false },
+ { "db_file", false },
+ { "sticker_file", false },
+ { "log_file", false },
+ { "pid_file", false },
+ { "state_file", false },
+ { "state_file_interval", false },
+ { "restore_paused", false },
+ { "user", false },
+ { "group", false },
+ { "bind_to_address", true },
+ { "port", false },
+ { "log_level", false },
+ { "zeroconf_name", false },
+ { "zeroconf_enabled", false },
+ { "password", true },
+ { "default_permissions", false },
+ { "audio_output_format", false },
+ { "mixer_type", false },
+ { "replaygain", false },
+ { "replaygain_preamp", false },
+ { "replaygain_missing_preamp", false },
+ { "replaygain_limit", false },
+ { "volume_normalization", false },
+ { "samplerate_converter", false },
+ { "audio_buffer_size", false },
+ { "buffer_before_play", false },
+ { "http_proxy_host", false },
+ { "http_proxy_port", false },
+ { "http_proxy_user", false },
+ { "http_proxy_password", false },
+ { "connection_timeout", false },
+ { "max_connections", false },
+ { "max_playlist_length", false },
+ { "max_command_list_size", false },
+ { "max_output_buffer_size", false },
+ { "filesystem_charset", false },
+ { "id3v1_encoding", false },
+ { "metadata_to_use", false },
+ { "save_absolute_paths_in_playlists", false },
+ { "gapless_mp3_playback", false },
+ { "auto_update", false },
+ { "auto_update_depth", false },
+ { "despotify_user", false },
+ { "despotify_password", false },
+ { "despotify_high_bitrate", false },
};
-static constexpr unsigned n_config_templates =
- sizeof(config_templates) / sizeof(config_templates[0]);
+static constexpr unsigned n_config_param_templates =
+ ARRAY_SIZE(config_param_templates);
-static_assert(n_config_templates == unsigned(CONF_MAX),
- "Wrong number of config_templates");
+static_assert(n_config_param_templates == unsigned(ConfigOption::MAX),
+ "Wrong number of config_param_templates");
+
+const ConfigTemplate config_block_templates[] = {
+ { "audio_output", true },
+ { "decoder", true },
+ { "input", true },
+ { "playlist_plugin", true },
+ { "resampler", false },
+ { "filter", true },
+ { "database", false },
+ { "neighbors", true },
+};
+
+static constexpr unsigned n_config_block_templates =
+ ARRAY_SIZE(config_block_templates);
+
+static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX),
+ "Wrong number of config_block_templates");
+
+gcc_pure
+static inline unsigned
+ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
+ const char *name)
+{
+ unsigned i = 0;
+ for (; i < count; ++i)
+ if (strcmp(templates[i].name, name) == 0)
+ break;
+
+ return i;
+}
ConfigOption
ParseConfigOptionName(const char *name)
{
- for (unsigned i = 0; i < n_config_templates; ++i)
- if (strcmp(config_templates[i].name, name) == 0)
- return ConfigOption(i);
+ return ConfigOption(ParseConfigTemplateName(config_param_templates,
+ n_config_param_templates,
+ name));
+}
- return CONF_MAX;
+ConfigBlockOption
+ParseConfigBlockOptionName(const char *name)
+{
+ return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
+ n_config_block_templates,
+ name));
}
diff --git a/src/config/ConfigTemplates.hxx b/src/config/ConfigTemplates.hxx
index 90d098dc0..1aa6c6e8d 100644
--- a/src/config/ConfigTemplates.hxx
+++ b/src/config/ConfigTemplates.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,9 +23,9 @@
struct ConfigTemplate {
const char *const name;
const bool repeatable;
- const bool block;
};
-extern const ConfigTemplate config_templates[];
+extern const ConfigTemplate config_param_templates[];
+extern const ConfigTemplate config_block_templates[];
#endif
diff --git a/src/config/Data.cxx b/src/config/Data.cxx
new file mode 100644
index 000000000..52521e31a
--- /dev/null
+++ b/src/config/Data.cxx
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Data.hxx"
+#include "Param.hxx"
+#include "Block.hxx"
+
+void
+ConfigData::Clear()
+{
+ for (auto &i : params) {
+ delete i;
+ i = nullptr;
+ }
+
+ for (auto &i : blocks) {
+ delete i;
+ i = nullptr;
+ }
+}
diff --git a/src/config/Data.hxx b/src/config/Data.hxx
new file mode 100644
index 000000000..6036c49e6
--- /dev/null
+++ b/src/config/Data.hxx
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_CONFIG_DATA_HXX
+#define MPD_CONFIG_DATA_HXX
+
+#include "ConfigOption.hxx"
+
+#include <array>
+
+struct config_param;
+struct ConfigBlock;
+
+struct ConfigData {
+ std::array<config_param *, std::size_t(ConfigOption::MAX)> params;
+ std::array<ConfigBlock *, std::size_t(ConfigBlockOption::MAX)> blocks;
+
+ void Clear();
+};
+
+#endif
diff --git a/src/config/Param.cxx b/src/config/Param.cxx
new file mode 100644
index 000000000..bfd9743d2
--- /dev/null
+++ b/src/config/Param.cxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Param.hxx"
+
+config_param::config_param(const char *_value, int _line)
+ :next(nullptr), value(_value), line(_line), used(false) {}
+
+config_param::~config_param()
+{
+ delete next;
+}
diff --git a/src/config/Param.hxx b/src/config/Param.hxx
new file mode 100644
index 000000000..e6a039c2a
--- /dev/null
+++ b/src/config/Param.hxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_CONFIG_PARAM_HXX
+#define MPD_CONFIG_PARAM_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#include <string>
+
+struct config_param {
+ /**
+ * The next config_param with the same name. The destructor
+ * deletes the whole chain.
+ */
+ struct config_param *next;
+
+ std::string value;
+
+ int line;
+
+ /**
+ * This flag is false when nobody has queried the value of
+ * this option yet.
+ */
+ bool used;
+
+ explicit config_param(int _line=-1)
+ :next(nullptr), line(_line), used(false) {}
+
+ gcc_nonnull_all
+ config_param(const char *_value, int _line=-1);
+
+ config_param(const config_param &) = delete;
+
+ ~config_param();
+
+ config_param &operator=(const config_param &) = delete;
+
+ /**
+ * Determine if this is a "null" instance, i.e. an empty
+ * object that was synthesized and not loaded from a
+ * configuration file.
+ */
+ bool IsNull() const {
+ return line < 0;
+ }
+};
+
+#endif
diff --git a/src/db/Configured.cxx b/src/db/Configured.cxx
index 625300d75..9ada7f34a 100644
--- a/src/db/Configured.cxx
+++ b/src/db/Configured.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,8 @@
#include "Configured.hxx"
#include "DatabaseGlue.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
+#include "config/Block.hxx"
#include "config/ConfigError.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/StandardDirectory.hxx"
@@ -32,8 +33,8 @@ Database *
CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
Error &error)
{
- const struct config_param *param = config_get_param(CONF_DATABASE);
- const struct config_param *path = config_get_param(CONF_DB_FILE);
+ const auto *param = config_get_block(ConfigBlockOption::DATABASE);
+ const auto *path = config_get_param(ConfigOption::DB_FILE);
if (param != nullptr && path != nullptr) {
error.Format(config_domain,
@@ -42,10 +43,10 @@ CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
return nullptr;
}
- struct config_param *allocated = nullptr;
+ ConfigBlock *allocated = nullptr;
if (param == nullptr && path != nullptr) {
- allocated = new config_param("database", path->line);
+ allocated = new ConfigBlock(path->line);
allocated->AddBlockParam("path", path->value.c_str(),
path->line);
param = allocated;
@@ -60,7 +61,7 @@ CreateConfiguredDatabase(EventLoop &loop, DatabaseListener &listener,
const auto db_file = AllocatedPath::Build(cache_dir, "mpd.db");
- allocated = new config_param("database");
+ allocated = new ConfigBlock();
allocated->AddBlockParam("path", db_file.c_str(), -1);
param = allocated;
}
diff --git a/src/db/Configured.hxx b/src/db/Configured.hxx
index 5d25b701c..aed2c2bf4 100644
--- a/src/db/Configured.hxx
+++ b/src/db/Configured.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Count.cxx b/src/db/Count.cxx
index e5e244a6a..3e974deca 100644
--- a/src/db/Count.cxx
+++ b/src/db/Count.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Count.hxx b/src/db/Count.hxx
index d22a3210d..d9f28cb03 100644
--- a/src/db/Count.hxx
+++ b/src/db/Count.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseError.cxx b/src/db/DatabaseError.cxx
index e0cbdd6a3..cf1993de2 100644
--- a/src/db/DatabaseError.cxx
+++ b/src/db/DatabaseError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseError.hxx b/src/db/DatabaseError.hxx
index c71bbdfff..542548c73 100644
--- a/src/db/DatabaseError.hxx
+++ b/src/db/DatabaseError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseGlue.cxx b/src/db/DatabaseGlue.cxx
index ade5c95f3..193b672e9 100644
--- a/src/db/DatabaseGlue.cxx
+++ b/src/db/DatabaseGlue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,17 +22,17 @@
#include "Registry.hxx"
#include "DatabaseError.hxx"
#include "util/Error.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "DatabasePlugin.hxx"
#include <string.h>
Database *
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
const char *plugin_name =
- param.GetBlockValue("plugin", "simple");
+ block.GetBlockValue("plugin", "simple");
const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name);
if (plugin == nullptr) {
@@ -41,5 +41,5 @@ DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
return nullptr;
}
- return plugin->create(loop, listener, param, error);
+ return plugin->create(loop, listener, block, error);
}
diff --git a/src/db/DatabaseGlue.hxx b/src/db/DatabaseGlue.hxx
index 70b50def3..67ff4f537 100644
--- a/src/db/DatabaseGlue.hxx
+++ b/src/db/DatabaseGlue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
#include "Compiler.h"
-struct config_param;
+struct ConfigBlock;
class EventLoop;
class DatabaseListener;
class Database;
@@ -35,6 +35,6 @@ class Error;
*/
Database *
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
- const config_param &param, Error &error);
+ const ConfigBlock &block, Error &error);
#endif
diff --git a/src/db/DatabaseListener.hxx b/src/db/DatabaseListener.hxx
index 8b410c2f5..5af3bff90 100644
--- a/src/db/DatabaseListener.hxx
+++ b/src/db/DatabaseListener.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseLock.cxx b/src/db/DatabaseLock.cxx
index c0b5e4844..ab4628722 100644
--- a/src/db/DatabaseLock.cxx
+++ b/src/db/DatabaseLock.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseLock.hxx b/src/db/DatabaseLock.hxx
index 9d0b0c152..786c97899 100644
--- a/src/db/DatabaseLock.hxx
+++ b/src/db/DatabaseLock.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabasePlaylist.cxx b/src/db/DatabasePlaylist.cxx
index f1cfdc874..d1e042c6a 100644
--- a/src/db/DatabasePlaylist.cxx
+++ b/src/db/DatabasePlaylist.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabasePlaylist.hxx b/src/db/DatabasePlaylist.hxx
index 9dc3526bb..333a36dc2 100644
--- a/src/db/DatabasePlaylist.hxx
+++ b/src/db/DatabasePlaylist.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabasePlugin.hxx b/src/db/DatabasePlugin.hxx
index 831101786..116aa59d2 100644
--- a/src/db/DatabasePlugin.hxx
+++ b/src/db/DatabasePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#ifndef MPD_DATABASE_PLUGIN_HXX
#define MPD_DATABASE_PLUGIN_HXX
-struct config_param;
+struct ConfigBlock;
class Error;
class EventLoop;
class DatabaseListener;
@@ -47,7 +47,7 @@ struct DatabasePlugin {
* Allocates and configures a database.
*/
Database *(*create)(EventLoop &loop, DatabaseListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
constexpr bool RequireStorage() const {
diff --git a/src/db/DatabasePrint.cxx b/src/db/DatabasePrint.cxx
index 498aedf97..33a4c65fe 100644
--- a/src/db/DatabasePrint.cxx
+++ b/src/db/DatabasePrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -147,27 +147,50 @@ PrintPlaylistFull(Client &client, bool base,
bool
db_selection_print(Client &client, const DatabaseSelection &selection,
- bool full, bool base, Error &error)
+ bool full, bool base,
+ unsigned window_start, unsigned window_end,
+ Error &error)
{
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return false;
+ unsigned i = 0;
+
using namespace std::placeholders;
const auto d = selection.filter == nullptr
? std::bind(full ? PrintDirectoryFull : PrintDirectoryBrief,
std::ref(client), base, _1)
: VisitDirectory();
- const auto s = std::bind(full ? PrintSongFull : PrintSongBrief,
- std::ref(client), base, _1);
+ VisitSong s = std::bind(full ? PrintSongFull : PrintSongBrief,
+ std::ref(client), base, _1);
const auto p = selection.filter == nullptr
? std::bind(full ? PrintPlaylistFull : PrintPlaylistBrief,
std::ref(client), base, _1, _2)
: VisitPlaylist();
+ if (window_start > 0 ||
+ window_end < (unsigned)std::numeric_limits<int>::max())
+ s = [s, window_start, window_end, &i](const LightSong &song,
+ Error &error2){
+ const bool in_window = i >= window_start && i < window_end;
+ ++i;
+ return !in_window || s(song, error2);
+ };
+
return db->Visit(selection, d, s, p, error);
}
+bool
+db_selection_print(Client &client, const DatabaseSelection &selection,
+ bool full, bool base,
+ Error &error)
+{
+ return db_selection_print(client, selection, full, base,
+ 0, std::numeric_limits<int>::max(),
+ error);
+}
+
static bool
PrintSongURIVisitor(Client &client, const LightSong &song)
{
diff --git a/src/db/DatabasePrint.hxx b/src/db/DatabasePrint.hxx
index 2ab5e703d..1c228a507 100644
--- a/src/db/DatabasePrint.hxx
+++ b/src/db/DatabasePrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -38,6 +38,12 @@ db_selection_print(Client &client, const DatabaseSelection &selection,
bool full, bool base, Error &error);
bool
+db_selection_print(Client &client, const DatabaseSelection &selection,
+ bool full, bool base,
+ unsigned window_start, unsigned window_end,
+ Error &error);
+
+bool
PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask,
const SongFilter *filter,
Error &error);
diff --git a/src/db/DatabaseQueue.cxx b/src/db/DatabaseQueue.cxx
index 490678188..c605e0878 100644
--- a/src/db/DatabaseQueue.cxx
+++ b/src/db/DatabaseQueue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseQueue.hxx b/src/db/DatabaseQueue.hxx
index e653f973c..e9ec7bde2 100644
--- a/src/db/DatabaseQueue.hxx
+++ b/src/db/DatabaseQueue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseSong.cxx b/src/db/DatabaseSong.cxx
index dd27aa8b3..d2475841b 100644
--- a/src/db/DatabaseSong.cxx
+++ b/src/db/DatabaseSong.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/DatabaseSong.hxx b/src/db/DatabaseSong.hxx
index 4daaf4047..c83f9562a 100644
--- a/src/db/DatabaseSong.hxx
+++ b/src/db/DatabaseSong.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Helpers.cxx b/src/db/Helpers.cxx
index add4bb98e..d4c29f405 100644
--- a/src/db/Helpers.cxx
+++ b/src/db/Helpers.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -46,7 +46,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
for (const auto &item : tag) {
switch (item.type) {
case TAG_ARTIST:
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
artists.emplace(item.value);
#else
artists.insert(item.value);
@@ -54,7 +54,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
break;
case TAG_ALBUM:
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
albums.emplace(item.value);
#else
albums.insert(item.value);
diff --git a/src/db/Helpers.hxx b/src/db/Helpers.hxx
index 651bac0e0..5fcab2d7f 100644
--- a/src/db/Helpers.hxx
+++ b/src/db/Helpers.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Interface.hxx b/src/db/Interface.hxx
index 152928c79..b951a9c22 100644
--- a/src/db/Interface.hxx
+++ b/src/db/Interface.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/LightDirectory.hxx b/src/db/LightDirectory.hxx
index d134151a4..ad5d34590 100644
--- a/src/db/LightDirectory.hxx
+++ b/src/db/LightDirectory.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/LightSong.cxx b/src/db/LightSong.cxx
index 5cdebc133..9202b1b30 100644
--- a/src/db/LightSong.cxx
+++ b/src/db/LightSong.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/LightSong.hxx b/src/db/LightSong.hxx
index bbd449fbe..3c289cce0 100644
--- a/src/db/LightSong.hxx
+++ b/src/db/LightSong.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/PlaylistInfo.hxx b/src/db/PlaylistInfo.hxx
index baa6cc361..f319cbcb6 100644
--- a/src/db/PlaylistInfo.hxx
+++ b/src/db/PlaylistInfo.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/PlaylistVector.cxx b/src/db/PlaylistVector.cxx
index 82a3519d9..1fffbc375 100644
--- a/src/db/PlaylistVector.cxx
+++ b/src/db/PlaylistVector.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/PlaylistVector.hxx b/src/db/PlaylistVector.hxx
index accd4fd42..7cb192dc0 100644
--- a/src/db/PlaylistVector.hxx
+++ b/src/db/PlaylistVector.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Registry.cxx b/src/db/Registry.cxx
index 5681a9b82..dc7807774 100644
--- a/src/db/Registry.cxx
+++ b/src/db/Registry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,10 +28,10 @@
const DatabasePlugin *const database_plugins[] = {
&simple_db_plugin,
-#ifdef HAVE_LIBMPDCLIENT
+#ifdef ENABLE_LIBMPDCLIENT
&proxy_db_plugin,
#endif
-#ifdef HAVE_LIBUPNP
+#ifdef ENABLE_UPNP
&upnp_db_plugin,
#endif
nullptr
diff --git a/src/db/Registry.hxx b/src/db/Registry.hxx
index 050842e21..9f672f25e 100644
--- a/src/db/Registry.hxx
+++ b/src/db/Registry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Selection.cxx b/src/db/Selection.cxx
index a886916cb..4a4016485 100644
--- a/src/db/Selection.cxx
+++ b/src/db/Selection.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Selection.hxx b/src/db/Selection.hxx
index 9802603fc..7216f5017 100644
--- a/src/db/Selection.hxx
+++ b/src/db/Selection.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Stats.hxx b/src/db/Stats.hxx
index 131a5dc47..c16dcc9c6 100644
--- a/src/db/Stats.hxx
+++ b/src/db/Stats.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/UniqueTags.cxx b/src/db/UniqueTags.cxx
index 589dc936d..4c01fdf69 100644
--- a/src/db/UniqueTags.cxx
+++ b/src/db/UniqueTags.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/UniqueTags.hxx b/src/db/UniqueTags.hxx
index 61004fc56..b44afe464 100644
--- a/src/db/UniqueTags.hxx
+++ b/src/db/UniqueTags.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Uri.hxx b/src/db/Uri.hxx
index 04960ba80..12acabe4a 100644
--- a/src/db/Uri.hxx
+++ b/src/db/Uri.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/Visitor.hxx b/src/db/Visitor.hxx
index c524f1722..1f6008117 100644
--- a/src/db/Visitor.hxx
+++ b/src/db/Visitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/LazyDatabase.cxx b/src/db/plugins/LazyDatabase.cxx
index bc52395c5..8c4901735 100644
--- a/src/db/plugins/LazyDatabase.cxx
+++ b/src/db/plugins/LazyDatabase.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/LazyDatabase.hxx b/src/db/plugins/LazyDatabase.hxx
index 38b3fdc2a..88bbcf170 100644
--- a/src/db/plugins/LazyDatabase.hxx
+++ b/src/db/plugins/LazyDatabase.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx
index 5fd224bb5..67c651e83 100644
--- a/src/db/plugins/ProxyDatabasePlugin.cxx
+++ b/src/db/plugins/ProxyDatabasePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,7 @@
#include "db/Stats.hxx"
#include "SongFilter.hxx"
#include "Compiler.h"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "tag/TagBuilder.hxx"
#include "tag/Tag.hxx"
#include "util/Error.hxx"
@@ -71,6 +71,7 @@ class ProxyDatabase final : public Database, SocketMonitor, IdleMonitor {
std::string host;
unsigned port;
+ bool keepalive;
struct mpd_connection *connection;
@@ -96,7 +97,7 @@ public:
listener(_listener) {}
static Database *Create(EventLoop &loop, DatabaseListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
virtual bool Open(Error &error) override;
@@ -128,7 +129,7 @@ public:
}
private:
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
bool Connect(Error &error);
bool CheckConnection(Error &error);
@@ -320,10 +321,10 @@ SendConstraints(mpd_connection *connection, const DatabaseSelection &selection)
Database *
ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
ProxyDatabase *db = new ProxyDatabase(loop, listener);
- if (!db->Configure(param, error)) {
+ if (!db->Configure(block, error)) {
delete db;
db = nullptr;
}
@@ -332,10 +333,11 @@ ProxyDatabase::Create(EventLoop &loop, DatabaseListener &listener,
}
bool
-ProxyDatabase::Configure(const config_param &param, gcc_unused Error &error)
+ProxyDatabase::Configure(const ConfigBlock &block, gcc_unused Error &error)
{
- host = param.GetBlockValue("host", "");
- port = param.GetBlockValue("port", 0u);
+ host = block.GetBlockValue("host", "");
+ port = block.GetBlockValue("port", 0u);
+ keepalive = block.GetBlockValue("keepalive", false);
return true;
}
@@ -376,6 +378,10 @@ ProxyDatabase::Connect(Error &error)
return false;
}
+#if LIBMPDCLIENT_CHECK_VERSION(2, 10, 0)
+ mpd_connection_set_keepalive(connection, keepalive);
+#endif
+
idle_received = unsigned(-1);
is_idle = false;
diff --git a/src/db/plugins/ProxyDatabasePlugin.hxx b/src/db/plugins/ProxyDatabasePlugin.hxx
index 699d374b5..590e5f5d2 100644
--- a/src/db/plugins/ProxyDatabasePlugin.hxx
+++ b/src/db/plugins/ProxyDatabasePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/DatabaseSave.cxx b/src/db/plugins/simple/DatabaseSave.cxx
index c766843b6..36e310bc9 100644
--- a/src/db/plugins/simple/DatabaseSave.cxx
+++ b/src/db/plugins/simple/DatabaseSave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/DatabaseSave.hxx b/src/db/plugins/simple/DatabaseSave.hxx
index bb7f57115..5a8a60a92 100644
--- a/src/db/plugins/simple/DatabaseSave.hxx
+++ b/src/db/plugins/simple/DatabaseSave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/Directory.cxx b/src/db/plugins/simple/Directory.cxx
index 218652b03..b795ee713 100644
--- a/src/db/plugins/simple/Directory.cxx
+++ b/src/db/plugins/simple/Directory.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx
index acef62143..115030a8c 100644
--- a/src/db/plugins/simple/Directory.hxx
+++ b/src/db/plugins/simple/Directory.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx
index e1650cbe8..5a7eb6da6 100644
--- a/src/db/plugins/simple/DirectorySave.cxx
+++ b/src/db/plugins/simple/DirectorySave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/DirectorySave.hxx b/src/db/plugins/simple/DirectorySave.hxx
index f464f9946..3948db02b 100644
--- a/src/db/plugins/simple/DirectorySave.hxx
+++ b/src/db/plugins/simple/DirectorySave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/Mount.cxx b/src/db/plugins/simple/Mount.cxx
index 96c7bbb5c..8898a6e9c 100644
--- a/src/db/plugins/simple/Mount.cxx
+++ b/src/db/plugins/simple/Mount.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/Mount.hxx b/src/db/plugins/simple/Mount.hxx
index a4690114c..ece644b8a 100644
--- a/src/db/plugins/simple/Mount.hxx
+++ b/src/db/plugins/simple/Mount.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/PrefixedLightSong.hxx b/src/db/plugins/simple/PrefixedLightSong.hxx
index 3664de001..16da747e3 100644
--- a/src/db/plugins/simple/PrefixedLightSong.hxx
+++ b/src/db/plugins/simple/PrefixedLightSong.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
index d6ad5e91f..da8d44fb0 100644
--- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx
+++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,14 +34,14 @@
#include "fs/io/TextFile.hxx"
#include "fs/io/BufferedOutputStream.hxx"
#include "fs/io/FileOutputStream.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "fs/FileSystem.hxx"
#include "util/CharUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
#include "fs/io/GzipOutputStream.hxx"
#endif
@@ -52,21 +52,21 @@ static constexpr Domain simple_db_domain("simple_db");
inline SimpleDatabase::SimpleDatabase()
:Database(simple_db_plugin),
path(AllocatedPath::Null()),
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
compress(true),
#endif
cache_path(AllocatedPath::Null()),
prefixed_light_song(nullptr) {}
inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path,
-#ifndef HAVE_ZLIB
+#ifndef ENABLE_ZLIB
gcc_unused
#endif
bool _compress)
:Database(simple_db_plugin),
path(std::move(_path)),
path_utf8(path.ToUTF8()),
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
compress(_compress),
#endif
cache_path(AllocatedPath::Null()),
@@ -76,10 +76,10 @@ inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path,
Database *
SimpleDatabase::Create(gcc_unused EventLoop &loop,
gcc_unused DatabaseListener &listener,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
SimpleDatabase *db = new SimpleDatabase();
- if (!db->Configure(param, error)) {
+ if (!db->Configure(block, error)) {
delete db;
db = nullptr;
}
@@ -88,9 +88,9 @@ SimpleDatabase::Create(gcc_unused EventLoop &loop,
}
bool
-SimpleDatabase::Configure(const config_param &param, Error &error)
+SimpleDatabase::Configure(const ConfigBlock &block, Error &error)
{
- path = param.GetBlockPath("path", error);
+ path = block.GetBlockPath("path", error);
if (path.IsNull()) {
if (!error.IsDefined())
error.Set(simple_db_domain,
@@ -100,12 +100,12 @@ SimpleDatabase::Configure(const config_param &param, Error &error)
path_utf8 = path.ToUTF8();
- cache_path = param.GetBlockPath("cache_directory", error);
+ cache_path = block.GetBlockPath("cache_directory", error);
if (path.IsNull() && error.IsDefined())
return false;
-#ifdef HAVE_ZLIB
- compress = param.GetBlockValue("compress", compress);
+#ifdef ENABLE_ZLIB
+ compress = block.GetBlockValue("compress", compress);
#endif
return true;
@@ -389,7 +389,7 @@ SimpleDatabase::Save(Error &error)
OutputStream *os = &fos;
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
GzipOutputStream *gzip = nullptr;
if (compress) {
gzip = new GzipOutputStream(*os, error);
@@ -407,13 +407,13 @@ SimpleDatabase::Save(Error &error)
db_save_internal(bos, *root);
if (!bos.Flush(error)) {
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
delete gzip;
#endif
return false;
}
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
if (gzip != nullptr) {
bool success = gzip->Flush(error);
delete gzip;
@@ -487,7 +487,7 @@ SimpleDatabase::Mount(const char *local_uri, const char *storage_uri,
std::string name(storage_uri);
std::replace_if(name.begin(), name.end(), IsUnsafeChar, '_');
-#ifndef HAVE_ZLIB
+#ifndef ENABLE_ZLIB
constexpr bool compress = false;
#endif
auto db = new SimpleDatabase(AllocatedPath::Build(cache_path,
diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.hxx b/src/db/plugins/simple/SimpleDatabasePlugin.hxx
index d82225f8c..fc720ecf8 100644
--- a/src/db/plugins/simple/SimpleDatabasePlugin.hxx
+++ b/src/db/plugins/simple/SimpleDatabasePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include <cassert>
-struct config_param;
+struct ConfigBlock;
struct Directory;
struct DatabasePlugin;
class EventLoop;
@@ -39,7 +39,7 @@ class SimpleDatabase : public Database {
AllocatedPath path;
std::string path_utf8;
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
bool compress;
#endif
@@ -73,7 +73,7 @@ class SimpleDatabase : public Database {
public:
static Database *Create(EventLoop &loop, DatabaseListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
gcc_pure
@@ -134,7 +134,7 @@ public:
}
private:
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
gcc_pure
bool Check(Error &error) const;
diff --git a/src/db/plugins/simple/Song.cxx b/src/db/plugins/simple/Song.cxx
index fbfc2ec19..b2515a2d5 100644
--- a/src/db/plugins/simple/Song.cxx
+++ b/src/db/plugins/simple/Song.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/Song.hxx b/src/db/plugins/simple/Song.hxx
index 9f3a4a3ef..192583681 100644
--- a/src/db/plugins/simple/Song.hxx
+++ b/src/db/plugins/simple/Song.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/SongSort.cxx b/src/db/plugins/simple/SongSort.cxx
index 4b7144937..70299a2d4 100644
--- a/src/db/plugins/simple/SongSort.cxx
+++ b/src/db/plugins/simple/SongSort.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/simple/SongSort.hxx b/src/db/plugins/simple/SongSort.hxx
index 2a0c4383b..0a75c9fda 100644
--- a/src/db/plugins/simple/SongSort.hxx
+++ b/src/db/plugins/simple/SongSort.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/ContentDirectoryService.cxx b/src/db/plugins/upnp/ContentDirectoryService.cxx
index 88d4bd644..d98559c7b 100644
--- a/src/db/plugins/upnp/ContentDirectoryService.cxx
+++ b/src/db/plugins/upnp/ContentDirectoryService.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/Directory.cxx b/src/db/plugins/upnp/Directory.cxx
index e94a1a997..894a53c6a 100644
--- a/src/db/plugins/upnp/Directory.cxx
+++ b/src/db/plugins/upnp/Directory.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -89,18 +89,18 @@ ParseDuration(const char *duration)
* this. Twonky returns directory names (titles) like 'Artist/Album'.
*/
gcc_pure
-static std::string
-titleToPathElt(std::string &&s)
+static std::string &&
+TitleToPathSegment(std::string &&s)
{
std::replace(s.begin(), s.end(), '/', '_');
- return s;
+ return std::move(s);
}
/**
* An XML parser which builds directory contents from DIDL lite input.
*/
class UPnPDirParser final : public CommonExpatParser {
- UPnPDirContent &m_dir;
+ UPnPDirContent &directory;
enum {
NONE,
@@ -120,22 +120,22 @@ class UPnPDirParser final : public CommonExpatParser {
*/
std::string value;
- UPnPDirObject m_tobj;
+ UPnPDirObject object;
TagBuilder tag;
public:
- UPnPDirParser(UPnPDirContent& dir)
- :m_dir(dir),
+ UPnPDirParser(UPnPDirContent &_directory)
+ :directory(_directory),
state(NONE),
tag_type(TAG_NUM_OF_ITEM_TYPES)
{
- m_tobj.clear();
+ object.Clear();
}
protected:
virtual void StartElement(const XML_Char *name, const XML_Char **attrs)
{
- if (m_tobj.type != UPnPDirObject::Type::UNKNOWN &&
+ if (object.type != UPnPDirObject::Type::UNKNOWN &&
tag_type == TAG_NUM_OF_ITEM_TYPES) {
tag_type = tag_table_lookup(upnp_tags, name);
if (tag_type != TAG_NUM_OF_ITEM_TYPES)
@@ -147,31 +147,31 @@ protected:
switch (name[0]) {
case 'c':
if (!strcmp(name, "container")) {
- m_tobj.clear();
- m_tobj.type = UPnPDirObject::Type::CONTAINER;
+ object.Clear();
+ object.type = UPnPDirObject::Type::CONTAINER;
const char *id = GetAttribute(attrs, "id");
if (id != nullptr)
- m_tobj.m_id = id;
+ object.id = id;
const char *pid = GetAttribute(attrs, "parentID");
if (pid != nullptr)
- m_tobj.m_pid = pid;
+ object.parent_id = pid;
}
break;
case 'i':
if (!strcmp(name, "item")) {
- m_tobj.clear();
- m_tobj.type = UPnPDirObject::Type::ITEM;
+ object.Clear();
+ object.type = UPnPDirObject::Type::ITEM;
const char *id = GetAttribute(attrs, "id");
if (id != nullptr)
- m_tobj.m_id = id;
+ object.id = id;
const char *pid = GetAttribute(attrs, "parentID");
if (pid != nullptr)
- m_tobj.m_pid = pid;
+ object.parent_id = pid;
}
break;
@@ -197,25 +197,15 @@ protected:
}
}
- bool checkobjok() {
- if (m_tobj.m_id.empty() || m_tobj.m_pid.empty() ||
- m_tobj.name.empty() ||
- (m_tobj.type == UPnPDirObject::Type::ITEM &&
- m_tobj.item_class == UPnPDirObject::ItemClass::UNKNOWN))
- return false;
-
- return true;
- }
-
virtual void EndElement(const XML_Char *name)
{
if (tag_type != TAG_NUM_OF_ITEM_TYPES) {
- assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN);
+ assert(object.type != UPnPDirObject::Type::UNKNOWN);
tag.AddItem(tag_type, value.c_str());
if (tag_type == TAG_TITLE)
- m_tobj.name = titleToPathElt(std::move(value));
+ object.name = TitleToPathSegment(std::move(value));
value.clear();
tag_type = TAG_NUM_OF_ITEM_TYPES;
@@ -223,9 +213,9 @@ protected:
}
if ((!strcmp(name, "container") || !strcmp(name, "item")) &&
- checkobjok()) {
- tag.Commit(m_tobj.tag);
- m_dir.objects.emplace_back(std::move(m_tobj));
+ object.Check()) {
+ tag.Commit(object.tag);
+ directory.objects.emplace_back(std::move(object));
}
state = NONE;
@@ -234,7 +224,7 @@ protected:
virtual void CharacterData(const XML_Char *s, int len)
{
if (tag_type != TAG_NUM_OF_ITEM_TYPES) {
- assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN);
+ assert(object.type != UPnPDirObject::Type::UNKNOWN);
value.append(s, len);
return;
@@ -245,11 +235,11 @@ protected:
break;
case RES:
- m_tobj.url.assign(s, len);
+ object.url.assign(s, len);
break;
case CLASS:
- m_tobj.item_class = ParseItemClass(s, len);
+ object.item_class = ParseItemClass(s, len);
break;
}
}
diff --git a/src/db/plugins/upnp/Directory.hxx b/src/db/plugins/upnp/Directory.hxx
index 433979900..639f2bcbe 100644
--- a/src/db/plugins/upnp/Directory.hxx
+++ b/src/db/plugins/upnp/Directory.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/Object.cxx b/src/db/plugins/upnp/Object.cxx
index 703fb0be4..0b5c4be88 100644
--- a/src/db/plugins/upnp/Object.cxx
+++ b/src/db/plugins/upnp/Object.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/Object.hxx b/src/db/plugins/upnp/Object.hxx
index 16a66c774..aced04b27 100644
--- a/src/db/plugins/upnp/Object.hxx
+++ b/src/db/plugins/upnp/Object.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#define MPD_UPNP_OBJECT_HXX
#include "tag/Tag.hxx"
+#include "Compiler.h"
#include <string>
@@ -50,8 +51,16 @@ public:
PLAYLIST,
};
- std::string m_id; // ObjectId
- std::string m_pid; // Parent ObjectId
+ /**
+ * ObjectId
+ */
+ std::string id;
+
+ /**
+ * Parent's ObjectId
+ */
+ std::string parent_id;
+
std::string url;
/**
@@ -71,15 +80,21 @@ public:
UPnPDirObject &operator=(UPnPDirObject &&) = default;
- void clear()
- {
- m_id.clear();
- m_pid.clear();
+ void Clear() {
+ id.clear();
+ parent_id.clear();
url.clear();
type = Type::UNKNOWN;
item_class = ItemClass::UNKNOWN;
tag.Clear();
}
+
+ gcc_pure
+ bool Check() const {
+ return !id.empty() && !parent_id.empty() && !name.empty() &&
+ (type != UPnPDirObject::Type::ITEM ||
+ item_class != UPnPDirObject::ItemClass::UNKNOWN);
+ }
};
#endif /* _UPNPDIRCONTENT_H_X_INCLUDED_ */
diff --git a/src/db/plugins/upnp/Tags.cxx b/src/db/plugins/upnp/Tags.cxx
index fd65df4d0..89d1b53c5 100644
--- a/src/db/plugins/upnp/Tags.cxx
+++ b/src/db/plugins/upnp/Tags.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/Tags.hxx b/src/db/plugins/upnp/Tags.hxx
index ec6d18478..8f85ce4b0 100644
--- a/src/db/plugins/upnp/Tags.hxx
+++ b/src/db/plugins/upnp/Tags.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
index 9970cdcf3..9f0841780 100644
--- a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
+++ b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
#include "db/LightDirectory.hxx"
#include "db/LightSong.hxx"
#include "db/Stats.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "tag/TagBuilder.hxx"
#include "tag/TagTable.hxx"
#include "util/Error.hxx"
@@ -78,7 +78,7 @@ public:
UpnpDatabase():Database(upnp_db_plugin) {}
static Database *Create(EventLoop &loop, DatabaseListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
virtual bool Open(Error &error) override;
@@ -106,7 +106,7 @@ public:
}
protected:
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
private:
bool VisitServer(const ContentDirectoryService &server,
@@ -158,10 +158,10 @@ private:
Database *
UpnpDatabase::Create(gcc_unused EventLoop &loop,
gcc_unused DatabaseListener &listener,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
UpnpDatabase *db = new UpnpDatabase();
- if (!db->Configure(param, error)) {
+ if (!db->Configure(block, error)) {
delete db;
return nullptr;
}
@@ -173,7 +173,7 @@ UpnpDatabase::Create(gcc_unused EventLoop &loop,
}
inline bool
-UpnpDatabase::Configure(const config_param &, Error &)
+UpnpDatabase::Configure(const ConfigBlock &, Error &)
{
return true;
}
@@ -414,7 +414,7 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
// So we return synthetic and ugly paths based on the object id,
// which we later have to detect.
const std::string path = songPath(server.getFriendlyName(),
- dirent.m_id);
+ dirent.id);
if (!visitSong(std::move(dirent), path.c_str(),
selection, visit_song,
error))
@@ -449,13 +449,13 @@ UpnpDatabase::BuildPath(const ContentDirectoryService &server,
std::string &path,
Error &error) const
{
- const char *pid = idirent.m_id.c_str();
+ const char *pid = idirent.id.c_str();
path.clear();
UPnPDirObject dirent;
while (strcmp(pid, rootid) != 0) {
if (!ReadNode(server, pid, dirent, error))
return false;
- pid = dirent.m_pid.c_str();
+ pid = dirent.parent_id.c_str();
if (path.empty())
path = dirent.name;
@@ -511,7 +511,7 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
return false;
}
- objid = std::move(child->m_id);
+ objid = std::move(child->id);
}
}
@@ -623,7 +623,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
}
std::string path = songPath(server.getFriendlyName(),
- dirent.m_id);
+ dirent.id);
if (!visitSong(std::move(dirent), path.c_str(),
selection,
visit_song, error))
@@ -642,7 +642,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
recursion (1-deep) here, which will handle the "add dir"
case. */
if (selection.recursive && selection.filter)
- return SearchSongs(server, tdirent.m_id.c_str(), selection,
+ return SearchSongs(server, tdirent.id.c_str(), selection,
visit_song, error);
const char *const base_uri = selection.uri.empty()
@@ -660,7 +660,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
and loop here, but it's not useful as mpd will only return
data to the client when we're done anyway. */
UPnPDirContent dirbuf;
- if (!server.readDir(handle, tdirent.m_id.c_str(), dirbuf,
+ if (!server.readDir(handle, tdirent.id.c_str(), dirbuf,
error))
return false;
@@ -749,7 +749,7 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
const char *value = dirent.tag.GetValue(tag);
if (value != nullptr) {
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
values.emplace(value);
#else
values.insert(value);
diff --git a/src/db/plugins/upnp/UpnpDatabasePlugin.hxx b/src/db/plugins/upnp/UpnpDatabasePlugin.hxx
index 0228405cd..f03cde75d 100644
--- a/src/db/plugins/upnp/UpnpDatabasePlugin.hxx
+++ b/src/db/plugins/upnp/UpnpDatabasePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Archive.cxx b/src/db/update/Archive.cxx
index fc8f1fcbf..6119f3233 100644
--- a/src/db/update/Archive.cxx
+++ b/src/db/update/Archive.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Container.cxx b/src/db/update/Container.cxx
index 1c420fa99..b51a80431 100644
--- a/src/db/update/Container.cxx
+++ b/src/db/update/Container.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Editor.cxx b/src/db/update/Editor.cxx
index 4136ccdad..2ca17f8cb 100644
--- a/src/db/update/Editor.cxx
+++ b/src/db/update/Editor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Editor.hxx b/src/db/update/Editor.hxx
index 58e23ed7a..cefb6c07f 100644
--- a/src/db/update/Editor.hxx
+++ b/src/db/update/Editor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx
index cf92ac8f7..b432bdce8 100644
--- a/src/db/update/ExcludeList.cxx
+++ b/src/db/update/ExcludeList.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/ExcludeList.hxx b/src/db/update/ExcludeList.hxx
index ef6c4d53e..ae196a7b2 100644
--- a/src/db/update/ExcludeList.hxx
+++ b/src/db/update/ExcludeList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifyDomain.cxx b/src/db/update/InotifyDomain.cxx
index 4a3ab2d79..18557a5ce 100644
--- a/src/db/update/InotifyDomain.cxx
+++ b/src/db/update/InotifyDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifyDomain.hxx b/src/db/update/InotifyDomain.hxx
index ad6202361..219ee7e4f 100644
--- a/src/db/update/InotifyDomain.hxx
+++ b/src/db/update/InotifyDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifyQueue.cxx b/src/db/update/InotifyQueue.cxx
index 013200f98..4b5269427 100644
--- a/src/db/update/InotifyQueue.cxx
+++ b/src/db/update/InotifyQueue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifyQueue.hxx b/src/db/update/InotifyQueue.hxx
index a9abc2969..dab7c7e8c 100644
--- a/src/db/update/InotifyQueue.hxx
+++ b/src/db/update/InotifyQueue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifySource.cxx b/src/db/update/InotifySource.cxx
index 233504ad6..d0ac5b779 100644
--- a/src/db/update/InotifySource.cxx
+++ b/src/db/update/InotifySource.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifySource.hxx b/src/db/update/InotifySource.hxx
index 2557680a0..0eb69719b 100644
--- a/src/db/update/InotifySource.hxx
+++ b/src/db/update/InotifySource.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,8 +41,8 @@ public:
}
/**
- * Creates a new inotify source and registers it in the GLib main
- * loop.
+ * Creates a new inotify source and registers it in the
+ * #EventLoop.
*
* @param a callback invoked for events received from the kernel
*/
diff --git a/src/db/update/InotifyUpdate.cxx b/src/db/update/InotifyUpdate.cxx
index 26bdddf8d..42423e07e 100644
--- a/src/db/update/InotifyUpdate.cxx
+++ b/src/db/update/InotifyUpdate.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/InotifyUpdate.hxx b/src/db/update/InotifyUpdate.hxx
index 0f78db71f..7d56240ac 100644
--- a/src/db/update/InotifyUpdate.hxx
+++ b/src/db/update/InotifyUpdate.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Queue.cxx b/src/db/update/Queue.cxx
index 6d6d80131..870207fc6 100644
--- a/src/db/update/Queue.cxx
+++ b/src/db/update/Queue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Queue.hxx b/src/db/update/Queue.hxx
index 9064ea481..6c0a5733d 100644
--- a/src/db/update/Queue.hxx
+++ b/src/db/update/Queue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Remove.cxx b/src/db/update/Remove.cxx
index dfada05b2..0f1cbde1c 100644
--- a/src/db/update/Remove.cxx
+++ b/src/db/update/Remove.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Remove.hxx b/src/db/update/Remove.hxx
index ce6d77d47..5ebfb884b 100644
--- a/src/db/update/Remove.hxx
+++ b/src/db/update/Remove.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Service.cxx b/src/db/update/Service.cxx
index e8a1f6b02..e14dbdc6c 100644
--- a/src/db/update/Service.cxx
+++ b/src/db/update/Service.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Service.hxx b/src/db/update/Service.hxx
index feaeaebc5..7dd198a7f 100644
--- a/src/db/update/Service.hxx
+++ b/src/db/update/Service.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/UpdateDomain.cxx b/src/db/update/UpdateDomain.cxx
index 80ad4fd22..68fcbe81c 100644
--- a/src/db/update/UpdateDomain.cxx
+++ b/src/db/update/UpdateDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/UpdateDomain.hxx b/src/db/update/UpdateDomain.hxx
index a6e994390..8669d24b4 100644
--- a/src/db/update/UpdateDomain.hxx
+++ b/src/db/update/UpdateDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/UpdateIO.cxx b/src/db/update/UpdateIO.cxx
index 9e43d1289..0fd46f1db 100644
--- a/src/db/update/UpdateIO.cxx
+++ b/src/db/update/UpdateIO.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/UpdateIO.hxx b/src/db/update/UpdateIO.hxx
index 2dbb4ae83..cf6cdd37d 100644
--- a/src/db/update/UpdateIO.hxx
+++ b/src/db/update/UpdateIO.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/UpdateSong.cxx b/src/db/update/UpdateSong.cxx
index 005bf8992..61c4db0d1 100644
--- a/src/db/update/UpdateSong.cxx
+++ b/src/db/update/UpdateSong.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index f71faa86d..6442e6d23 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -57,11 +57,11 @@ UpdateWalk::UpdateWalk(EventLoop &_loop, DatabaseListener &_listener,
{
#ifndef WIN32
follow_inside_symlinks =
- config_get_bool(CONF_FOLLOW_INSIDE_SYMLINKS,
+ config_get_bool(ConfigOption::FOLLOW_INSIDE_SYMLINKS,
DEFAULT_FOLLOW_INSIDE_SYMLINKS);
follow_outside_symlinks =
- config_get_bool(CONF_FOLLOW_OUTSIDE_SYMLINKS,
+ config_get_bool(ConfigOption::FOLLOW_OUTSIDE_SYMLINKS,
DEFAULT_FOLLOW_OUTSIDE_SYMLINKS);
#endif
}
diff --git a/src/db/update/Walk.hxx b/src/db/update/Walk.hxx
index a4c518813..94db4dbee 100644
--- a/src/db/update/Walk.hxx
+++ b/src/db/update/Walk.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx
index 4794d60e7..eb6bb1109 100644
--- a/src/decoder/DecoderAPI.cxx
+++ b/src/decoder/DecoderAPI.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderAPI.hxx b/src/decoder/DecoderAPI.hxx
index b756331d9..cb53f4ec5 100644
--- a/src/decoder/DecoderAPI.hxx
+++ b/src/decoder/DecoderAPI.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
#include "tag/Tag.hxx"
#include "AudioFormat.hxx"
#include "MixRampInfo.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "Chrono.hxx"
// IWYU pragma: end_exports
diff --git a/src/decoder/DecoderBuffer.cxx b/src/decoder/DecoderBuffer.cxx
index a8958d6fd..47c18cdd1 100644
--- a/src/decoder/DecoderBuffer.cxx
+++ b/src/decoder/DecoderBuffer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderBuffer.hxx b/src/decoder/DecoderBuffer.hxx
index 9cf47d915..bc7138d5b 100644
--- a/src/decoder/DecoderBuffer.hxx
+++ b/src/decoder/DecoderBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderCommand.hxx b/src/decoder/DecoderCommand.hxx
index a00519644..88eac0181 100644
--- a/src/decoder/DecoderCommand.hxx
+++ b/src/decoder/DecoderCommand.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderControl.cxx b/src/decoder/DecoderControl.cxx
index c30da6214..a4fe570b2 100644
--- a/src/decoder/DecoderControl.cxx
+++ b/src/decoder/DecoderControl.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderControl.hxx b/src/decoder/DecoderControl.hxx
index ed2b8c538..a8e675bba 100644
--- a/src/decoder/DecoderControl.hxx
+++ b/src/decoder/DecoderControl.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderError.cxx b/src/decoder/DecoderError.cxx
index bd3842837..d82a4d58c 100644
--- a/src/decoder/DecoderError.cxx
+++ b/src/decoder/DecoderError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderError.hxx b/src/decoder/DecoderError.hxx
index 83cf98204..58aa6cb83 100644
--- a/src/decoder/DecoderError.hxx
+++ b/src/decoder/DecoderError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderInternal.cxx b/src/decoder/DecoderInternal.cxx
index f35878682..f0bb04125 100644
--- a/src/decoder/DecoderInternal.cxx
+++ b/src/decoder/DecoderInternal.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderInternal.hxx b/src/decoder/DecoderInternal.hxx
index 24b665e85..f33c80402 100644
--- a/src/decoder/DecoderInternal.hxx
+++ b/src/decoder/DecoderInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderList.cxx b/src/decoder/DecoderList.cxx
index cd6881ce2..e153b1398 100644
--- a/src/decoder/DecoderList.cxx
+++ b/src/decoder/DecoderList.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
#include "DecoderList.hxx"
#include "DecoderPlugin.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "plugins/AudiofileDecoderPlugin.hxx"
#include "plugins/PcmDecoderPlugin.hxx"
#include "plugins/DsdiffDecoderPlugin.hxx"
@@ -48,44 +48,42 @@
#include <string.h>
const struct DecoderPlugin *const decoder_plugins[] = {
-#ifdef HAVE_MAD
+#ifdef ENABLE_MAD
&mad_decoder_plugin,
#endif
-#ifdef HAVE_MPG123
+#ifdef ENABLE_MPG123
&mpg123_decoder_plugin,
#endif
#ifdef ENABLE_VORBIS_DECODER
&vorbis_decoder_plugin,
#endif
-#if defined(HAVE_FLAC)
+#ifdef ENABLE_FLAC
&oggflac_decoder_plugin,
-#endif
-#ifdef HAVE_FLAC
&flac_decoder_plugin,
#endif
-#ifdef HAVE_OPUS
+#ifdef ENABLE_OPUS
&opus_decoder_plugin,
#endif
#ifdef ENABLE_SNDFILE
&sndfile_decoder_plugin,
#endif
-#ifdef HAVE_AUDIOFILE
+#ifdef ENABLE_AUDIOFILE
&audiofile_decoder_plugin,
#endif
#ifdef ENABLE_DSD
&dsdiff_decoder_plugin,
&dsf_decoder_plugin,
#endif
-#ifdef HAVE_FAAD
+#ifdef ENABLE_FAAD
&faad_decoder_plugin,
#endif
-#ifdef HAVE_MPCDEC
+#ifdef ENABLE_MPCDEC
&mpcdec_decoder_plugin,
#endif
-#ifdef HAVE_WAVPACK
+#ifdef ENABLE_WAVPACK
&wavpack_decoder_plugin,
#endif
-#ifdef HAVE_MODPLUG
+#ifdef ENABLE_MODPLUG
&modplug_decoder_plugin,
#endif
#ifdef ENABLE_MIKMOD_DECODER
@@ -100,13 +98,13 @@ const struct DecoderPlugin *const decoder_plugins[] = {
#ifdef ENABLE_FLUIDSYNTH
&fluidsynth_decoder_plugin,
#endif
-#ifdef HAVE_ADPLUG
+#ifdef ENABLE_ADPLUG
&adplug_decoder_plugin,
#endif
-#ifdef HAVE_FFMPEG
+#ifdef ENABLE_FFMPEG
&ffmpeg_decoder_plugin,
#endif
-#ifdef HAVE_GME
+#ifdef ENABLE_GME
&gme_decoder_plugin,
#endif
&pcm_decoder_plugin,
@@ -129,12 +127,13 @@ decoder_plugin_from_name(const char *name)
void decoder_plugin_init_all(void)
{
- struct config_param empty;
+ ConfigBlock empty;
for (unsigned i = 0; decoder_plugins[i] != nullptr; ++i) {
const DecoderPlugin &plugin = *decoder_plugins[i];
- const struct config_param *param =
- config_find_block(CONF_DECODER, "plugin", plugin.name);
+ const auto *param =
+ config_find_block(ConfigBlockOption::DECODER, "plugin",
+ plugin.name);
if (param == nullptr)
param = &empty;
diff --git a/src/decoder/DecoderList.hxx b/src/decoder/DecoderList.hxx
index 47085d4ae..f44d96c67 100644
--- a/src/decoder/DecoderList.hxx
+++ b/src/decoder/DecoderList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderPlugin.cxx b/src/decoder/DecoderPlugin.cxx
index a0722c348..60b1c36d4 100644
--- a/src/decoder/DecoderPlugin.cxx
+++ b/src/decoder/DecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx
index dbf3db9aa..ef275266c 100644
--- a/src/decoder/DecoderPlugin.hxx
+++ b/src/decoder/DecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
#include "Compiler.h"
-struct config_param;
+struct ConfigBlock;
class InputStream;
struct tag_handler;
class Path;
@@ -44,7 +44,7 @@ struct DecoderPlugin {
* @return true if the plugin was initialized successfully,
* false if the plugin is not available
*/
- bool (*init)(const config_param &param);
+ bool (*init)(const ConfigBlock &block);
/**
* Deinitialize a decoder plugin which was initialized
@@ -112,9 +112,9 @@ struct DecoderPlugin {
* @return true if the plugin was initialized successfully, false if
* the plugin is not available
*/
- bool Init(const config_param &param) const {
+ bool Init(const ConfigBlock &block) const {
return init != nullptr
- ? init(param)
+ ? init(block)
: true;
}
diff --git a/src/decoder/DecoderPrint.cxx b/src/decoder/DecoderPrint.cxx
index 54b89c36c..fe7206410 100644
--- a/src/decoder/DecoderPrint.cxx
+++ b/src/decoder/DecoderPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderPrint.hxx b/src/decoder/DecoderPrint.hxx
index 695bd099d..f8dd03c08 100644
--- a/src/decoder/DecoderPrint.hxx
+++ b/src/decoder/DecoderPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx
index dd5518b98..6ac7e459f 100644
--- a/src/decoder/DecoderThread.cxx
+++ b/src/decoder/DecoderThread.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/DecoderThread.hxx b/src/decoder/DecoderThread.hxx
index d5fde281c..c262a679b 100644
--- a/src/decoder/DecoderThread.hxx
+++ b/src/decoder/DecoderThread.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/AdPlugDecoderPlugin.cxx b/src/decoder/plugins/AdPlugDecoderPlugin.cxx
index 9cc37ade4..dd3f2b7ff 100644
--- a/src/decoder/plugins/AdPlugDecoderPlugin.cxx
+++ b/src/decoder/plugins/AdPlugDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -38,14 +38,14 @@ static constexpr Domain adplug_domain("adplug");
static unsigned sample_rate;
static bool
-adplug_init(const config_param &param)
+adplug_init(const ConfigBlock &block)
{
FormatDebug(adplug_domain, "adplug %s",
CAdPlug::get_version().c_str());
Error error;
- sample_rate = param.GetBlockValue("sample_rate", 48000u);
+ sample_rate = block.GetBlockValue("sample_rate", 48000u);
if (!audio_check_sample_rate(sample_rate, error)) {
LogError(error);
return false;
diff --git a/src/decoder/plugins/AdPlugDecoderPlugin.h b/src/decoder/plugins/AdPlugDecoderPlugin.h
index 539dbbf0a..16d9e507b 100644
--- a/src/decoder/plugins/AdPlugDecoderPlugin.h
+++ b/src/decoder/plugins/AdPlugDecoderPlugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/AudiofileDecoderPlugin.cxx b/src/decoder/plugins/AudiofileDecoderPlugin.cxx
index a0ef71e49..7d59d9460 100644
--- a/src/decoder/plugins/AudiofileDecoderPlugin.cxx
+++ b/src/decoder/plugins/AudiofileDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -43,7 +43,7 @@ audiofile_error_func(long, const char *msg)
}
static bool
-audiofile_init(const config_param &)
+audiofile_init(const ConfigBlock &)
{
afSetErrorHandler(audiofile_error_func);
return true;
diff --git a/src/decoder/plugins/AudiofileDecoderPlugin.hxx b/src/decoder/plugins/AudiofileDecoderPlugin.hxx
index 61129076d..dfeda0f7d 100644
--- a/src/decoder/plugins/AudiofileDecoderPlugin.hxx
+++ b/src/decoder/plugins/AudiofileDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/DsdLib.cxx b/src/decoder/plugins/DsdLib.cxx
index 7321261f6..c5df5beec 100644
--- a/src/decoder/plugins/DsdLib.cxx
+++ b/src/decoder/plugins/DsdLib.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
#include <id3tag.h>
#endif
@@ -103,7 +103,7 @@ dsdlib_valid_freq(uint32_t samplefreq)
}
}
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
void
dsdlib_tag_id3(InputStream &is,
const struct tag_handler *handler,
diff --git a/src/decoder/plugins/DsdLib.hxx b/src/decoder/plugins/DsdLib.hxx
index 8295bcbf6..4aa4b4af1 100644
--- a/src/decoder/plugins/DsdLib.hxx
+++ b/src/decoder/plugins/DsdLib.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/DsdiffDecoderPlugin.cxx b/src/decoder/plugins/DsdiffDecoderPlugin.cxx
index b6c79e11e..bd587e0ce 100644
--- a/src/decoder/plugins/DsdiffDecoderPlugin.cxx
+++ b/src/decoder/plugins/DsdiffDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -72,9 +72,9 @@ struct DsdiffMetaData {
static bool lsbitfirst;
static bool
-dsdiff_init(const config_param &param)
+dsdiff_init(const ConfigBlock &block)
{
- lsbitfirst = param.GetBlockValue("lsbitfirst", false);
+ lsbitfirst = block.GetBlockValue("lsbitfirst", false);
return true;
}
@@ -244,7 +244,7 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
/** offset for title tag */
offset_type title_offset = 0;
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
offset_type id3_offset = 0;
#endif
@@ -269,7 +269,7 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
chunk_size = chunk_header->GetSize();
title_offset = is.GetOffset();
}
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
/* 'ID3 ' chunk, offspec. Used by sacdextract */
if (chunk_header->id.Equals("ID3 ")) {
chunk_size = chunk_header->GetSize();
@@ -283,7 +283,7 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
/* done processing chunk headers, process tags if any */
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
if (id3_offset != 0) {
/* a ID3 tag has preference over the other tags, do not process
other tags if we have one */
diff --git a/src/decoder/plugins/DsdiffDecoderPlugin.hxx b/src/decoder/plugins/DsdiffDecoderPlugin.hxx
index 7aa36752b..503e99756 100644
--- a/src/decoder/plugins/DsdiffDecoderPlugin.hxx
+++ b/src/decoder/plugins/DsdiffDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/DsfDecoderPlugin.cxx b/src/decoder/plugins/DsfDecoderPlugin.cxx
index 690616d15..b111dbd51 100644
--- a/src/decoder/plugins/DsfDecoderPlugin.cxx
+++ b/src/decoder/plugins/DsfDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -47,7 +47,7 @@ struct DsfMetaData {
unsigned sample_rate, channels;
bool bitreverse;
offset_type n_blocks;
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
offset_type id3_offset;
#endif
};
@@ -111,7 +111,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
if (sizeof(dsf_header) != chunk_size)
return false;
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
const offset_type metadata_offset = dsf_header.pmeta.Read();
#endif
@@ -174,7 +174,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
metadata->n_blocks = data_size / block_size;
metadata->channels = channels;
metadata->sample_rate = samplefreq;
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
metadata->id3_offset = metadata_offset;
#endif
/* check bits per sample format, determine if bitreverse is needed */
@@ -352,7 +352,7 @@ dsf_scan_stream(InputStream &is,
audio_format.sample_rate);
tag_handler_invoke_duration(handler, handler_ctx, songtime);
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
/* Add available tags from the ID3 tag */
dsdlib_tag_id3(is, handler, handler_ctx, metadata.id3_offset);
#endif
diff --git a/src/decoder/plugins/DsfDecoderPlugin.hxx b/src/decoder/plugins/DsfDecoderPlugin.hxx
index 02bea0b5c..5da6217e9 100644
--- a/src/decoder/plugins/DsfDecoderPlugin.hxx
+++ b/src/decoder/plugins/DsfDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FaadDecoderPlugin.cxx b/src/decoder/plugins/FaadDecoderPlugin.cxx
index add23aaa4..8ea2b685c 100644
--- a/src/decoder/plugins/FaadDecoderPlugin.cxx
+++ b/src/decoder/plugins/FaadDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FaadDecoderPlugin.hxx b/src/decoder/plugins/FaadDecoderPlugin.hxx
index 968433e9b..3c42b4226 100644
--- a/src/decoder/plugins/FaadDecoderPlugin.hxx
+++ b/src/decoder/plugins/FaadDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index 722f954e2..faff70c66 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,14 +20,24 @@
/* necessary because libavutil/common.h uses UINT64_C */
#define __STDC_CONSTANT_MACROS
+#include "lib/ffmpeg/Time.hxx"
#include "config.h"
#include "FfmpegDecoderPlugin.hxx"
#include "lib/ffmpeg/Domain.hxx"
+#include "lib/ffmpeg/Error.hxx"
+#include "lib/ffmpeg/LogError.hxx"
+#include "lib/ffmpeg/Init.hxx"
+#include "lib/ffmpeg/Buffer.hxx"
#include "../DecoderAPI.hxx"
#include "FfmpegMetaData.hxx"
+#include "FfmpegIo.hxx"
+#include "tag/TagBuilder.hxx"
#include "tag/TagHandler.hxx"
+#include "tag/ReplayGain.hxx"
+#include "tag/MixRamp.hxx"
#include "input/InputStream.hxx"
#include "CheckAudioFormat.hxx"
+#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "LogV.hxx"
@@ -38,7 +48,6 @@ extern "C" {
#include <libavformat/avio.h>
#include <libavutil/avutil.h>
#include <libavutil/log.h>
-#include <libavutil/mathematics.h>
#if LIBAVUTIL_VERSION_MAJOR >= 53
#include <libavutil/frame.h>
@@ -48,205 +57,50 @@ extern "C" {
#include <assert.h>
#include <string.h>
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
-static LogLevel
-import_ffmpeg_level(int level)
-{
- if (level <= AV_LOG_FATAL)
- return LogLevel::ERROR;
-
- if (level <= AV_LOG_WARNING)
- return LogLevel::WARNING;
-
- if (level <= AV_LOG_INFO)
- return LogLevel::INFO;
-
- return LogLevel::DEBUG;
-}
-
-static void
-mpd_ffmpeg_log_callback(gcc_unused void *ptr, int level,
- const char *fmt, va_list vl)
-{
- const AVClass * cls = nullptr;
-
- if (ptr != nullptr)
- cls = *(const AVClass *const*)ptr;
-
- if (cls != nullptr) {
- char domain[64];
- snprintf(domain, sizeof(domain), "%s/%s",
- ffmpeg_domain.GetName(), cls->item_name(ptr));
- const Domain d(domain);
- LogFormatV(d, import_ffmpeg_level(level), fmt, vl);
- }
-}
-
-struct AvioStream {
- Decoder *const decoder;
- InputStream &input;
-
- AVIOContext *io;
-
- unsigned char buffer[8192];
-
- AvioStream(Decoder *_decoder, InputStream &_input)
- :decoder(_decoder), input(_input), io(nullptr) {}
-
- ~AvioStream() {
- if (io != nullptr)
- av_free(io);
- }
-
- bool Open();
-};
-
-static int
-mpd_ffmpeg_stream_read(void *opaque, uint8_t *buf, int size)
-{
- AvioStream *stream = (AvioStream *)opaque;
-
- return decoder_read(stream->decoder, stream->input,
- (void *)buf, size);
-}
-
-static int64_t
-mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
-{
- AvioStream *stream = (AvioStream *)opaque;
-
- switch (whence) {
- case SEEK_SET:
- break;
-
- case SEEK_CUR:
- pos += stream->input.GetOffset();
- break;
-
- case SEEK_END:
- if (!stream->input.KnownSize())
- return -1;
-
- pos += stream->input.GetSize();
- break;
-
- case AVSEEK_SIZE:
- if (!stream->input.KnownSize())
- return -1;
-
- return stream->input.GetSize();
-
- default:
- return -1;
- }
-
- if (!stream->input.LockSeek(pos, IgnoreError()))
- return -1;
-
- return stream->input.GetOffset();
-}
-
-bool
-AvioStream::Open()
-{
- io = avio_alloc_context(buffer, sizeof(buffer),
- false, this,
- mpd_ffmpeg_stream_read, nullptr,
- input.IsSeekable()
- ? mpd_ffmpeg_stream_seek : nullptr);
- return io != nullptr;
-}
-
-/**
- * API compatibility wrapper for av_open_input_stream() and
- * avformat_open_input().
- */
-static int
-mpd_ffmpeg_open_input(AVFormatContext **ic_ptr,
- AVIOContext *pb,
- const char *filename,
- AVInputFormat *fmt)
+static AVFormatContext *
+FfmpegOpenInput(AVIOContext *pb,
+ const char *filename,
+ AVInputFormat *fmt)
{
AVFormatContext *context = avformat_alloc_context();
if (context == nullptr)
- return AVERROR(ENOMEM);
+ return nullptr;
context->pb = pb;
- *ic_ptr = context;
- return avformat_open_input(ic_ptr, filename, fmt, nullptr);
+
+ avformat_open_input(&context, filename, fmt, nullptr);
+ return context;
}
static bool
-ffmpeg_init(gcc_unused const config_param &param)
+ffmpeg_init(gcc_unused const ConfigBlock &block)
{
- av_log_set_callback(mpd_ffmpeg_log_callback);
-
- av_register_all();
+ FfmpegInit();
return true;
}
+gcc_pure
static int
-ffmpeg_find_audio_stream(const AVFormatContext *format_context)
+ffmpeg_find_audio_stream(const AVFormatContext &format_context)
{
- for (unsigned i = 0; i < format_context->nb_streams; ++i)
- if (format_context->streams[i]->codec->codec_type ==
+ for (unsigned i = 0; i < format_context.nb_streams; ++i)
+ if (format_context.streams[i]->codec->codec_type ==
AVMEDIA_TYPE_AUDIO)
return i;
return -1;
}
-gcc_const
-static double
-time_from_ffmpeg(int64_t t, const AVRational time_base)
-{
- assert(t != (int64_t)AV_NOPTS_VALUE);
-
- return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
- / (double)1024;
-}
-
-template<typename Ratio>
-static constexpr AVRational
-RatioToAVRational()
-{
- return { Ratio::num, Ratio::den };
-}
-
-gcc_const
-static int64_t
-time_to_ffmpeg(SongTime t, const AVRational time_base)
-{
- return av_rescale_q(t.count(),
- RatioToAVRational<SongTime::period>(),
- time_base);
-}
-
-/**
- * Replace #AV_NOPTS_VALUE with the given fallback.
- */
-static constexpr int64_t
-timestamp_fallback(int64_t t, int64_t fallback)
-{
- return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
- ? t
- : fallback;
-}
-
/**
* Accessor for AVStream::start_time that replaces AV_NOPTS_VALUE with
* zero. We can't use AV_NOPTS_VALUE in calculations, and we simply
* assume that the stream's start time is zero, which appears to be
* the best way out of that situation.
*/
-static int64_t
+static constexpr int64_t
start_time_fallback(const AVStream &stream)
{
- return timestamp_fallback(stream.start_time, 0);
+ return FfmpegTimestampFallback(stream.start_time, 0);
}
static void
@@ -264,99 +118,103 @@ copy_interleave_frame2(uint8_t *dest, uint8_t **src,
}
/**
- * Copy PCM data from a AVFrame to an interleaved buffer.
+ * Copy PCM data from a non-empty AVFrame to an interleaved buffer.
*/
-static int
-copy_interleave_frame(const AVCodecContext *codec_context,
- const AVFrame *frame,
- uint8_t **output_buffer,
- uint8_t **global_buffer, int *global_buffer_size)
+static ConstBuffer<void>
+copy_interleave_frame(const AVCodecContext &codec_context,
+ const AVFrame &frame,
+ FfmpegBuffer &global_buffer,
+ Error &error)
{
+ assert(frame.nb_samples > 0);
+
int plane_size;
const int data_size =
av_samples_get_buffer_size(&plane_size,
- codec_context->channels,
- frame->nb_samples,
- codec_context->sample_fmt, 1);
- if (data_size <= 0)
- return data_size;
-
- if (av_sample_fmt_is_planar(codec_context->sample_fmt) &&
- codec_context->channels > 1) {
- if(*global_buffer_size < data_size) {
- av_freep(global_buffer);
-
- *global_buffer = (uint8_t*)av_malloc(data_size);
-
- if (!*global_buffer)
- /* Not enough memory - shouldn't happen */
- return AVERROR(ENOMEM);
- *global_buffer_size = data_size;
+ codec_context.channels,
+ frame.nb_samples,
+ codec_context.sample_fmt, 1);
+ assert(data_size != 0);
+ if (data_size < 0) {
+ SetFfmpegError(error, data_size);
+ return 0;
+ }
+
+ void *output_buffer;
+ if (av_sample_fmt_is_planar(codec_context.sample_fmt) &&
+ codec_context.channels > 1) {
+ output_buffer = global_buffer.GetT<uint8_t>(data_size);
+ if (output_buffer == nullptr) {
+ /* Not enough memory - shouldn't happen */
+ error.SetErrno(ENOMEM);
+ return 0;
}
- *output_buffer = *global_buffer;
- copy_interleave_frame2(*output_buffer, frame->extended_data,
- frame->nb_samples,
- codec_context->channels,
- av_get_bytes_per_sample(codec_context->sample_fmt));
+
+ copy_interleave_frame2((uint8_t *)output_buffer,
+ frame.extended_data,
+ frame.nb_samples,
+ codec_context.channels,
+ av_get_bytes_per_sample(codec_context.sample_fmt));
} else {
- *output_buffer = frame->extended_data[0];
+ output_buffer = frame.extended_data[0];
}
- return data_size;
+ return { output_buffer, (size_t)data_size };
}
+/**
+ * Decode an #AVPacket and send the resulting PCM data to the decoder
+ * API.
+ */
static DecoderCommand
ffmpeg_send_packet(Decoder &decoder, InputStream &is,
- const AVPacket *packet,
- AVCodecContext *codec_context,
- const AVStream *stream,
- AVFrame *frame,
- uint8_t **buffer, int *buffer_size)
+ AVPacket packet,
+ AVCodecContext &codec_context,
+ const AVStream &stream,
+ AVFrame &frame,
+ FfmpegBuffer &buffer)
{
- if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE) {
- auto start = start_time_fallback(*stream);
- if (packet->pts >= start)
+ if (packet.pts >= 0 && packet.pts != (int64_t)AV_NOPTS_VALUE) {
+ auto start = start_time_fallback(stream);
+ if (packet.pts >= start)
decoder_timestamp(decoder,
- time_from_ffmpeg(packet->pts - start,
- stream->time_base));
+ FfmpegTimeToDouble(packet.pts - start,
+ stream.time_base));
}
- AVPacket packet2 = *packet;
-
- uint8_t *output_buffer;
+ Error error;
DecoderCommand cmd = DecoderCommand::NONE;
- while (packet2.size > 0 && cmd == DecoderCommand::NONE) {
- int audio_size = 0;
+ while (packet.size > 0 && cmd == DecoderCommand::NONE) {
int got_frame = 0;
- int len = avcodec_decode_audio4(codec_context,
- frame, &got_frame,
- &packet2);
- if (len >= 0 && got_frame) {
- audio_size = copy_interleave_frame(codec_context,
- frame,
- &output_buffer,
- buffer, buffer_size);
- if (audio_size < 0)
- len = audio_size;
- }
-
+ int len = avcodec_decode_audio4(&codec_context,
+ &frame, &got_frame,
+ &packet);
if (len < 0) {
/* if error, we skip the frame */
- LogDefault(ffmpeg_domain,
- "decoding failed, frame skipped");
+ LogFfmpegError(len, "decoding failed, frame skipped");
break;
}
- packet2.data += len;
- packet2.size -= len;
+ packet.data += len;
+ packet.size -= len;
- if (audio_size <= 0)
+ if (!got_frame || frame.nb_samples <= 0)
continue;
+ auto output_buffer =
+ copy_interleave_frame(codec_context, frame,
+ buffer, error);
+ if (output_buffer.IsNull()) {
+ /* this must be a serious error,
+ e.g. OOM */
+ LogError(error);
+ return DecoderCommand::STOP;
+ }
+
cmd = decoder_data(decoder, is,
- output_buffer, audio_size,
- codec_context->bit_rate / 1000);
+ output_buffer.data, output_buffer.size,
+ codec_context.bit_rate / 1000);
}
return cmd;
}
@@ -399,10 +257,8 @@ ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
static AVInputFormat *
ffmpeg_probe(Decoder *decoder, InputStream &is)
{
- enum {
- BUFFER_SIZE = 16384,
- PADDING = 16,
- };
+ constexpr size_t BUFFER_SIZE = 16384;
+ constexpr size_t PADDING = 16;
unsigned char buffer[BUFFER_SIZE];
size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE);
@@ -442,85 +298,163 @@ ffmpeg_probe(Decoder *decoder, InputStream &is)
}
static void
-ffmpeg_decode(Decoder &decoder, InputStream &input)
+FfmpegParseMetaData(AVDictionary &dict, ReplayGainInfo &rg, MixRampInfo &mr)
{
- AVInputFormat *input_format = ffmpeg_probe(&decoder, input);
- if (input_format == nullptr)
- return;
+ AVDictionaryEntry *i = nullptr;
- FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)",
- input_format->name, input_format->long_name);
+ while ((i = av_dict_get(&dict, "", i,
+ AV_DICT_IGNORE_SUFFIX)) != nullptr) {
+ const char *name = i->key;
+ const char *value = i->value;
- AvioStream stream(&decoder, input);
- if (!stream.Open()) {
- LogError(ffmpeg_domain, "Failed to open stream");
- return;
+ if (!ParseReplayGainTag(rg, name, value))
+ ParseMixRampTag(mr, name, value);
}
+}
- //ffmpeg works with ours "fileops" helper
- AVFormatContext *format_context = nullptr;
- if (mpd_ffmpeg_open_input(&format_context, stream.io,
- input.GetURI(),
- input_format) != 0) {
- LogError(ffmpeg_domain, "Open failed");
+static void
+FfmpegParseMetaData(const AVStream &stream,
+ ReplayGainInfo &rg, MixRampInfo &mr)
+{
+ FfmpegParseMetaData(*stream.metadata, rg, mr);
+}
+
+static void
+FfmpegParseMetaData(const AVFormatContext &format_context, int audio_stream,
+ ReplayGainInfo &rg, MixRampInfo &mr)
+{
+ assert(audio_stream >= 0);
+
+ FfmpegParseMetaData(*format_context.metadata, rg, mr);
+ FfmpegParseMetaData(*format_context.streams[audio_stream],
+ rg, mr);
+}
+
+static void
+FfmpegParseMetaData(Decoder &decoder,
+ const AVFormatContext &format_context, int audio_stream)
+{
+ ReplayGainInfo rg;
+ rg.Clear();
+
+ MixRampInfo mr;
+ mr.Clear();
+
+ FfmpegParseMetaData(format_context, audio_stream, rg, mr);
+
+ if (rg.IsDefined())
+ decoder_replay_gain(decoder, &rg);
+
+ if (mr.IsDefined())
+ decoder_mixramp(decoder, std::move(mr));
+}
+
+static void
+FfmpegScanMetadata(const AVStream &stream,
+ const tag_handler &handler, void *handler_ctx)
+{
+ FfmpegScanDictionary(stream.metadata, &handler, handler_ctx);
+}
+
+static void
+FfmpegScanMetadata(const AVFormatContext &format_context, int audio_stream,
+ const tag_handler &handler, void *handler_ctx)
+{
+ assert(audio_stream >= 0);
+
+ FfmpegScanDictionary(format_context.metadata, &handler, handler_ctx);
+ FfmpegScanMetadata(*format_context.streams[audio_stream],
+ handler, handler_ctx);
+}
+
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
+
+static void
+FfmpegScanTag(const AVFormatContext &format_context, int audio_stream,
+ TagBuilder &tag)
+{
+ FfmpegScanMetadata(format_context, audio_stream,
+ full_tag_handler, &tag);
+}
+
+/**
+ * Check if a new stream tag was received and pass it to
+ * decoder_tag().
+ */
+static void
+FfmpegCheckTag(Decoder &decoder, InputStream &is,
+ AVFormatContext &format_context, int audio_stream)
+{
+ AVStream &stream = *format_context.streams[audio_stream];
+ if ((stream.event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) == 0)
+ /* no new metadata */
return;
- }
+ /* clear the flag */
+ stream.event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
+
+ TagBuilder tag;
+ FfmpegScanTag(format_context, audio_stream, tag);
+ if (!tag.IsEmpty())
+ decoder_tag(decoder, is, tag.Commit());
+}
+
+#endif
+
+static void
+FfmpegDecode(Decoder &decoder, InputStream &input,
+ AVFormatContext &format_context)
+{
const int find_result =
- avformat_find_stream_info(format_context, nullptr);
+ avformat_find_stream_info(&format_context, nullptr);
if (find_result < 0) {
LogError(ffmpeg_domain, "Couldn't find stream info");
- avformat_close_input(&format_context);
return;
}
int audio_stream = ffmpeg_find_audio_stream(format_context);
if (audio_stream == -1) {
LogError(ffmpeg_domain, "No audio stream inside");
- avformat_close_input(&format_context);
return;
}
- AVStream *av_stream = format_context->streams[audio_stream];
+ AVStream &av_stream = *format_context.streams[audio_stream];
- AVCodecContext *codec_context = av_stream->codec;
+ 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);
+ 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)
+ if (codec_context.codec_name[0] != 0)
FormatDebug(ffmpeg_domain, "codec '%s'",
- codec_context->codec_name);
+ codec_context.codec_name);
#endif
- AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);
+ AVCodec *codec = avcodec_find_decoder(codec_context.codec_id);
if (!codec) {
LogError(ffmpeg_domain, "Unsupported audio codec");
- avformat_close_input(&format_context);
return;
}
const SampleFormat sample_format =
- ffmpeg_sample_format(codec_context->sample_fmt);
+ ffmpeg_sample_format(codec_context.sample_fmt);
if (sample_format == SampleFormat::UNDEFINED) {
// (error message already done by ffmpeg_sample_format())
- avformat_close_input(&format_context);
return;
}
Error error;
AudioFormat audio_format;
if (!audio_format_init_checked(audio_format,
- codec_context->sample_rate,
+ codec_context.sample_rate,
sample_format,
- codec_context->channels, error)) {
+ codec_context.channels, error)) {
LogError(error);
- avformat_close_input(&format_context);
return;
}
@@ -529,22 +463,20 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
values into AVCodecContext.channels - a change that will be
reverted later by avcodec_decode_audio3() */
- const int open_result = avcodec_open2(codec_context, codec, nullptr);
+ const int open_result = avcodec_open2(&codec_context, codec, nullptr);
if (open_result < 0) {
LogError(ffmpeg_domain, "Could not open codec");
- avformat_close_input(&format_context);
return;
}
const SignedSongTime total_time =
- format_context->duration != (int64_t)AV_NOPTS_VALUE
- ? SignedSongTime::FromScale<uint64_t>(format_context->duration,
- AV_TIME_BASE)
- : SignedSongTime::Negative();
+ FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
decoder_initialized(decoder, audio_format,
input.IsSeekable(), total_time);
+ FfmpegParseMetaData(decoder, format_context, audio_stream);
+
#if LIBAVUTIL_VERSION_MAJOR >= 53
AVFrame *frame = av_frame_alloc();
#else
@@ -552,26 +484,28 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
#endif
if (!frame) {
LogError(ffmpeg_domain, "Could not allocate frame");
- avformat_close_input(&format_context);
return;
}
- uint8_t *interleaved_buffer = nullptr;
- int interleaved_buffer_size = 0;
+ FfmpegBuffer interleaved_buffer;
DecoderCommand cmd;
do {
AVPacket packet;
- if (av_read_frame(format_context, &packet) < 0)
+ if (av_read_frame(&format_context, &packet) < 0)
/* end of file */
break;
+#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
+ FfmpegCheckTag(decoder, input, format_context, audio_stream);
+#endif
+
if (packet.stream_index == audio_stream)
cmd = ffmpeg_send_packet(decoder, input,
- &packet, codec_context,
+ packet, codec_context,
av_stream,
- frame,
- &interleaved_buffer, &interleaved_buffer_size);
+ *frame,
+ interleaved_buffer);
else
cmd = decoder_get_command(decoder);
@@ -579,15 +513,15 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
if (cmd == DecoderCommand::SEEK) {
int64_t where =
- time_to_ffmpeg(decoder_seek_time(decoder),
- av_stream->time_base) +
- start_time_fallback(*av_stream);
+ ToFfmpegTime(decoder_seek_time(decoder),
+ av_stream.time_base) +
+ start_time_fallback(av_stream);
- if (av_seek_frame(format_context, audio_stream, where,
+ if (av_seek_frame(&format_context, audio_stream, where,
AVSEEK_FLAG_ANY) < 0)
decoder_seek_error(decoder);
else {
- avcodec_flush_buffers(codec_context);
+ avcodec_flush_buffers(&codec_context);
decoder_command_finished(decoder);
}
}
@@ -598,15 +532,63 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
avcodec_free_frame(&frame);
#else
- av_freep(&frame);
+ av_free(frame);
#endif
- av_freep(&interleaved_buffer);
- avcodec_close(codec_context);
+ avcodec_close(&codec_context);
+}
+
+static void
+ffmpeg_decode(Decoder &decoder, InputStream &input)
+{
+ AVInputFormat *input_format = ffmpeg_probe(&decoder, input);
+ if (input_format == nullptr)
+ return;
+
+ FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)",
+ input_format->name, input_format->long_name);
+
+ AvioStream stream(&decoder, input);
+ if (!stream.Open()) {
+ LogError(ffmpeg_domain, "Failed to open stream");
+ return;
+ }
+
+ AVFormatContext *format_context =
+ FfmpegOpenInput(stream.io, input.GetURI(), input_format);
+ if (format_context == nullptr) {
+ LogError(ffmpeg_domain, "Open failed");
+ return;
+ }
+
+ FfmpegDecode(decoder, input, *format_context);
avformat_close_input(&format_context);
}
-//no tag reading in ffmpeg, check if playable
+static bool
+FfmpegScanStream(AVFormatContext &format_context,
+ const struct tag_handler &handler, void *handler_ctx)
+{
+ const int find_result =
+ avformat_find_stream_info(&format_context, nullptr);
+ if (find_result < 0)
+ return false;
+
+ const int audio_stream = ffmpeg_find_audio_stream(format_context);
+ if (audio_stream < 0)
+ return false;
+
+ const AVStream &stream = *format_context.streams[audio_stream];
+ if (stream.duration != (int64_t)AV_NOPTS_VALUE)
+ tag_handler_invoke_duration(&handler, handler_ctx,
+ FromFfmpegTime(stream.duration,
+ stream.time_base));
+
+ FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);
+
+ return true;
+}
+
static bool
ffmpeg_scan_stream(InputStream &is,
const struct tag_handler *handler, void *handler_ctx)
@@ -619,33 +601,14 @@ ffmpeg_scan_stream(InputStream &is,
if (!stream.Open())
return false;
- AVFormatContext *f = nullptr;
- if (mpd_ffmpeg_open_input(&f, stream.io, is.GetURI(),
- input_format) != 0)
+ AVFormatContext *f =
+ FfmpegOpenInput(stream.io, is.GetURI(), input_format);
+ if (f == nullptr)
return false;
- const int find_result =
- avformat_find_stream_info(f, nullptr);
- if (find_result < 0) {
- avformat_close_input(&f);
- return false;
- }
-
- if (f->duration != (int64_t)AV_NOPTS_VALUE) {
- const auto duration =
- SongTime::FromScale<uint64_t>(f->duration,
- AV_TIME_BASE);
- tag_handler_invoke_duration(handler, handler_ctx, duration);
- }
-
- ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
- int idx = ffmpeg_find_audio_stream(f);
- if (idx >= 0)
- ffmpeg_scan_dictionary(f->streams[idx]->metadata,
- handler, handler_ctx);
-
+ bool result = FfmpegScanStream(*f, *handler, handler_ctx);
avformat_close_input(&f);
- return true;
+ return result;
}
/**
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.hxx b/src/decoder/plugins/FfmpegDecoderPlugin.hxx
index 0a3e78e4b..5f2710d10 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.hxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FfmpegIo.cxx b/src/decoder/plugins/FfmpegIo.cxx
new file mode 100644
index 000000000..9603a131d
--- /dev/null
+++ b/src/decoder/plugins/FfmpegIo.cxx
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "FfmpegIo.hxx"
+#include "../DecoderAPI.hxx"
+#include "input/InputStream.hxx"
+#include "util/Error.hxx"
+
+AvioStream::~AvioStream()
+{
+ av_free(io);
+}
+
+inline int
+AvioStream::Read(void *dest, int size)
+{
+ return decoder_read(decoder, input, dest, size);
+}
+
+inline int64_t
+AvioStream::Seek(int64_t pos, int whence)
+{
+ switch (whence) {
+ case SEEK_SET:
+ break;
+
+ case SEEK_CUR:
+ pos += input.GetOffset();
+ break;
+
+ case SEEK_END:
+ if (!input.KnownSize())
+ return -1;
+
+ pos += input.GetSize();
+ break;
+
+ case AVSEEK_SIZE:
+ if (!input.KnownSize())
+ return -1;
+
+ return input.GetSize();
+
+ default:
+ return -1;
+ }
+
+ if (!input.LockSeek(pos, IgnoreError()))
+ return -1;
+
+ return input.GetOffset();
+}
+
+int
+AvioStream::_Read(void *opaque, uint8_t *buf, int size)
+{
+ AvioStream &stream = *(AvioStream *)opaque;
+
+ return stream.Read(buf, size);
+}
+
+int64_t
+AvioStream::_Seek(void *opaque, int64_t pos, int whence)
+{
+ AvioStream &stream = *(AvioStream *)opaque;
+
+ return stream.Seek(pos, whence);
+}
+
+bool
+AvioStream::Open()
+{
+ io = avio_alloc_context(buffer, sizeof(buffer),
+ false, this,
+ _Read, nullptr,
+ input.IsSeekable() ? _Seek : nullptr);
+ return io != nullptr;
+}
diff --git a/src/decoder/plugins/FfmpegIo.hxx b/src/decoder/plugins/FfmpegIo.hxx
new file mode 100644
index 000000000..add4b40e7
--- /dev/null
+++ b/src/decoder/plugins/FfmpegIo.hxx
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_IO_HXX
+#define MPD_FFMPEG_IO_HXX
+
+#include "check.h"
+
+extern "C" {
+#include "libavformat/avio.h"
+}
+
+#include <stdint.h>
+
+class InputStream;
+struct Decoder;
+
+struct AvioStream {
+ Decoder *const decoder;
+ InputStream &input;
+
+ AVIOContext *io;
+
+ uint8_t buffer[8192];
+
+ AvioStream(Decoder *_decoder, InputStream &_input)
+ :decoder(_decoder), input(_input), io(nullptr) {}
+
+ ~AvioStream();
+
+ bool Open();
+
+private:
+ int Read(void *buffer, int size);
+ int64_t Seek(int64_t pos, int whence);
+
+ static int _Read(void *opaque, uint8_t *buf, int size);
+ static int64_t _Seek(void *opaque, int64_t pos, int whence);
+};
+
+#endif
diff --git a/src/decoder/plugins/FfmpegMetaData.cxx b/src/decoder/plugins/FfmpegMetaData.cxx
index a39466945..102d5669e 100644
--- a/src/decoder/plugins/FfmpegMetaData.cxx
+++ b/src/decoder/plugins/FfmpegMetaData.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,7 +25,11 @@
#include "tag/TagTable.hxx"
#include "tag/TagHandler.hxx"
-static const struct tag_table ffmpeg_tags[] = {
+extern "C" {
+#include <libavutil/dict.h>
+}
+
+static constexpr struct tag_table ffmpeg_tags[] = {
{ "year", TAG_DATE },
{ "author-sort", TAG_ARTIST_SORT },
{ "album_artist", TAG_ALBUM_ARTIST },
@@ -36,9 +40,9 @@ static const struct tag_table ffmpeg_tags[] = {
};
static void
-ffmpeg_copy_metadata(TagType type,
- AVDictionary *m, const char *name,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanTag(TagType type,
+ AVDictionary *m, const char *name,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVDictionaryEntry *mt = nullptr;
@@ -48,8 +52,8 @@ ffmpeg_copy_metadata(TagType type,
}
static void
-ffmpeg_scan_pairs(AVDictionary *dict,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanPairs(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
{
AVDictionaryEntry *i = nullptr;
@@ -59,18 +63,20 @@ ffmpeg_scan_pairs(AVDictionary *dict,
}
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const struct tag_handler *handler, void *handler_ctx)
+FfmpegScanDictionary(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
{
- for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- ffmpeg_copy_metadata(TagType(i), dict, tag_item_names[i],
- handler, handler_ctx);
+ if (handler->tag != nullptr) {
+ for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
+ FfmpegScanTag(TagType(i), dict, tag_item_names[i],
+ handler, handler_ctx);
- for (const struct tag_table *i = ffmpeg_tags;
- i->name != nullptr; ++i)
- ffmpeg_copy_metadata(i->type, dict, i->name,
- handler, handler_ctx);
+ for (const struct tag_table *i = ffmpeg_tags;
+ i->name != nullptr; ++i)
+ FfmpegScanTag(i->type, dict, i->name,
+ handler, handler_ctx);
+ }
if (handler->pair != nullptr)
- ffmpeg_scan_pairs(dict, handler, handler_ctx);
+ FfmpegScanPairs(dict, handler, handler_ctx);
}
diff --git a/src/decoder/plugins/FfmpegMetaData.hxx b/src/decoder/plugins/FfmpegMetaData.hxx
index 5eb41db68..bdf5dd613 100644
--- a/src/decoder/plugins/FfmpegMetaData.hxx
+++ b/src/decoder/plugins/FfmpegMetaData.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,19 +20,11 @@
#ifndef MPD_FFMPEG_METADATA_HXX
#define MPD_FFMPEG_METADATA_HXX
-extern "C" {
-#include <libavutil/dict.h>
-}
-
-/* suppress the ffmpeg compatibility macro */
-#ifdef SampleFormat
-#undef SampleFormat
-#endif
-
+struct AVDictionary;
struct tag_handler;
void
-ffmpeg_scan_dictionary(AVDictionary *dict,
- const tag_handler *handler, void *handler_ctx);
+FfmpegScanDictionary(AVDictionary *dict,
+ const tag_handler *handler, void *handler_ctx);
#endif
diff --git a/src/decoder/plugins/FlacCommon.cxx b/src/decoder/plugins/FlacCommon.cxx
index e86f85569..e68871b1d 100644
--- a/src/decoder/plugins/FlacCommon.cxx
+++ b/src/decoder/plugins/FlacCommon.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacCommon.hxx b/src/decoder/plugins/FlacCommon.hxx
index 34ce0a3fc..e6c800cb9 100644
--- a/src/decoder/plugins/FlacCommon.hxx
+++ b/src/decoder/plugins/FlacCommon.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacDecoderPlugin.cxx b/src/decoder/plugins/FlacDecoderPlugin.cxx
index eea813401..1455f7084 100644
--- a/src/decoder/plugins/FlacDecoderPlugin.cxx
+++ b/src/decoder/plugins/FlacDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -291,7 +291,7 @@ flac_decode(Decoder &decoder, InputStream &input_stream)
}
static bool
-oggflac_init(gcc_unused const config_param &param)
+oggflac_init(gcc_unused const ConfigBlock &block)
{
return !!FLAC_API_SUPPORTS_OGG_FLAC;
}
diff --git a/src/decoder/plugins/FlacDecoderPlugin.h b/src/decoder/plugins/FlacDecoderPlugin.h
index fcdecf869..fa92ff32b 100644
--- a/src/decoder/plugins/FlacDecoderPlugin.h
+++ b/src/decoder/plugins/FlacDecoderPlugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacDomain.cxx b/src/decoder/plugins/FlacDomain.cxx
index fc5cc5498..591da3ee2 100644
--- a/src/decoder/plugins/FlacDomain.cxx
+++ b/src/decoder/plugins/FlacDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacDomain.hxx b/src/decoder/plugins/FlacDomain.hxx
index a06c6c6b4..a27b91d40 100644
--- a/src/decoder/plugins/FlacDomain.hxx
+++ b/src/decoder/plugins/FlacDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacIOHandle.cxx b/src/decoder/plugins/FlacIOHandle.cxx
index 0dd895798..b85efe6c8 100644
--- a/src/decoder/plugins/FlacIOHandle.cxx
+++ b/src/decoder/plugins/FlacIOHandle.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacIOHandle.hxx b/src/decoder/plugins/FlacIOHandle.hxx
index 90acc66af..e840528b1 100644
--- a/src/decoder/plugins/FlacIOHandle.hxx
+++ b/src/decoder/plugins/FlacIOHandle.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacInput.cxx b/src/decoder/plugins/FlacInput.cxx
index 5b4c3104d..91f54b807 100644
--- a/src/decoder/plugins/FlacInput.cxx
+++ b/src/decoder/plugins/FlacInput.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacInput.hxx b/src/decoder/plugins/FlacInput.hxx
index 427abccb4..f55b2ebbd 100644
--- a/src/decoder/plugins/FlacInput.hxx
+++ b/src/decoder/plugins/FlacInput.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacMetadata.cxx b/src/decoder/plugins/FlacMetadata.cxx
index 03e276dce..14a9fe294 100644
--- a/src/decoder/plugins/FlacMetadata.cxx
+++ b/src/decoder/plugins/FlacMetadata.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,7 @@
#include "tag/MixRamp.hxx"
#include "ReplayGainInfo.hxx"
#include "util/ASCII.hxx"
-#include "util/SplitString.hxx"
+#include "util/DivideString.hxx"
bool
flac_parse_replay_gain(ReplayGainInfo &rgi,
@@ -97,7 +97,7 @@ flac_scan_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
{
if (handler->pair != nullptr) {
const char *comment = (const char *)entry->entry;
- const SplitString split(comment, '=');
+ const DivideString split(comment, '=');
if (split.IsDefined() && !split.IsEmpty())
tag_handler_invoke_pair(handler, handler_ctx,
split.GetFirst(),
diff --git a/src/decoder/plugins/FlacMetadata.hxx b/src/decoder/plugins/FlacMetadata.hxx
index d791fa34e..4805f8042 100644
--- a/src/decoder/plugins/FlacMetadata.hxx
+++ b/src/decoder/plugins/FlacMetadata.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacPcm.cxx b/src/decoder/plugins/FlacPcm.cxx
index 311500f26..7ba4a6ad3 100644
--- a/src/decoder/plugins/FlacPcm.cxx
+++ b/src/decoder/plugins/FlacPcm.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FlacPcm.hxx b/src/decoder/plugins/FlacPcm.hxx
index 30c318725..51233a689 100644
--- a/src/decoder/plugins/FlacPcm.hxx
+++ b/src/decoder/plugins/FlacPcm.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
index f19ac5bf4..2b4967b95 100644
--- a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
+++ b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,7 +35,7 @@ static unsigned sample_rate;
static const char *soundfont_path;
/**
- * Convert a fluidsynth log level to a GLib log level.
+ * Convert a fluidsynth log level to a MPD log level.
*/
static LogLevel
fluidsynth_level_to_mpd(enum fluid_log_level level)
@@ -61,7 +61,7 @@ fluidsynth_level_to_mpd(enum fluid_log_level level)
}
/**
- * The fluidsynth logging callback. It forwards messages to the GLib
+ * The fluidsynth logging callback. It forwards messages to the MPD
* logging library.
*/
static void
@@ -73,17 +73,17 @@ fluidsynth_mpd_log_function(int level, char *message, gcc_unused void *data)
}
static bool
-fluidsynth_init(const config_param &param)
+fluidsynth_init(const ConfigBlock &block)
{
Error error;
- sample_rate = param.GetBlockValue("sample_rate", 48000u);
+ sample_rate = block.GetBlockValue("sample_rate", 48000u);
if (!audio_check_sample_rate(sample_rate, error)) {
LogError(error);
return false;
}
- soundfont_path = param.GetBlockValue("soundfont",
+ soundfont_path = block.GetBlockValue("soundfont",
"/usr/share/sounds/sf2/FluidR3_GM.sf2");
fluid_set_log_function(LAST_LOG_LEVEL,
diff --git a/src/decoder/plugins/FluidsynthDecoderPlugin.hxx b/src/decoder/plugins/FluidsynthDecoderPlugin.hxx
index cd8ec2d62..9845fd72e 100644
--- a/src/decoder/plugins/FluidsynthDecoderPlugin.hxx
+++ b/src/decoder/plugins/FluidsynthDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx
index cc6ce5e5d..dccf21d43 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.cxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
+#include "fs/AllocatedPath.hxx"
#include "util/Alloc.hxx"
#include "util/FormatString.hxx"
#include "util/UriUtil.hxx"
@@ -30,7 +31,6 @@
#include "util/Domain.hxx"
#include "Log.hxx"
-#include <glib.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -47,65 +47,42 @@ static constexpr unsigned GME_BUFFER_FRAMES = 2048;
static constexpr unsigned GME_BUFFER_SAMPLES =
GME_BUFFER_FRAMES * GME_CHANNELS;
-/**
- * returns the file path stripped of any /tune_xxx.* subtune
- * suffix
- */
-static char *
-get_container_name(Path path_fs)
+struct GmeContainerPath {
+ AllocatedPath path;
+ unsigned track;
+};
+
+gcc_pure
+static unsigned
+ParseSubtuneName(const char *base)
{
- const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
- char *path_container = xstrdup(path_fs.c_str());
-
- char pat[64];
- snprintf(pat, sizeof(pat), "%s%s",
- "*/" SUBTUNE_PREFIX "???.",
- subtune_suffix);
- GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
- if (!g_pattern_match(path_with_subtune,
- strlen(path_container), path_container, nullptr)) {
- g_pattern_spec_free(path_with_subtune);
- return path_container;
- }
+ if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
+ return 0;
- char *ptr = g_strrstr(path_container, "/" SUBTUNE_PREFIX);
- if (ptr != nullptr)
- *ptr='\0';
+ base += sizeof(SUBTUNE_PREFIX) - 1;
- g_pattern_spec_free(path_with_subtune);
- return path_container;
+ char *endptr;
+ auto track = strtoul(base, &endptr, 10);
+ if (endptr == base || *endptr != '.')
+ return 0;
+
+ return track;
}
/**
- * returns tune number from file.nsf/tune_xxx.* style path or 0 if no subtune
- * is appended.
+ * returns the file path stripped of any /tune_xxx.* subtune suffix
+ * and the track number (or 0 if no "tune_xxx" suffix is present).
*/
-static int
-get_song_num(Path path_fs)
+static GmeContainerPath
+ParseContainerPath(Path path_fs)
{
- const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
+ const Path base = path_fs.GetBase();
+ unsigned track;
+ if (base.IsNull() ||
+ (track = ParseSubtuneName(base.c_str())) < 1)
+ return { AllocatedPath(path_fs), 0 };
- char pat[64];
- snprintf(pat, sizeof(pat), "%s%s",
- "*/" SUBTUNE_PREFIX "???.",
- subtune_suffix);
- GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
-
- if (g_pattern_match(path_with_subtune,
- path_fs.length(), path_fs.data(), nullptr)) {
- char *sub = g_strrstr(path_fs.c_str(), "/" SUBTUNE_PREFIX);
- g_pattern_spec_free(path_with_subtune);
- if (!sub)
- return 0;
-
- sub += strlen("/" SUBTUNE_PREFIX);
- int song_num = strtol(sub, nullptr, 10);
-
- return song_num - 1;
- } else {
- g_pattern_spec_free(path_with_subtune);
- return 0;
- }
+ return { path_fs.GetDirectoryName(), track - 1 };
}
static char *
@@ -136,20 +113,18 @@ gme_container_scan(Path path_fs, const unsigned int tnum)
static void
gme_file_decode(Decoder &decoder, Path path_fs)
{
- char *path_container = get_container_name(path_fs);
+ const auto container = ParseContainerPath(path_fs);
Music_Emu *emu;
const char *gme_err =
- gme_open_file(path_container, &emu, GME_SAMPLE_RATE);
- free(path_container);
+ gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE);
if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err);
return;
}
gme_info_t *ti;
- const int song_num = get_song_num(path_fs);
- gme_err = gme_track_info(emu, &ti, song_num);
+ gme_err = gme_track_info(emu, &ti, container.track);
if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err);
gme_delete(emu);
@@ -175,7 +150,7 @@ gme_file_decode(Decoder &decoder, Path path_fs)
decoder_initialized(decoder, audio_format, true, song_len);
- gme_err = gme_start_track(emu, song_num);
+ gme_err = gme_start_track(emu, container.track);
if (gme_err != nullptr)
LogWarning(gme_domain, gme_err);
@@ -209,72 +184,85 @@ gme_file_decode(Decoder &decoder, Path path_fs)
gme_delete(emu);
}
-static bool
-gme_scan_file(Path path_fs,
- const struct tag_handler *handler, void *handler_ctx)
+static void
+ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count,
+ const struct tag_handler *handler, void *handler_ctx)
{
- char *path_container = get_container_name(path_fs);
-
- Music_Emu *emu;
- const char *gme_err =
- gme_open_file(path_container, &emu, GME_SAMPLE_RATE);
- free(path_container);
- if (gme_err != nullptr) {
- LogWarning(gme_domain, gme_err);
- return false;
- }
-
- const int song_num = get_song_num(path_fs);
-
- gme_info_t *ti;
- gme_err = gme_track_info(emu, &ti, song_num);
- if (gme_err != nullptr) {
- LogWarning(gme_domain, gme_err);
- gme_delete(emu);
- return false;
- }
-
- assert(ti != nullptr);
-
- if (ti->length > 0)
+ if (info.length > 0)
tag_handler_invoke_duration(handler, handler_ctx,
- SongTime::FromMS(ti->length));
+ SongTime::FromMS(info.length));
- if (ti->song != nullptr) {
- if (gme_track_count(emu) > 1) {
+ if (info.song != nullptr) {
+ if (track_count > 1) {
/* start numbering subtunes from 1 */
char tag_title[1024];
snprintf(tag_title, sizeof(tag_title),
- "%s (%d/%d)",
- ti->song, song_num + 1,
- gme_track_count(emu));
+ "%s (%u/%d)",
+ info.song, song_num + 1,
+ track_count);
tag_handler_invoke_tag(handler, handler_ctx,
TAG_TITLE, tag_title);
} else
tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, ti->song);
+ TAG_TITLE, info.song);
}
- if (ti->author != nullptr)
+ if (info.author != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
- TAG_ARTIST, ti->author);
+ TAG_ARTIST, info.author);
- if (ti->game != nullptr)
+ if (info.game != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
- TAG_ALBUM, ti->game);
+ TAG_ALBUM, info.game);
- if (ti->comment != nullptr)
+ if (info.comment != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
- TAG_COMMENT, ti->comment);
+ TAG_COMMENT, info.comment);
- if (ti->copyright != nullptr)
+ if (info.copyright != nullptr)
tag_handler_invoke_tag(handler, handler_ctx,
- TAG_DATE, ti->copyright);
+ TAG_DATE, info.copyright);
+}
+
+static bool
+ScanMusicEmu(Music_Emu *emu, unsigned song_num,
+ const struct tag_handler *handler, void *handler_ctx)
+{
+ gme_info_t *ti;
+ const char *gme_err = gme_track_info(emu, &ti, song_num);
+ if (gme_err != nullptr) {
+ LogWarning(gme_domain, gme_err);
+ return false;
+ }
+
+ assert(ti != nullptr);
+
+ ScanGmeInfo(*ti, song_num, gme_track_count(emu),
+ handler, handler_ctx);
gme_free_info(ti);
+ return true;
+}
+
+static bool
+gme_scan_file(Path path_fs,
+ const struct tag_handler *handler, void *handler_ctx)
+{
+ const auto container = ParseContainerPath(path_fs);
+
+ Music_Emu *emu;
+ const char *gme_err =
+ gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE);
+ if (gme_err != nullptr) {
+ LogWarning(gme_domain, gme_err);
+ return false;
+ }
+
+ const bool result = ScanMusicEmu(emu, container.track, handler, handler_ctx);
+
gme_delete(emu);
- return true;
+ return result;
}
static const char *const gme_suffixes[] = {
diff --git a/src/decoder/plugins/GmeDecoderPlugin.hxx b/src/decoder/plugins/GmeDecoderPlugin.hxx
index f4885b6e4..07f78d9e2 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.hxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/MadDecoderPlugin.cxx b/src/decoder/plugins/MadDecoderPlugin.cxx
index de6c9b127..ea2c9ac6c 100644
--- a/src/decoder/plugins/MadDecoderPlugin.cxx
+++ b/src/decoder/plugins/MadDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
#include <mad.h>
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
#include <id3tag.h>
#endif
@@ -107,9 +107,9 @@ mad_fixed_to_24_buffer(int32_t *dest, const struct mad_synth *synth,
}
static bool
-mp3_plugin_init(gcc_unused const config_param &param)
+mp3_plugin_init(gcc_unused const ConfigBlock &block)
{
- gapless_playback = config_get_bool(CONF_GAPLESS_MP3_PLAYBACK,
+ gapless_playback = config_get_bool(ConfigOption::GAPLESS_MP3_PLAYBACK,
DEFAULT_GAPLESS_MP3_PLAYBACK);
return true;
}
@@ -251,7 +251,7 @@ MadDecoder::FillBuffer()
return true;
}
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
static bool
parse_id3_replay_gain_info(ReplayGainInfo &rgi,
struct id3_tag *tag)
@@ -285,7 +285,7 @@ parse_id3_replay_gain_info(ReplayGainInfo &rgi,
}
#endif
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
gcc_pure
static MixRampInfo
parse_id3_mixramp(struct id3_tag *tag)
@@ -317,7 +317,7 @@ parse_id3_mixramp(struct id3_tag *tag)
inline void
MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
{
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
id3_byte_t *allocated = nullptr;
const id3_length_t count = stream.bufend - stream.this_frame;
@@ -369,7 +369,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
id3_tag_delete(id3_tag);
delete[] allocated;
-#else /* !HAVE_ID3TAG */
+#else /* !ENABLE_ID3TAG */
(void)mpd_tag;
/* This code is enabled when libid3tag is disabled. Instead
@@ -386,7 +386,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
#endif
}
-#ifndef HAVE_ID3TAG
+#ifndef ENABLE_ID3TAG
/**
* This function emulates libid3tag when it is disabled. Instead of
* doing a real analyzation of the frame, it just checks whether the
@@ -402,7 +402,7 @@ id3_tag_query(const void *p0, size_t length)
? (p[8] << 7) + p[9] + 10
: 0;
}
-#endif /* !HAVE_ID3TAG */
+#endif /* !ENABLE_ID3TAG */
static enum mp3_action
RecoverFrameError(struct mad_stream &stream)
@@ -504,10 +504,10 @@ struct xing {
enum xing_magic magic; /* header magic */
};
-static const unsigned XING_FRAMES = 1;
-static const unsigned XING_BYTES = 2;
-static const unsigned XING_TOC = 4;
-static const unsigned XING_SCALE = 8;
+static constexpr unsigned XING_FRAMES = 1;
+static constexpr unsigned XING_BYTES = 2;
+static constexpr unsigned XING_TOC = 4;
+static constexpr unsigned XING_SCALE = 8;
struct lame_version {
unsigned major;
diff --git a/src/decoder/plugins/MadDecoderPlugin.hxx b/src/decoder/plugins/MadDecoderPlugin.hxx
index eb2a10d6f..c06f7341a 100644
--- a/src/decoder/plugins/MadDecoderPlugin.hxx
+++ b/src/decoder/plugins/MadDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/MikmodDecoderPlugin.cxx b/src/decoder/plugins/MikmodDecoderPlugin.cxx
index 85633f1fc..135bae15a 100644
--- a/src/decoder/plugins/MikmodDecoderPlugin.cxx
+++ b/src/decoder/plugins/MikmodDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -109,15 +109,15 @@ static bool mikmod_loop;
static unsigned mikmod_sample_rate;
static bool
-mikmod_decoder_init(const config_param &param)
+mikmod_decoder_init(const ConfigBlock &block)
{
static char params[] = "";
- mikmod_loop = param.GetBlockValue("loop", false);
- mikmod_sample_rate = param.GetBlockValue("sample_rate", 44100u);
+ mikmod_loop = block.GetBlockValue("loop", false);
+ mikmod_sample_rate = block.GetBlockValue("sample_rate", 44100u);
if (!audio_valid_sample_rate(mikmod_sample_rate))
FormatFatalError("Invalid sample rate in line %d: %u",
- param.line, mikmod_sample_rate);
+ block.line, mikmod_sample_rate);
md_device = 0;
md_reverb = 0;
diff --git a/src/decoder/plugins/MikmodDecoderPlugin.hxx b/src/decoder/plugins/MikmodDecoderPlugin.hxx
index 27ba2a823..508c7ae28 100644
--- a/src/decoder/plugins/MikmodDecoderPlugin.hxx
+++ b/src/decoder/plugins/MikmodDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/ModplugDecoderPlugin.cxx b/src/decoder/plugins/ModplugDecoderPlugin.cxx
index 3e0a41550..153392929 100644
--- a/src/decoder/plugins/ModplugDecoderPlugin.cxx
+++ b/src/decoder/plugins/ModplugDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,12 +41,12 @@ static constexpr offset_type MODPLUG_FILE_LIMIT = 100 * 1024 * 1024;
static int modplug_loop_count;
static bool
-modplug_decoder_init(const config_param &param)
+modplug_decoder_init(const ConfigBlock &block)
{
- modplug_loop_count = param.GetBlockValue("loop_count", 0);
+ modplug_loop_count = block.GetBlockValue("loop_count", 0);
if (modplug_loop_count < -1)
FormatFatalError("Invalid loop count in line %d: %i",
- param.line, modplug_loop_count);
+ block.line, modplug_loop_count);
return true;
}
diff --git a/src/decoder/plugins/ModplugDecoderPlugin.hxx b/src/decoder/plugins/ModplugDecoderPlugin.hxx
index 08f2ecb12..5d20afc7f 100644
--- a/src/decoder/plugins/ModplugDecoderPlugin.hxx
+++ b/src/decoder/plugins/ModplugDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.cxx b/src/decoder/plugins/MpcdecDecoderPlugin.cxx
index befed0f3b..c87377dd6 100644
--- a/src/decoder/plugins/MpcdecDecoderPlugin.cxx
+++ b/src/decoder/plugins/MpcdecDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.hxx b/src/decoder/plugins/MpcdecDecoderPlugin.hxx
index 7f71311fa..86216b4c2 100644
--- a/src/decoder/plugins/MpcdecDecoderPlugin.hxx
+++ b/src/decoder/plugins/MpcdecDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/Mpg123DecoderPlugin.cxx b/src/decoder/plugins/Mpg123DecoderPlugin.cxx
index 166529a4d..760b8b9c2 100644
--- a/src/decoder/plugins/Mpg123DecoderPlugin.cxx
+++ b/src/decoder/plugins/Mpg123DecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@
static constexpr Domain mpg123_domain("mpg123");
static bool
-mpd_mpg123_init(gcc_unused const config_param &param)
+mpd_mpg123_init(gcc_unused const ConfigBlock &block)
{
mpg123_init();
diff --git a/src/decoder/plugins/Mpg123DecoderPlugin.hxx b/src/decoder/plugins/Mpg123DecoderPlugin.hxx
index fd089c6a4..e09e6f956 100644
--- a/src/decoder/plugins/Mpg123DecoderPlugin.hxx
+++ b/src/decoder/plugins/Mpg123DecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggCodec.cxx b/src/decoder/plugins/OggCodec.cxx
index c7f39586e..cd35609aa 100644
--- a/src/decoder/plugins/OggCodec.cxx
+++ b/src/decoder/plugins/OggCodec.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggCodec.hxx b/src/decoder/plugins/OggCodec.hxx
index 3b096561c..a47ae566e 100644
--- a/src/decoder/plugins/OggCodec.hxx
+++ b/src/decoder/plugins/OggCodec.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggFind.cxx b/src/decoder/plugins/OggFind.cxx
index 978e1d7cf..b452c0a00 100644
--- a/src/decoder/plugins/OggFind.cxx
+++ b/src/decoder/plugins/OggFind.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggFind.hxx b/src/decoder/plugins/OggFind.hxx
index 2aa4f6c06..47a80a232 100644
--- a/src/decoder/plugins/OggFind.hxx
+++ b/src/decoder/plugins/OggFind.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggSyncState.hxx b/src/decoder/plugins/OggSyncState.hxx
index 024902fff..1641b4aa1 100644
--- a/src/decoder/plugins/OggSyncState.hxx
+++ b/src/decoder/plugins/OggSyncState.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggUtil.cxx b/src/decoder/plugins/OggUtil.cxx
index 6341b0008..a7812238d 100644
--- a/src/decoder/plugins/OggUtil.cxx
+++ b/src/decoder/plugins/OggUtil.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OggUtil.hxx b/src/decoder/plugins/OggUtil.hxx
index 94c380ef4..b9bfe17de 100644
--- a/src/decoder/plugins/OggUtil.hxx
+++ b/src/decoder/plugins/OggUtil.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx
index e14827e38..0d03566a7 100644
--- a/src/decoder/plugins/OpusDecoderPlugin.cxx
+++ b/src/decoder/plugins/OpusDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -61,7 +61,7 @@ IsOpusTags(const ogg_packet &packet)
}
static bool
-mpd_opus_init(gcc_unused const config_param &param)
+mpd_opus_init(gcc_unused const ConfigBlock &block)
{
LogDebug(opus_domain, opus_get_version_string());
diff --git a/src/decoder/plugins/OpusDecoderPlugin.h b/src/decoder/plugins/OpusDecoderPlugin.h
index 260dab99a..c6a8e921d 100644
--- a/src/decoder/plugins/OpusDecoderPlugin.h
+++ b/src/decoder/plugins/OpusDecoderPlugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusDomain.cxx b/src/decoder/plugins/OpusDomain.cxx
index 1efd64a48..d65c9c14a 100644
--- a/src/decoder/plugins/OpusDomain.cxx
+++ b/src/decoder/plugins/OpusDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusDomain.hxx b/src/decoder/plugins/OpusDomain.hxx
index fb19e0301..813bc097c 100644
--- a/src/decoder/plugins/OpusDomain.hxx
+++ b/src/decoder/plugins/OpusDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusHead.cxx b/src/decoder/plugins/OpusHead.cxx
index bfa41d618..3357fdddb 100644
--- a/src/decoder/plugins/OpusHead.cxx
+++ b/src/decoder/plugins/OpusHead.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusHead.hxx b/src/decoder/plugins/OpusHead.hxx
index c478d8d90..b04386ff8 100644
--- a/src/decoder/plugins/OpusHead.hxx
+++ b/src/decoder/plugins/OpusHead.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusReader.hxx b/src/decoder/plugins/OpusReader.hxx
index c5b8e9107..c449a88d1 100644
--- a/src/decoder/plugins/OpusReader.hxx
+++ b/src/decoder/plugins/OpusReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusTags.cxx b/src/decoder/plugins/OpusTags.cxx
index aff5479c0..a77a0f71a 100644
--- a/src/decoder/plugins/OpusTags.cxx
+++ b/src/decoder/plugins/OpusTags.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/OpusTags.hxx b/src/decoder/plugins/OpusTags.hxx
index be3ac3a8d..57c46882e 100644
--- a/src/decoder/plugins/OpusTags.hxx
+++ b/src/decoder/plugins/OpusTags.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/PcmDecoderPlugin.cxx b/src/decoder/plugins/PcmDecoderPlugin.cxx
index c07a7b9b1..d9a8110de 100644
--- a/src/decoder/plugins/PcmDecoderPlugin.cxx
+++ b/src/decoder/plugins/PcmDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/PcmDecoderPlugin.hxx b/src/decoder/plugins/PcmDecoderPlugin.hxx
index 3582e5856..0fd0e6b26 100644
--- a/src/decoder/plugins/PcmDecoderPlugin.hxx
+++ b/src/decoder/plugins/PcmDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx
index 8435f095f..0d17e98c4 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.cxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,87 +22,64 @@
#include "../DecoderAPI.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
+#include "fs/AllocatedPath.hxx"
#include "util/FormatString.hxx"
#include "util/Domain.hxx"
+#include "util/Error.hxx"
#include "system/ByteOrder.hxx"
+#include "system/FatalError.hxx"
#include "Log.hxx"
-#include <errno.h>
-#include <stdlib.h>
#include <string.h>
-#include <glib.h>
#include <sidplay/sidplay2.h>
#include <sidplay/builders/resid.h>
#include <sidplay/utils/SidTuneMod.h>
+#include <sidplay/utils/SidDatabase.h>
#define SUBTUNE_PREFIX "tune_"
static constexpr Domain sidplay_domain("sidplay");
-static GPatternSpec *path_with_subtune;
-static const char *songlength_file;
-static GKeyFile *songlength_database;
+static SidDatabase *songlength_database;
static bool all_files_are_containers;
static unsigned default_songlength;
static bool filter_setting;
-static GKeyFile *
-sidplay_load_songlength_db(const char *path)
+static SidDatabase *
+sidplay_load_songlength_db(const Path path)
{
- GError *error = nullptr;
- gchar *data;
- gsize size;
-
- if (!g_file_get_contents(path, &data, &size, &error)) {
+ SidDatabase *db = new SidDatabase();
+ if (db->open(path.c_str()) < 0) {
FormatError(sidplay_domain,
"unable to read songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- return nullptr;
- }
-
- /* replace any ; comment characters with # */
- for (gsize i = 0; i < size; i++)
- if (data[i] == ';')
- data[i] = '#';
-
- GKeyFile *db = g_key_file_new();
- bool success = g_key_file_load_from_data(db, data, size,
- G_KEY_FILE_NONE, &error);
- g_free(data);
- if (!success) {
- FormatError(sidplay_domain,
- "unable to parse songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- g_key_file_free(db);
+ path.c_str(), db->error());
+ delete db;
return nullptr;
}
- g_key_file_set_list_separator(db, ' ');
return db;
}
static bool
-sidplay_init(const config_param &param)
+sidplay_init(const ConfigBlock &block)
{
/* read the songlengths database file */
- songlength_file = param.GetBlockValue("songlength_database");
- if (songlength_file != nullptr)
- songlength_database = sidplay_load_songlength_db(songlength_file);
+ Error error;
+ const auto database_path = block.GetBlockPath("songlength_database", error);
+ if (!database_path.IsNull())
+ songlength_database = sidplay_load_songlength_db(database_path);
+ else if (error.IsDefined())
+ FatalError(error);
- default_songlength = param.GetBlockValue("default_songlength", 0u);
+ default_songlength = block.GetBlockValue("default_songlength", 0u);
all_files_are_containers =
- param.GetBlockValue("all_files_are_containers", true);
+ block.GetBlockValue("all_files_are_containers", true);
- path_with_subtune=g_pattern_spec_new(
- "*/" SUBTUNE_PREFIX "???.sid");
-
- filter_setting = param.GetBlockValue("filter", true);
+ filter_setting = block.GetBlockValue("filter", true);
return true;
}
@@ -110,96 +87,61 @@ sidplay_init(const config_param &param)
static void
sidplay_finish()
{
- g_pattern_spec_free(path_with_subtune);
-
- if(songlength_database)
- g_key_file_free(songlength_database);
+ delete songlength_database;
}
-/**
- * returns the file path stripped of any /tune_xxx.sid subtune
- * suffix
- */
-static char *
-get_container_name(Path path_fs)
+struct SidplayContainerPath {
+ AllocatedPath path;
+ unsigned track;
+};
+
+gcc_pure
+static unsigned
+ParseSubtuneName(const char *base)
{
- char *path_container = strdup(path_fs.c_str());
+ if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
+ return 0;
- if(!g_pattern_match(path_with_subtune,
- strlen(path_container), path_container, nullptr))
- return path_container;
+ base += sizeof(SUBTUNE_PREFIX) - 1;
- char *ptr=g_strrstr(path_container, "/" SUBTUNE_PREFIX);
- if(ptr) *ptr='\0';
+ char *endptr;
+ auto track = strtoul(base, &endptr, 10);
+ if (endptr == base || *endptr != '.')
+ return 0;
- return path_container;
+ return track;
}
/**
- * returns tune number from file.sid/tune_xxx.sid style path or 1 if
- * no subtune is appended
+ * returns the file path stripped of any /tune_xxx.* subtune suffix
+ * and the track number (or 1 if no "tune_xxx" suffix is present).
*/
-static unsigned
-get_song_num(const char *path_fs)
+static SidplayContainerPath
+ParseContainerPath(Path path_fs)
{
- if(g_pattern_match(path_with_subtune,
- strlen(path_fs), path_fs, nullptr)) {
- char *sub=g_strrstr(path_fs, "/" SUBTUNE_PREFIX);
- if(!sub) return 1;
-
- sub+=strlen("/" SUBTUNE_PREFIX);
- int song_num=strtol(sub, nullptr, 10);
-
- if (errno == EINVAL)
- return 1;
- else
- return song_num;
- } else
- return 1;
+ const Path base = path_fs.GetBase();
+ unsigned track;
+ if (base.IsNull() ||
+ (track = ParseSubtuneName(base.c_str())) < 1)
+ return { AllocatedPath(path_fs), 1 };
+
+ return { path_fs.GetDirectoryName(), track };
}
/* get the song length in seconds */
static SignedSongTime
-get_song_length(Path path_fs)
+get_song_length(SidTuneMod &tune)
{
+ assert(tune);
+
if (songlength_database == nullptr)
return SignedSongTime::Negative();
- char *sid_file = get_container_name(path_fs);
- SidTuneMod tune(sid_file);
- free(sid_file);
- if(!tune) {
- LogWarning(sidplay_domain,
- "failed to load file for calculating md5 sum");
+ const auto length = songlength_database->length(tune);
+ if (length < 0)
return SignedSongTime::Negative();
- }
- char md5sum[SIDTUNE_MD5_LENGTH+1];
- tune.createMD5(md5sum);
-
- const unsigned song_num = get_song_num(path_fs.c_str());
- gsize num_items;
- gchar **values=g_key_file_get_string_list(songlength_database,
- "Database", md5sum, &num_items, nullptr);
- if(!values || song_num>num_items) {
- g_strfreev(values);
- return SignedSongTime::Negative();
- }
-
- int minutes=strtol(values[song_num-1], nullptr, 10);
- if(errno==EINVAL) minutes=0;
-
- int seconds;
- char *ptr=strchr(values[song_num-1], ':');
- if(ptr) {
- seconds=strtol(ptr+1, nullptr, 10);
- if(errno==EINVAL) seconds=0;
- } else
- seconds=0;
-
- g_strfreev(values);
-
- return SignedSongTime::FromS((minutes * 60) + seconds);
+ return SignedSongTime::FromS(length);
}
static void
@@ -209,18 +151,17 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
/* load the tune */
- char *path_container=get_container_name(path_fs);
- SidTune tune(path_container, nullptr, true);
- free(path_container);
+ const auto container = ParseContainerPath(path_fs);
+ SidTuneMod tune(container.path.c_str());
if (!tune) {
LogWarning(sidplay_domain, "failed to load file");
return;
}
- const int song_num = get_song_num(path_fs.c_str());
+ const int song_num = container.track;
tune.selectSong(song_num);
- auto duration = get_song_length(path_fs);
+ auto duration = get_song_length(tune);
if (duration.IsNegative() && default_songlength > 0)
duration = SongTime::FromS(default_songlength);
@@ -347,14 +288,15 @@ static bool
sidplay_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
- const int song_num = get_song_num(path_fs.c_str());
- char *path_container=get_container_name(path_fs);
+ const auto container = ParseContainerPath(path_fs);
+ const unsigned song_num = container.track;
- SidTune tune(path_container, nullptr, true);
- free(path_container);
+ SidTuneMod tune(container.path.c_str());
if (!tune)
return false;
+ tune.selectSong(song_num);
+
const SidTuneInfo &info = tune.getInfo();
/* title */
@@ -385,7 +327,7 @@ sidplay_scan_file(Path path_fs,
tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
/* time */
- const auto duration = get_song_length(path_fs);
+ const auto duration = get_song_length(tune);
if (!duration.IsNegative())
tag_handler_invoke_duration(handler, handler_ctx,
SongTime(duration));
diff --git a/src/decoder/plugins/SidplayDecoderPlugin.hxx b/src/decoder/plugins/SidplayDecoderPlugin.hxx
index 58786e646..d54ab9fa6 100644
--- a/src/decoder/plugins/SidplayDecoderPlugin.hxx
+++ b/src/decoder/plugins/SidplayDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/SndfileDecoderPlugin.cxx b/src/decoder/plugins/SndfileDecoderPlugin.cxx
index 5518c70be..68ca20cc7 100644
--- a/src/decoder/plugins/SndfileDecoderPlugin.cxx
+++ b/src/decoder/plugins/SndfileDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
static constexpr Domain sndfile_domain("sndfile");
static bool
-sndfile_init(gcc_unused const config_param &param)
+sndfile_init(gcc_unused const ConfigBlock &block)
{
LogDebug(sndfile_domain, sf_version_string());
return true;
diff --git a/src/decoder/plugins/SndfileDecoderPlugin.hxx b/src/decoder/plugins/SndfileDecoderPlugin.hxx
index d56acdd5a..c793e1356 100644
--- a/src/decoder/plugins/SndfileDecoderPlugin.hxx
+++ b/src/decoder/plugins/SndfileDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/VorbisComments.cxx b/src/decoder/plugins/VorbisComments.cxx
index 062f46acf..e742e32ff 100644
--- a/src/decoder/plugins/VorbisComments.cxx
+++ b/src/decoder/plugins/VorbisComments.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@
#include "tag/ReplayGain.hxx"
#include "ReplayGainInfo.hxx"
#include "util/ASCII.hxx"
-#include "util/SplitString.hxx"
+#include "util/DivideString.hxx"
#include <stddef.h>
#include <stdlib.h>
@@ -74,7 +74,7 @@ vorbis_scan_comment(const char *comment,
const struct tag_handler *handler, void *handler_ctx)
{
if (handler->pair != nullptr) {
- const SplitString split(comment, '=');
+ const DivideString split(comment, '=');
if (split.IsDefined() && !split.IsEmpty())
tag_handler_invoke_pair(handler, handler_ctx,
split.GetFirst(),
diff --git a/src/decoder/plugins/VorbisComments.hxx b/src/decoder/plugins/VorbisComments.hxx
index 893c89277..54912aed7 100644
--- a/src/decoder/plugins/VorbisComments.hxx
+++ b/src/decoder/plugins/VorbisComments.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/VorbisDecoderPlugin.cxx b/src/decoder/plugins/VorbisDecoderPlugin.cxx
index e0d3d1374..d569f747e 100644
--- a/src/decoder/plugins/VorbisDecoderPlugin.cxx
+++ b/src/decoder/plugins/VorbisDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -194,7 +194,7 @@ vorbis_interleave(float *dest, const float *const*src,
/* public */
static bool
-vorbis_init(gcc_unused const config_param &param)
+vorbis_init(gcc_unused const ConfigBlock &block)
{
#ifndef HAVE_TREMOR
LogDebug(vorbis_domain, vorbis_version_string());
diff --git a/src/decoder/plugins/VorbisDecoderPlugin.h b/src/decoder/plugins/VorbisDecoderPlugin.h
index b54df2e97..1e2aee47e 100644
--- a/src/decoder/plugins/VorbisDecoderPlugin.h
+++ b/src/decoder/plugins/VorbisDecoderPlugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/VorbisDomain.cxx b/src/decoder/plugins/VorbisDomain.cxx
index e3d880efa..2855e325d 100644
--- a/src/decoder/plugins/VorbisDomain.cxx
+++ b/src/decoder/plugins/VorbisDomain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/VorbisDomain.hxx b/src/decoder/plugins/VorbisDomain.hxx
index 48715e328..bd63e5948 100644
--- a/src/decoder/plugins/VorbisDomain.hxx
+++ b/src/decoder/plugins/VorbisDomain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx
index 67859bbd2..66d04bbe4 100644
--- a/src/decoder/plugins/WavpackDecoderPlugin.cxx
+++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,10 +28,10 @@
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/Macros.hxx"
+#include "util/Alloc.hxx"
#include "Log.hxx"
#include <wavpack/wavpack.h>
-#include <glib.h>
#include <assert.h>
#include <stdio.h>
@@ -484,10 +484,10 @@ wavpack_open_wvc(Decoder &decoder, const char *uri)
if (uri == nullptr)
return nullptr;
- char *wvc_url = g_strconcat(uri, "c", nullptr);
+ char *wvc_url = xstrcatdup(uri, "c");
InputStream *is_wvc = decoder_open_uri(decoder, uri, IgnoreError());
- g_free(wvc_url);
+ free(wvc_url);
if (is_wvc == nullptr)
return nullptr;
diff --git a/src/decoder/plugins/WavpackDecoderPlugin.hxx b/src/decoder/plugins/WavpackDecoderPlugin.hxx
index 2e5f9bd42..f2ee72e25 100644
--- a/src/decoder/plugins/WavpackDecoderPlugin.hxx
+++ b/src/decoder/plugins/WavpackDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/WildmidiDecoderPlugin.cxx b/src/decoder/plugins/WildmidiDecoderPlugin.cxx
index fc58f0977..64fa33b05 100644
--- a/src/decoder/plugins/WildmidiDecoderPlugin.cxx
+++ b/src/decoder/plugins/WildmidiDecoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -38,11 +38,11 @@ static constexpr Domain wildmidi_domain("wildmidi");
static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000;
static bool
-wildmidi_init(const config_param &param)
+wildmidi_init(const ConfigBlock &block)
{
Error error;
const AllocatedPath path =
- param.GetBlockPath("config_file",
+ block.GetBlockPath("config_file",
"/etc/timidity/timidity.cfg",
error);
if (path.IsNull())
diff --git a/src/decoder/plugins/WildmidiDecoderPlugin.hxx b/src/decoder/plugins/WildmidiDecoderPlugin.hxx
index fc87aab80..ec896662b 100644
--- a/src/decoder/plugins/WildmidiDecoderPlugin.hxx
+++ b/src/decoder/plugins/WildmidiDecoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/decoder/plugins/XiphTags.cxx b/src/decoder/plugins/XiphTags.cxx
index 11a0bcd42..24a2aa623 100644
--- a/src/decoder/plugins/XiphTags.cxx
+++ b/src/decoder/plugins/XiphTags.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,6 @@
const struct tag_table xiph_tags[] = {
{ "tracknumber", TAG_TRACK },
{ "discnumber", TAG_DISC },
- { "album artist", TAG_ALBUM_ARTIST },
{ "description", TAG_COMMENT },
{ nullptr, TAG_NUM_OF_ITEM_TYPES }
};
diff --git a/src/decoder/plugins/XiphTags.hxx b/src/decoder/plugins/XiphTags.hxx
index 48a27425f..d83e116c1 100644
--- a/src/decoder/plugins/XiphTags.hxx
+++ b/src/decoder/plugins/XiphTags.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/EncoderAPI.hxx b/src/encoder/EncoderAPI.hxx
index b147eac21..def543c58 100644
--- a/src/encoder/EncoderAPI.hxx
+++ b/src/encoder/EncoderAPI.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,10 +27,11 @@
// IWYU pragma: begin_exports
+#include "EncoderInterface.hxx"
#include "EncoderPlugin.hxx"
#include "AudioFormat.hxx"
#include "tag/Tag.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
// IWYU pragma: end_exports
diff --git a/src/encoder/EncoderInterface.hxx b/src/encoder/EncoderInterface.hxx
new file mode 100644
index 000000000..8ee723a63
--- /dev/null
+++ b/src/encoder/EncoderInterface.hxx
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_ENCODER_INTERFACE_HXX
+#define MPD_ENCODER_INTERFACE_HXX
+
+#include "EncoderPlugin.hxx"
+
+#include <assert.h>
+
+struct Encoder {
+ const EncoderPlugin &plugin;
+
+#ifndef NDEBUG
+ bool open, pre_tag, tag, end;
+#endif
+
+ explicit Encoder(const EncoderPlugin &_plugin)
+ :plugin(_plugin)
+#ifndef NDEBUG
+ , open(false)
+#endif
+ {}
+
+
+ /**
+ * Frees an #Encoder object.
+ */
+ void Dispose() {
+ assert(!open);
+
+ plugin.finish(this);
+ }
+
+ /**
+ * Opens the object. You must call this prior to using it.
+ * Before you free it, you must call Close(). You may open
+ * and close (reuse) one encoder any number of times.
+ *
+ * After this function returns successfully and before the
+ * first encoder_write() call, you should invoke
+ * encoder_read() to obtain the file header.
+ *
+ * @param audio_format the encoder's input audio format; the plugin
+ * may modify the struct to adapt it to its abilities
+ * @return true on success
+ */
+ bool Open(AudioFormat &audio_format, Error &error) {
+ assert(!open);
+
+ bool success = plugin.open(this, audio_format, error);
+#ifndef NDEBUG
+ open = success;
+ pre_tag = tag = end = false;
+#endif
+ return success;
+ }
+
+
+ /**
+ * Closes the object. This disables the encoder, and readies
+ * it for reusal by calling Open() again.
+ */
+ void Close() {
+ assert(open);
+
+ if (plugin.close != nullptr)
+ plugin.close(this);
+
+#ifndef NDEBUG
+ open = false;
+#endif
+ }
+};
+
+/**
+ * Ends the stream: flushes the encoder object, generate an
+ * end-of-stream marker (if applicable), make everything which might
+ * currently be buffered available by encoder_read().
+ *
+ * After this function has been called, the encoder may not be usable
+ * for more data, and only encoder_read() and Encoder::Close() can be
+ * called.
+ *
+ * @param encoder the encoder
+ * @return true on success
+ */
+static inline bool
+encoder_end(Encoder *encoder, Error &error)
+{
+ assert(encoder->open);
+ assert(!encoder->end);
+
+#ifndef NDEBUG
+ encoder->end = true;
+#endif
+
+ /* this method is optional */
+ return encoder->plugin.end != nullptr
+ ? encoder->plugin.end(encoder, error)
+ : true;
+}
+
+/**
+ * Flushes an encoder object, make everything which might currently be
+ * buffered available by encoder_read().
+ *
+ * @param encoder the encoder
+ * @return true on success
+ */
+static inline bool
+encoder_flush(Encoder *encoder, Error &error)
+{
+ assert(encoder->open);
+ assert(!encoder->pre_tag);
+ assert(!encoder->tag);
+ assert(!encoder->end);
+
+ /* this method is optional */
+ return encoder->plugin.flush != nullptr
+ ? encoder->plugin.flush(encoder, error)
+ : true;
+}
+
+/**
+ * Prepare for sending a tag to the encoder. This is used by some
+ * encoders to flush the previous sub-stream, in preparation to begin
+ * a new one.
+ *
+ * @param encoder the encoder
+ * @param tag the tag object
+ * @return true on success
+ */
+static inline bool
+encoder_pre_tag(Encoder *encoder, Error &error)
+{
+ assert(encoder->open);
+ assert(!encoder->pre_tag);
+ assert(!encoder->tag);
+ assert(!encoder->end);
+
+ /* this method is optional */
+ bool success = encoder->plugin.pre_tag != nullptr
+ ? encoder->plugin.pre_tag(encoder, error)
+ : true;
+
+#ifndef NDEBUG
+ encoder->pre_tag = success;
+#endif
+ return success;
+}
+
+/**
+ * Sends a tag to the encoder.
+ *
+ * Instructions: call encoder_pre_tag(); then obtain flushed data with
+ * encoder_read(); finally call encoder_tag().
+ *
+ * @param encoder the encoder
+ * @param tag the tag object
+ * @return true on success
+ */
+static inline bool
+encoder_tag(Encoder *encoder, const Tag &tag, Error &error)
+{
+ assert(encoder->open);
+ assert(!encoder->pre_tag);
+ assert(encoder->tag);
+ assert(!encoder->end);
+
+#ifndef NDEBUG
+ encoder->tag = false;
+#endif
+
+ /* this method is optional */
+ return encoder->plugin.tag != nullptr
+ ? encoder->plugin.tag(encoder, tag, error)
+ : true;
+}
+
+/**
+ * Writes raw PCM data to the encoder.
+ *
+ * @param encoder the encoder
+ * @param data the buffer containing PCM samples
+ * @param length the length of the buffer in bytes
+ * @return true on success
+ */
+static inline bool
+encoder_write(Encoder *encoder, const void *data, size_t length,
+ Error &error)
+{
+ assert(encoder->open);
+ assert(!encoder->pre_tag);
+ assert(!encoder->tag);
+ assert(!encoder->end);
+
+ return encoder->plugin.write(encoder, data, length, error);
+}
+
+/**
+ * Reads encoded data from the encoder.
+ *
+ * Call this repeatedly until no more data is returned.
+ *
+ * @param encoder the encoder
+ * @param dest the destination buffer to copy to
+ * @param length the maximum length of the destination buffer
+ * @return the number of bytes written to #dest
+ */
+static inline size_t
+encoder_read(Encoder *encoder, void *dest, size_t length)
+{
+ assert(encoder->open);
+ assert(!encoder->pre_tag || !encoder->tag);
+
+#ifndef NDEBUG
+ if (encoder->pre_tag) {
+ encoder->pre_tag = false;
+ encoder->tag = true;
+ }
+#endif
+
+ return encoder->plugin.read(encoder, dest, length);
+}
+
+/**
+ * Get mime type of encoded content.
+ *
+ * @param plugin the encoder plugin
+ * @return an constant string, nullptr on failure
+ */
+static inline const char *
+encoder_get_mime_type(Encoder *encoder)
+{
+ /* this method is optional */
+ return encoder->plugin.get_mime_type != nullptr
+ ? encoder->plugin.get_mime_type(encoder)
+ : nullptr;
+}
+
+#endif
diff --git a/src/encoder/EncoderList.cxx b/src/encoder/EncoderList.cxx
index 4bca5a4fe..f074f610b 100644
--- a/src/encoder/EncoderList.cxx
+++ b/src/encoder/EncoderList.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -33,16 +33,16 @@
const EncoderPlugin *const encoder_plugins[] = {
&null_encoder_plugin,
-#ifdef ENABLE_VORBIS_ENCODER
+#ifdef ENABLE_VORBISENC
&vorbis_encoder_plugin,
#endif
-#ifdef HAVE_OPUS
+#ifdef ENABLE_OPUS
&opus_encoder_plugin,
#endif
-#ifdef ENABLE_LAME_ENCODER
+#ifdef ENABLE_LAME
&lame_encoder_plugin,
#endif
-#ifdef ENABLE_TWOLAME_ENCODER
+#ifdef ENABLE_TWOLAME
&twolame_encoder_plugin,
#endif
#ifdef ENABLE_WAVE_ENCODER
@@ -51,7 +51,7 @@ const EncoderPlugin *const encoder_plugins[] = {
#ifdef ENABLE_FLAC_ENCODER
&flac_encoder_plugin,
#endif
-#ifdef ENABLE_SHINE_ENCODER
+#ifdef ENABLE_SHINE
&shine_encoder_plugin,
#endif
nullptr
diff --git a/src/encoder/EncoderList.hxx b/src/encoder/EncoderList.hxx
index e18d8ec74..19a4dd6d8 100644
--- a/src/encoder/EncoderList.hxx
+++ b/src/encoder/EncoderList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/EncoderPlugin.hxx b/src/encoder/EncoderPlugin.hxx
index 95e4e5838..f990bf105 100644
--- a/src/encoder/EncoderPlugin.hxx
+++ b/src/encoder/EncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,35 +20,18 @@
#ifndef MPD_ENCODER_PLUGIN_HXX
#define MPD_ENCODER_PLUGIN_HXX
-#include <assert.h>
-#include <stdbool.h>
#include <stddef.h>
-struct EncoderPlugin;
+struct Encoder;
struct AudioFormat;
-struct config_param;
+struct ConfigBlock;
struct Tag;
class Error;
-struct Encoder {
- const EncoderPlugin &plugin;
-
-#ifndef NDEBUG
- bool open, pre_tag, tag, end;
-#endif
-
- explicit Encoder(const EncoderPlugin &_plugin)
- :plugin(_plugin)
-#ifndef NDEBUG
- , open(false)
-#endif
- {}
-};
-
struct EncoderPlugin {
const char *name;
- Encoder *(*init)(const config_param &param,
+ Encoder *(*init)(const ConfigBlock &block,
Error &error);
void (*finish)(Encoder *encoder);
@@ -65,7 +48,7 @@ struct EncoderPlugin {
bool (*pre_tag)(Encoder *encoder, Error &error);
- bool (*tag)(Encoder *encoder, const Tag *tag,
+ bool (*tag)(Encoder *encoder, const Tag &tag,
Error &error);
bool (*write)(Encoder *encoder,
@@ -86,236 +69,10 @@ struct EncoderPlugin {
* @return an encoder object on success, nullptr on failure
*/
static inline Encoder *
-encoder_init(const EncoderPlugin &plugin, const config_param &param,
+encoder_init(const EncoderPlugin &plugin, const ConfigBlock &block,
Error &error_r)
{
- return plugin.init(param, error_r);
-}
-
-/**
- * Frees an encoder object.
- *
- * @param encoder the encoder
- */
-static inline void
-encoder_finish(Encoder *encoder)
-{
- assert(!encoder->open);
-
- encoder->plugin.finish(encoder);
-}
-
-/**
- * Opens an encoder object. You must call this prior to using it.
- * Before you free it, you must call encoder_close(). You may open
- * and close (reuse) one encoder any number of times.
- *
- * After this function returns successfully and before the first
- * encoder_write() call, you should invoke encoder_read() to obtain
- * the file header.
- *
- * @param encoder the encoder
- * @param audio_format the encoder's input audio format; the plugin
- * may modify the struct to adapt it to its abilities
- * @return true on success
- */
-static inline bool
-encoder_open(Encoder *encoder, AudioFormat &audio_format,
- Error &error)
-{
- assert(!encoder->open);
-
- bool success = encoder->plugin.open(encoder, audio_format, error);
-#ifndef NDEBUG
- encoder->open = success;
- encoder->pre_tag = encoder->tag = encoder->end = false;
-#endif
- return success;
-}
-
-/**
- * Closes an encoder object. This disables the encoder, and readies
- * it for reusal by calling encoder_open() again.
- *
- * @param encoder the encoder
- */
-static inline void
-encoder_close(Encoder *encoder)
-{
- assert(encoder->open);
-
- if (encoder->plugin.close != nullptr)
- encoder->plugin.close(encoder);
-
-#ifndef NDEBUG
- encoder->open = false;
-#endif
-}
-
-/**
- * Ends the stream: flushes the encoder object, generate an
- * end-of-stream marker (if applicable), make everything which might
- * currently be buffered available by encoder_read().
- *
- * After this function has been called, the encoder may not be usable
- * for more data, and only encoder_read() and encoder_close() can be
- * called.
- *
- * @param encoder the encoder
- * @return true on success
- */
-static inline bool
-encoder_end(Encoder *encoder, Error &error)
-{
- assert(encoder->open);
- assert(!encoder->end);
-
-#ifndef NDEBUG
- encoder->end = true;
-#endif
-
- /* this method is optional */
- return encoder->plugin.end != nullptr
- ? encoder->plugin.end(encoder, error)
- : true;
-}
-
-/**
- * Flushes an encoder object, make everything which might currently be
- * buffered available by encoder_read().
- *
- * @param encoder the encoder
- * @return true on success
- */
-static inline bool
-encoder_flush(Encoder *encoder, Error &error)
-{
- assert(encoder->open);
- assert(!encoder->pre_tag);
- assert(!encoder->tag);
- assert(!encoder->end);
-
- /* this method is optional */
- return encoder->plugin.flush != nullptr
- ? encoder->plugin.flush(encoder, error)
- : true;
-}
-
-/**
- * Prepare for sending a tag to the encoder. This is used by some
- * encoders to flush the previous sub-stream, in preparation to begin
- * a new one.
- *
- * @param encoder the encoder
- * @param tag the tag object
- * @return true on success
- */
-static inline bool
-encoder_pre_tag(Encoder *encoder, Error &error)
-{
- assert(encoder->open);
- assert(!encoder->pre_tag);
- assert(!encoder->tag);
- assert(!encoder->end);
-
- /* this method is optional */
- bool success = encoder->plugin.pre_tag != nullptr
- ? encoder->plugin.pre_tag(encoder, error)
- : true;
-
-#ifndef NDEBUG
- encoder->pre_tag = success;
-#endif
- return success;
-}
-
-/**
- * Sends a tag to the encoder.
- *
- * Instructions: call encoder_pre_tag(); then obtain flushed data with
- * encoder_read(); finally call encoder_tag().
- *
- * @param encoder the encoder
- * @param tag the tag object
- * @return true on success
- */
-static inline bool
-encoder_tag(Encoder *encoder, const Tag *tag, Error &error)
-{
- assert(encoder->open);
- assert(!encoder->pre_tag);
- assert(encoder->tag);
- assert(!encoder->end);
-
-#ifndef NDEBUG
- encoder->tag = false;
-#endif
-
- /* this method is optional */
- return encoder->plugin.tag != nullptr
- ? encoder->plugin.tag(encoder, tag, error)
- : true;
-}
-
-/**
- * Writes raw PCM data to the encoder.
- *
- * @param encoder the encoder
- * @param data the buffer containing PCM samples
- * @param length the length of the buffer in bytes
- * @return true on success
- */
-static inline bool
-encoder_write(Encoder *encoder, const void *data, size_t length,
- Error &error)
-{
- assert(encoder->open);
- assert(!encoder->pre_tag);
- assert(!encoder->tag);
- assert(!encoder->end);
-
- return encoder->plugin.write(encoder, data, length, error);
-}
-
-/**
- * Reads encoded data from the encoder.
- *
- * Call this repeatedly until no more data is returned.
- *
- * @param encoder the encoder
- * @param dest the destination buffer to copy to
- * @param length the maximum length of the destination buffer
- * @return the number of bytes written to #dest
- */
-static inline size_t
-encoder_read(Encoder *encoder, void *dest, size_t length)
-{
- assert(encoder->open);
- assert(!encoder->pre_tag || !encoder->tag);
-
-#ifndef NDEBUG
- if (encoder->pre_tag) {
- encoder->pre_tag = false;
- encoder->tag = true;
- }
-#endif
-
- return encoder->plugin.read(encoder, dest, length);
-}
-
-/**
- * Get mime type of encoded content.
- *
- * @param plugin the encoder plugin
- * @return an constant string, nullptr on failure
- */
-static inline const char *
-encoder_get_mime_type(Encoder *encoder)
-{
- /* this method is optional */
- return encoder->plugin.get_mime_type != nullptr
- ? encoder->plugin.get_mime_type(encoder)
- : nullptr;
+ return plugin.init(block, error_r);
}
#endif
diff --git a/src/encoder/ToOutputStream.cxx b/src/encoder/ToOutputStream.cxx
new file mode 100644
index 000000000..43345cf70
--- /dev/null
+++ b/src/encoder/ToOutputStream.cxx
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "ToOutputStream.hxx"
+#include "EncoderInterface.hxx"
+#include "fs/io/OutputStream.hxx"
+
+bool
+EncoderToOutputStream(OutputStream &os, Encoder &encoder, Error &error)
+{
+ while (true) {
+ /* read from the encoder */
+
+ char buffer[32768];
+ size_t nbytes = encoder_read(&encoder, buffer, sizeof(buffer));
+ if (nbytes == 0)
+ return true;
+
+ /* write everything to the stream */
+
+ if (!os.Write(buffer, nbytes, error))
+ return false;
+ }
+}
diff --git a/src/encoder/ToOutputStream.hxx b/src/encoder/ToOutputStream.hxx
new file mode 100644
index 000000000..e3fb7b908
--- /dev/null
+++ b/src/encoder/ToOutputStream.hxx
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_ENCODER_TO_OUTPUT_STREAM_HXX
+#define MPD_ENCODER_TO_OUTPUT_STREAM_HXX
+
+#include "check.h"
+
+struct Encoder;
+class OutputStream;
+class Error;
+
+bool
+EncoderToOutputStream(OutputStream &os, Encoder &encoder, Error &error);
+
+#endif
diff --git a/src/encoder/plugins/FlacEncoderPlugin.cxx b/src/encoder/plugins/FlacEncoderPlugin.cxx
index 26987fe99..afeef3b84 100644
--- a/src/encoder/plugins/FlacEncoderPlugin.cxx
+++ b/src/encoder/plugins/FlacEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -56,21 +56,21 @@ struct flac_encoder {
static constexpr Domain flac_encoder_domain("vorbis_encoder");
static bool
-flac_encoder_configure(struct flac_encoder *encoder, const config_param &param,
+flac_encoder_configure(struct flac_encoder *encoder, const ConfigBlock &block,
gcc_unused Error &error)
{
- encoder->compression = param.GetBlockValue("compression", 5u);
+ encoder->compression = block.GetBlockValue("compression", 5u);
return true;
}
static Encoder *
-flac_encoder_init(const config_param &param, Error &error)
+flac_encoder_init(const ConfigBlock &block, Error &error)
{
flac_encoder *encoder = new flac_encoder();
- /* load configuration from "param" */
- if (!flac_encoder_configure(encoder, param, error)) {
+ /* load configuration from "block" */
+ if (!flac_encoder_configure(encoder, block, error)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
diff --git a/src/encoder/plugins/FlacEncoderPlugin.hxx b/src/encoder/plugins/FlacEncoderPlugin.hxx
index 0cdc01600..dcd899974 100644
--- a/src/encoder/plugins/FlacEncoderPlugin.hxx
+++ b/src/encoder/plugins/FlacEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/LameEncoderPlugin.cxx b/src/encoder/plugins/LameEncoderPlugin.cxx
index 3878b52bb..7c6313109 100644
--- a/src/encoder/plugins/LameEncoderPlugin.cxx
+++ b/src/encoder/plugins/LameEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -47,18 +47,18 @@ struct LameEncoder final {
LameEncoder():encoder(lame_encoder_plugin) {}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
};
static constexpr Domain lame_encoder_domain("lame_encoder");
bool
-LameEncoder::Configure(const config_param &param, Error &error)
+LameEncoder::Configure(const ConfigBlock &block, Error &error)
{
const char *value;
char *endptr;
- value = param.GetBlockValue("quality");
+ value = block.GetBlockValue("quality");
if (value != nullptr) {
/* a quality was configured (VBR) */
@@ -72,7 +72,7 @@ LameEncoder::Configure(const config_param &param, Error &error)
return false;
}
- if (param.GetBlockValue("bitrate") != nullptr) {
+ if (block.GetBlockValue("bitrate") != nullptr) {
error.Set(config_domain,
"quality and bitrate are both defined");
return false;
@@ -80,7 +80,7 @@ LameEncoder::Configure(const config_param &param, Error &error)
} else {
/* a bit rate was configured */
- value = param.GetBlockValue("bitrate");
+ value = block.GetBlockValue("bitrate");
if (value == nullptr) {
error.Set(config_domain,
"neither bitrate nor quality defined");
@@ -101,12 +101,12 @@ LameEncoder::Configure(const config_param &param, Error &error)
}
static Encoder *
-lame_encoder_init(const config_param &param, Error &error)
+lame_encoder_init(const ConfigBlock &block, Error &error)
{
LameEncoder *encoder = new LameEncoder();
- /* load configuration from "param" */
- if (!encoder->Configure(param, error)) {
+ /* load configuration from "block" */
+ if (!encoder->Configure(block, error)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
diff --git a/src/encoder/plugins/LameEncoderPlugin.hxx b/src/encoder/plugins/LameEncoderPlugin.hxx
index 03e398f67..5a077f7cc 100644
--- a/src/encoder/plugins/LameEncoderPlugin.hxx
+++ b/src/encoder/plugins/LameEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/NullEncoderPlugin.cxx b/src/encoder/plugins/NullEncoderPlugin.cxx
index 1d571d465..99be7aec4 100644
--- a/src/encoder/plugins/NullEncoderPlugin.cxx
+++ b/src/encoder/plugins/NullEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@ struct NullEncoder final {
};
static Encoder *
-null_encoder_init(gcc_unused const config_param &param,
+null_encoder_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
NullEncoder *encoder = new NullEncoder();
diff --git a/src/encoder/plugins/NullEncoderPlugin.hxx b/src/encoder/plugins/NullEncoderPlugin.hxx
index 6acf88e49..9fabe81fd 100644
--- a/src/encoder/plugins/NullEncoderPlugin.hxx
+++ b/src/encoder/plugins/NullEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/OggSerial.cxx b/src/encoder/plugins/OggSerial.cxx
index 677829439..639d2b3c1 100644
--- a/src/encoder/plugins/OggSerial.cxx
+++ b/src/encoder/plugins/OggSerial.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/OggSerial.hxx b/src/encoder/plugins/OggSerial.hxx
index ceba8ebf9..21ae02804 100644
--- a/src/encoder/plugins/OggSerial.hxx
+++ b/src/encoder/plugins/OggSerial.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/OggStream.hxx b/src/encoder/plugins/OggStream.hxx
index 805238c1d..376a697a1 100644
--- a/src/encoder/plugins/OggStream.hxx
+++ b/src/encoder/plugins/OggStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/OpusEncoderPlugin.cxx b/src/encoder/plugins/OpusEncoderPlugin.cxx
index 27b614b86..4fd40cd50 100644
--- a/src/encoder/plugins/OpusEncoderPlugin.cxx
+++ b/src/encoder/plugins/OpusEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -73,9 +73,9 @@ static constexpr Domain opus_encoder_domain("opus_encoder");
static bool
opus_encoder_configure(struct opus_encoder *encoder,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
- const char *value = param.GetBlockValue("bitrate", "auto");
+ const char *value = block.GetBlockValue("bitrate", "auto");
if (strcmp(value, "auto") == 0)
encoder->bitrate = OPUS_AUTO;
else if (strcmp(value, "max") == 0)
@@ -90,13 +90,13 @@ opus_encoder_configure(struct opus_encoder *encoder,
}
}
- encoder->complexity = param.GetBlockValue("complexity", 10u);
+ encoder->complexity = block.GetBlockValue("complexity", 10u);
if (encoder->complexity > 10) {
error.Format(config_domain, "Invalid complexity");
return false;
}
- value = param.GetBlockValue("signal", "auto");
+ value = block.GetBlockValue("signal", "auto");
if (strcmp(value, "auto") == 0)
encoder->signal = OPUS_AUTO;
else if (strcmp(value, "voice") == 0)
@@ -112,12 +112,12 @@ opus_encoder_configure(struct opus_encoder *encoder,
}
static Encoder *
-opus_encoder_init(const config_param &param, Error &error)
+opus_encoder_init(const ConfigBlock &block, Error &error)
{
opus_encoder *encoder = new opus_encoder();
- /* load configuration from "param" */
- if (!opus_encoder_configure(encoder, param, error)) {
+ /* load configuration from "block" */
+ if (!opus_encoder_configure(encoder, block, error)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
diff --git a/src/encoder/plugins/OpusEncoderPlugin.hxx b/src/encoder/plugins/OpusEncoderPlugin.hxx
index 4e71694b9..09067e37d 100644
--- a/src/encoder/plugins/OpusEncoderPlugin.hxx
+++ b/src/encoder/plugins/OpusEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/ShineEncoderPlugin.cxx b/src/encoder/plugins/ShineEncoderPlugin.cxx
index 61cb8609e..c397906d3 100644
--- a/src/encoder/plugins/ShineEncoderPlugin.cxx
+++ b/src/encoder/plugins/ShineEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ struct ShineEncoder {
ShineEncoder():encoder(shine_encoder_plugin){}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
bool Setup(Error &error);
@@ -63,22 +63,21 @@ struct ShineEncoder {
static constexpr Domain shine_encoder_domain("shine_encoder");
inline bool
-ShineEncoder::Configure(const config_param &param,
- gcc_unused Error &error)
+ShineEncoder::Configure(const ConfigBlock &block, gcc_unused Error &error)
{
shine_set_config_mpeg_defaults(&config.mpeg);
- config.mpeg.bitr = param.GetBlockValue("bitrate", 128);
+ config.mpeg.bitr = block.GetBlockValue("bitrate", 128);
return true;
}
static Encoder *
-shine_encoder_init(const config_param &param, Error &error)
+shine_encoder_init(const ConfigBlock &block, Error &error)
{
ShineEncoder *encoder = new ShineEncoder();
- /* load configuration from "param" */
- if (!encoder->Configure(param, error)) {
+ /* load configuration from "block" */
+ if (!encoder->Configure(block, error)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
diff --git a/src/encoder/plugins/ShineEncoderPlugin.hxx b/src/encoder/plugins/ShineEncoderPlugin.hxx
index 8b1520a74..ecde902fb 100644
--- a/src/encoder/plugins/ShineEncoderPlugin.hxx
+++ b/src/encoder/plugins/ShineEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/TwolameEncoderPlugin.cxx b/src/encoder/plugins/TwolameEncoderPlugin.cxx
index 2eb6b2b1c..262fc6c33 100644
--- a/src/encoder/plugins/TwolameEncoderPlugin.cxx
+++ b/src/encoder/plugins/TwolameEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -53,18 +53,18 @@ struct TwolameEncoder final {
TwolameEncoder():encoder(twolame_encoder_plugin) {}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
};
static constexpr Domain twolame_encoder_domain("twolame_encoder");
bool
-TwolameEncoder::Configure(const config_param &param, Error &error)
+TwolameEncoder::Configure(const ConfigBlock &block, Error &error)
{
const char *value;
char *endptr;
- value = param.GetBlockValue("quality");
+ value = block.GetBlockValue("quality");
if (value != nullptr) {
/* a quality was configured (VBR) */
@@ -78,7 +78,7 @@ TwolameEncoder::Configure(const config_param &param, Error &error)
return false;
}
- if (param.GetBlockValue("bitrate") != nullptr) {
+ if (block.GetBlockValue("bitrate") != nullptr) {
error.Set(config_domain,
"quality and bitrate are both defined");
return false;
@@ -86,7 +86,7 @@ TwolameEncoder::Configure(const config_param &param, Error &error)
} else {
/* a bit rate was configured */
- value = param.GetBlockValue("bitrate");
+ value = block.GetBlockValue("bitrate");
if (value == nullptr) {
error.Set(config_domain,
"neither bitrate nor quality defined");
@@ -107,15 +107,15 @@ TwolameEncoder::Configure(const config_param &param, Error &error)
}
static Encoder *
-twolame_encoder_init(const config_param &param, Error &error_r)
+twolame_encoder_init(const ConfigBlock &block, Error &error_r)
{
FormatDebug(twolame_encoder_domain,
"libtwolame version %s", get_twolame_version());
TwolameEncoder *encoder = new TwolameEncoder();
- /* load configuration from "param" */
- if (!encoder->Configure(param, error_r)) {
+ /* load configuration from "block" */
+ if (!encoder->Configure(block, error_r)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
diff --git a/src/encoder/plugins/TwolameEncoderPlugin.hxx b/src/encoder/plugins/TwolameEncoderPlugin.hxx
index 531dd3e90..2c0b250da 100644
--- a/src/encoder/plugins/TwolameEncoderPlugin.hxx
+++ b/src/encoder/plugins/TwolameEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/VorbisEncoderPlugin.cxx b/src/encoder/plugins/VorbisEncoderPlugin.cxx
index ecc784a47..11e057eaa 100644
--- a/src/encoder/plugins/VorbisEncoderPlugin.cxx
+++ b/src/encoder/plugins/VorbisEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,14 +25,13 @@
#include "tag/Tag.hxx"
#include "AudioFormat.hxx"
#include "config/ConfigError.hxx"
+#include "util/StringUtil.hxx"
#include "util/NumberParser.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <vorbis/vorbisenc.h>
-#include <glib.h>
-
struct vorbis_encoder {
/** the base class */
Encoder encoder;
@@ -58,18 +57,18 @@ struct vorbis_encoder {
static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
static bool
-vorbis_encoder_configure(struct vorbis_encoder *encoder,
- const config_param &param, Error &error)
+vorbis_encoder_configure(struct vorbis_encoder &encoder,
+ const ConfigBlock &block, Error &error)
{
- const char *value = param.GetBlockValue("quality");
+ const char *value = block.GetBlockValue("quality");
if (value != nullptr) {
/* a quality was configured (VBR) */
char *endptr;
- encoder->quality = ParseDouble(value, &endptr);
+ encoder.quality = ParseDouble(value, &endptr);
- if (*endptr != '\0' || encoder->quality < -1.0 ||
- encoder->quality > 10.0) {
+ if (*endptr != '\0' || encoder.quality < -1.0 ||
+ encoder.quality > 10.0) {
error.Format(config_domain,
"quality \"%s\" is not a number in the "
"range -1 to 10",
@@ -77,7 +76,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
return false;
}
- if (param.GetBlockValue("bitrate") != nullptr) {
+ if (block.GetBlockValue("bitrate") != nullptr) {
error.Set(config_domain,
"quality and bitrate are both defined");
return false;
@@ -85,18 +84,18 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
} else {
/* a bit rate was configured */
- value = param.GetBlockValue("bitrate");
+ value = block.GetBlockValue("bitrate");
if (value == nullptr) {
error.Set(config_domain,
"neither bitrate nor quality defined");
return false;
}
- encoder->quality = -2.0;
+ encoder.quality = -2.0;
char *endptr;
- encoder->bitrate = ParseInt(value, &endptr);
- if (*endptr != '\0' || encoder->bitrate <= 0) {
+ encoder.bitrate = ParseInt(value, &endptr);
+ if (*endptr != '\0' || encoder.bitrate <= 0) {
error.Set(config_domain,
"bitrate should be a positive integer");
return false;
@@ -107,12 +106,12 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
}
static Encoder *
-vorbis_encoder_init(const config_param &param, Error &error)
+vorbis_encoder_init(const ConfigBlock &block, Error &error)
{
vorbis_encoder *encoder = new vorbis_encoder();
- /* load configuration from "param" */
- if (!vorbis_encoder_configure(encoder, param, error)) {
+ /* load configuration from "block" */
+ if (!vorbis_encoder_configure(*encoder, block, error)) {
/* configuration has failed, roll back and return error */
delete encoder;
return nullptr;
@@ -132,63 +131,63 @@ vorbis_encoder_finish(Encoder *_encoder)
}
static bool
-vorbis_encoder_reinit(struct vorbis_encoder *encoder, Error &error)
+vorbis_encoder_reinit(struct vorbis_encoder &encoder, Error &error)
{
- vorbis_info_init(&encoder->vi);
+ vorbis_info_init(&encoder.vi);
- if (encoder->quality >= -1.0) {
+ if (encoder.quality >= -1.0) {
/* a quality was configured (VBR) */
- if (0 != vorbis_encode_init_vbr(&encoder->vi,
- encoder->audio_format.channels,
- encoder->audio_format.sample_rate,
- encoder->quality * 0.1)) {
+ if (0 != vorbis_encode_init_vbr(&encoder.vi,
+ encoder.audio_format.channels,
+ encoder.audio_format.sample_rate,
+ encoder.quality * 0.1)) {
error.Set(vorbis_encoder_domain,
"error initializing vorbis vbr");
- vorbis_info_clear(&encoder->vi);
+ vorbis_info_clear(&encoder.vi);
return false;
}
} else {
/* a bit rate was configured */
- if (0 != vorbis_encode_init(&encoder->vi,
- encoder->audio_format.channels,
- encoder->audio_format.sample_rate, -1.0,
- encoder->bitrate * 1000, -1.0)) {
+ if (0 != vorbis_encode_init(&encoder.vi,
+ encoder.audio_format.channels,
+ encoder.audio_format.sample_rate, -1.0,
+ encoder.bitrate * 1000, -1.0)) {
error.Set(vorbis_encoder_domain,
"error initializing vorbis encoder");
- vorbis_info_clear(&encoder->vi);
+ vorbis_info_clear(&encoder.vi);
return false;
}
}
- vorbis_analysis_init(&encoder->vd, &encoder->vi);
- vorbis_block_init(&encoder->vd, &encoder->vb);
- encoder->stream.Initialize(GenerateOggSerial());
+ vorbis_analysis_init(&encoder.vd, &encoder.vi);
+ vorbis_block_init(&encoder.vd, &encoder.vb);
+ encoder.stream.Initialize(GenerateOggSerial());
return true;
}
static void
-vorbis_encoder_headerout(struct vorbis_encoder *encoder, vorbis_comment *vc)
+vorbis_encoder_headerout(struct vorbis_encoder &encoder, vorbis_comment &vc)
{
ogg_packet packet, comments, codebooks;
- vorbis_analysis_headerout(&encoder->vd, vc,
+ vorbis_analysis_headerout(&encoder.vd, &vc,
&packet, &comments, &codebooks);
- encoder->stream.PacketIn(packet);
- encoder->stream.PacketIn(comments);
- encoder->stream.PacketIn(codebooks);
+ encoder.stream.PacketIn(packet);
+ encoder.stream.PacketIn(comments);
+ encoder.stream.PacketIn(codebooks);
}
static void
-vorbis_encoder_send_header(struct vorbis_encoder *encoder)
+vorbis_encoder_send_header(struct vorbis_encoder &encoder)
{
vorbis_comment vc;
vorbis_comment_init(&vc);
- vorbis_encoder_headerout(encoder, &vc);
+ vorbis_encoder_headerout(encoder, vc);
vorbis_comment_clear(&vc);
}
@@ -197,11 +196,11 @@ vorbis_encoder_open(Encoder *_encoder,
AudioFormat &audio_format,
Error &error)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
audio_format.format = SampleFormat::FLOAT;
- encoder->audio_format = audio_format;
+ encoder.audio_format = audio_format;
if (!vorbis_encoder_reinit(encoder, error))
return false;
@@ -212,78 +211,78 @@ vorbis_encoder_open(Encoder *_encoder,
}
static void
-vorbis_encoder_clear(struct vorbis_encoder *encoder)
+vorbis_encoder_clear(struct vorbis_encoder &encoder)
{
- encoder->stream.Deinitialize();
- vorbis_block_clear(&encoder->vb);
- vorbis_dsp_clear(&encoder->vd);
- vorbis_info_clear(&encoder->vi);
+ encoder.stream.Deinitialize();
+ vorbis_block_clear(&encoder.vb);
+ vorbis_dsp_clear(&encoder.vd);
+ vorbis_info_clear(&encoder.vi);
}
static void
vorbis_encoder_close(Encoder *_encoder)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
vorbis_encoder_clear(encoder);
}
static void
-vorbis_encoder_blockout(struct vorbis_encoder *encoder)
+vorbis_encoder_blockout(struct vorbis_encoder &encoder)
{
- while (vorbis_analysis_blockout(&encoder->vd, &encoder->vb) == 1) {
- vorbis_analysis(&encoder->vb, nullptr);
- vorbis_bitrate_addblock(&encoder->vb);
+ while (vorbis_analysis_blockout(&encoder.vd, &encoder.vb) == 1) {
+ vorbis_analysis(&encoder.vb, nullptr);
+ vorbis_bitrate_addblock(&encoder.vb);
ogg_packet packet;
- while (vorbis_bitrate_flushpacket(&encoder->vd, &packet))
- encoder->stream.PacketIn(packet);
+ while (vorbis_bitrate_flushpacket(&encoder.vd, &packet))
+ encoder.stream.PacketIn(packet);
}
}
static bool
vorbis_encoder_flush(Encoder *_encoder, gcc_unused Error &error)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
- encoder->stream.Flush();
+ encoder.stream.Flush();
return true;
}
static bool
vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
- vorbis_analysis_wrote(&encoder->vd, 0);
+ vorbis_analysis_wrote(&encoder.vd, 0);
vorbis_encoder_blockout(encoder);
/* reinitialize vorbis_dsp_state and vorbis_block to reset the
end-of-stream marker */
- vorbis_block_clear(&encoder->vb);
- vorbis_dsp_clear(&encoder->vd);
- vorbis_analysis_init(&encoder->vd, &encoder->vi);
- vorbis_block_init(&encoder->vd, &encoder->vb);
+ vorbis_block_clear(&encoder.vb);
+ vorbis_dsp_clear(&encoder.vd);
+ vorbis_analysis_init(&encoder.vd, &encoder.vi);
+ vorbis_block_init(&encoder.vd, &encoder.vb);
- encoder->stream.Flush();
+ encoder.stream.Flush();
return true;
}
static void
-copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag)
+copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag &tag)
{
- for (const auto &item : *tag) {
- char *name = g_ascii_strup(tag_item_names[item.type], -1);
+ for (const auto &item : tag) {
+ char name[64];
+ ToUpperASCII(name, tag_item_names[item.type], sizeof(name));
vorbis_comment_add_tag(vc, name, item.value);
- g_free(name);
}
}
static bool
-vorbis_encoder_tag(Encoder *_encoder, const Tag *tag,
+vorbis_encoder_tag(Encoder *_encoder, const Tag &tag,
gcc_unused Error &error)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
vorbis_comment comment;
/* write the vorbis_comment object */
@@ -293,11 +292,11 @@ vorbis_encoder_tag(Encoder *_encoder, const Tag *tag,
/* reset ogg_stream_state and begin a new stream */
- encoder->stream.Reinitialize(GenerateOggSerial());
+ encoder.stream.Reinitialize(GenerateOggSerial());
/* send that vorbis_comment to the ogg_stream_state */
- vorbis_encoder_headerout(encoder, &comment);
+ vorbis_encoder_headerout(encoder, comment);
vorbis_comment_clear(&comment);
return true;
@@ -317,19 +316,19 @@ vorbis_encoder_write(Encoder *_encoder,
const void *data, size_t length,
gcc_unused Error &error)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
- unsigned num_frames = length / encoder->audio_format.GetFrameSize();
+ unsigned num_frames = length / encoder.audio_format.GetFrameSize();
/* this is for only 16-bit audio */
- interleaved_to_vorbis_buffer(vorbis_analysis_buffer(&encoder->vd,
+ interleaved_to_vorbis_buffer(vorbis_analysis_buffer(&encoder.vd,
num_frames),
(const float *)data,
num_frames,
- encoder->audio_format.channels);
+ encoder.audio_format.channels);
- vorbis_analysis_wrote(&encoder->vd, num_frames);
+ vorbis_analysis_wrote(&encoder.vd, num_frames);
vorbis_encoder_blockout(encoder);
return true;
}
@@ -337,9 +336,9 @@ vorbis_encoder_write(Encoder *_encoder,
static size_t
vorbis_encoder_read(Encoder *_encoder, void *dest, size_t length)
{
- struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
+ struct vorbis_encoder &encoder = *(struct vorbis_encoder *)_encoder;
- return encoder->stream.PageOut(dest, length);
+ return encoder.stream.PageOut(dest, length);
}
static const char *
diff --git a/src/encoder/plugins/VorbisEncoderPlugin.hxx b/src/encoder/plugins/VorbisEncoderPlugin.hxx
index 80703bf88..a6d1c46d2 100644
--- a/src/encoder/plugins/VorbisEncoderPlugin.hxx
+++ b/src/encoder/plugins/VorbisEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/encoder/plugins/WaveEncoderPlugin.cxx b/src/encoder/plugins/WaveEncoderPlugin.cxx
index 97a26e821..3493bed3a 100644
--- a/src/encoder/plugins/WaveEncoderPlugin.cxx
+++ b/src/encoder/plugins/WaveEncoderPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -79,7 +79,7 @@ fill_wave_header(struct wave_header *header, int channels, int bits,
}
static Encoder *
-wave_encoder_init(gcc_unused const config_param &param,
+wave_encoder_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
WaveEncoder *encoder = new WaveEncoder();
diff --git a/src/encoder/plugins/WaveEncoderPlugin.hxx b/src/encoder/plugins/WaveEncoderPlugin.hxx
index 341b98adc..878985612 100644
--- a/src/encoder/plugins/WaveEncoderPlugin.hxx
+++ b/src/encoder/plugins/WaveEncoderPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/BufferedSocket.cxx b/src/event/BufferedSocket.cxx
index 939824baa..97df66483 100644
--- a/src/event/BufferedSocket.cxx
+++ b/src/event/BufferedSocket.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/BufferedSocket.hxx b/src/event/BufferedSocket.hxx
index b1882de2f..1478f82ca 100644
--- a/src/event/BufferedSocket.hxx
+++ b/src/event/BufferedSocket.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/Call.cxx b/src/event/Call.cxx
index bc16c4e95..216d4a5e8 100644
--- a/src/event/Call.cxx
+++ b/src/event/Call.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/Call.hxx b/src/event/Call.hxx
index 808965de1..f16337ac3 100644
--- a/src/event/Call.hxx
+++ b/src/event/Call.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/DeferredMonitor.cxx b/src/event/DeferredMonitor.cxx
index 3e824012f..7d23746de 100644
--- a/src/event/DeferredMonitor.cxx
+++ b/src/event/DeferredMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/DeferredMonitor.hxx b/src/event/DeferredMonitor.hxx
index c4aa605fc..2697a7226 100644
--- a/src/event/DeferredMonitor.hxx
+++ b/src/event/DeferredMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/FullyBufferedSocket.cxx b/src/event/FullyBufferedSocket.cxx
index 457add2b0..6e52e704c 100644
--- a/src/event/FullyBufferedSocket.cxx
+++ b/src/event/FullyBufferedSocket.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/FullyBufferedSocket.hxx b/src/event/FullyBufferedSocket.hxx
index b03152be2..77b5c4416 100644
--- a/src/event/FullyBufferedSocket.hxx
+++ b/src/event/FullyBufferedSocket.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/IdleMonitor.cxx b/src/event/IdleMonitor.cxx
index 4af656a22..32b412825 100644
--- a/src/event/IdleMonitor.cxx
+++ b/src/event/IdleMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/IdleMonitor.hxx b/src/event/IdleMonitor.hxx
index 8d4d2681a..c7e9e4035 100644
--- a/src/event/IdleMonitor.hxx
+++ b/src/event/IdleMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx
index 1bac7c551..fca1f516f 100644
--- a/src/event/Loop.cxx
+++ b/src/event/Loop.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx
index 56804dc81..4001e31a0 100644
--- a/src/event/Loop.hxx
+++ b/src/event/Loop.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/MultiSocketMonitor.cxx b/src/event/MultiSocketMonitor.cxx
index ef77de425..6fc420b8d 100644
--- a/src/event/MultiSocketMonitor.cxx
+++ b/src/event/MultiSocketMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/MultiSocketMonitor.hxx b/src/event/MultiSocketMonitor.hxx
index b40ee8caa..eb6f51aa8 100644
--- a/src/event/MultiSocketMonitor.hxx
+++ b/src/event/MultiSocketMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroup.hxx b/src/event/PollGroup.hxx
index a2f176860..f376d50ca 100644
--- a/src/event/PollGroup.hxx
+++ b/src/event/PollGroup.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroupEPoll.hxx b/src/event/PollGroupEPoll.hxx
index d8edb8a1f..9457823a6 100644
--- a/src/event/PollGroupEPoll.hxx
+++ b/src/event/PollGroupEPoll.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroupPoll.cxx b/src/event/PollGroupPoll.cxx
index 402f8616f..b961c3f90 100644
--- a/src/event/PollGroupPoll.cxx
+++ b/src/event/PollGroupPoll.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroupPoll.hxx b/src/event/PollGroupPoll.hxx
index f7a3ccb4f..8d73280b4 100644
--- a/src/event/PollGroupPoll.hxx
+++ b/src/event/PollGroupPoll.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroupWinSelect.cxx b/src/event/PollGroupWinSelect.cxx
index 26c8abd46..796f699e2 100644
--- a/src/event/PollGroupWinSelect.cxx
+++ b/src/event/PollGroupWinSelect.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollGroupWinSelect.hxx b/src/event/PollGroupWinSelect.hxx
index d01067709..276a602a6 100644
--- a/src/event/PollGroupWinSelect.hxx
+++ b/src/event/PollGroupWinSelect.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/PollResultGeneric.hxx b/src/event/PollResultGeneric.hxx
index 35daf7f08..3dbeda0e4 100644
--- a/src/event/PollResultGeneric.hxx
+++ b/src/event/PollResultGeneric.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx
index 313f0a6cf..91c1d9bdf 100644
--- a/src/event/ServerSocket.cxx
+++ b/src/event/ServerSocket.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -198,7 +198,7 @@ OneServerSocket::Open(Error &error)
if (!path.IsNull())
chmod(path.c_str(), 0666);
- /* register in the GLib main loop */
+ /* register in the EventLoop */
SetFD(_fd);
diff --git a/src/event/ServerSocket.hxx b/src/event/ServerSocket.hxx
index 4c3fd9f1d..9faab1dab 100644
--- a/src/event/ServerSocket.hxx
+++ b/src/event/ServerSocket.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/SignalMonitor.cxx b/src/event/SignalMonitor.cxx
index 2d8fe681f..c9a7085eb 100644
--- a/src/event/SignalMonitor.cxx
+++ b/src/event/SignalMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/SignalMonitor.hxx b/src/event/SignalMonitor.hxx
index a41e57ef9..6bed61c66 100644
--- a/src/event/SignalMonitor.hxx
+++ b/src/event/SignalMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/SocketMonitor.cxx b/src/event/SocketMonitor.cxx
index 69207287d..00e6e6c45 100644
--- a/src/event/SocketMonitor.cxx
+++ b/src/event/SocketMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/SocketMonitor.hxx b/src/event/SocketMonitor.hxx
index 56d4273f0..4231e3ec0 100644
--- a/src/event/SocketMonitor.hxx
+++ b/src/event/SocketMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/TimeoutMonitor.cxx b/src/event/TimeoutMonitor.cxx
index 007e8aa2c..1bda47c5c 100644
--- a/src/event/TimeoutMonitor.cxx
+++ b/src/event/TimeoutMonitor.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/TimeoutMonitor.hxx b/src/event/TimeoutMonitor.hxx
index 414d48aa6..00289a0db 100644
--- a/src/event/TimeoutMonitor.hxx
+++ b/src/event/TimeoutMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/event/WakeFD.hxx b/src/event/WakeFD.hxx
index c6222b59c..4b3792111 100644
--- a/src/event/WakeFD.hxx
+++ b/src/event/WakeFD.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/FilterConfig.cxx b/src/filter/FilterConfig.cxx
index d8c1fc6c2..c5f24362c 100644
--- a/src/filter/FilterConfig.cxx
+++ b/src/filter/FilterConfig.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,10 +21,11 @@
#include "FilterConfig.hxx"
#include "plugins/ChainFilterPlugin.hxx"
#include "FilterPlugin.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Param.hxx"
#include "config/ConfigOption.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigError.hxx"
+#include "config/Block.hxx"
#include "util/Error.hxx"
#include <algorithm>
@@ -34,8 +35,8 @@
static bool
filter_chain_append_new(Filter &chain, const char *template_name, Error &error)
{
- const struct config_param *cfg =
- config_find_block(CONF_AUDIO_FILTER, "name", template_name);
+ const auto *cfg = config_find_block(ConfigBlockOption::AUDIO_FILTER,
+ "name", template_name);
if (cfg == nullptr) {
error.Format(config_domain,
"filter template not found: %s",
diff --git a/src/filter/FilterConfig.hxx b/src/filter/FilterConfig.hxx
index 1018eed51..93bebfdd3 100644
--- a/src/filter/FilterConfig.hxx
+++ b/src/filter/FilterConfig.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/FilterInternal.hxx b/src/filter/FilterInternal.hxx
index d2e619540..86a4cfd87 100644
--- a/src/filter/FilterInternal.hxx
+++ b/src/filter/FilterInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/FilterPlugin.cxx b/src/filter/FilterPlugin.cxx
index 98314f771..93d1942a0 100644
--- a/src/filter/FilterPlugin.cxx
+++ b/src/filter/FilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#include "config.h"
#include "FilterPlugin.hxx"
#include "FilterRegistry.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "config/ConfigError.hxx"
#include "util/Error.hxx"
@@ -28,20 +28,20 @@
Filter *
filter_new(const struct filter_plugin *plugin,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
assert(plugin != nullptr);
assert(!error.IsDefined());
- return plugin->init(param, error);
+ return plugin->init(block, error);
}
Filter *
-filter_configured_new(const config_param &param, Error &error)
+filter_configured_new(const ConfigBlock &block, Error &error)
{
assert(!error.IsDefined());
- const char *plugin_name = param.GetBlockValue("plugin");
+ const char *plugin_name = block.GetBlockValue("plugin");
if (plugin_name == nullptr) {
error.Set(config_domain, "No filter plugin specified");
return nullptr;
@@ -54,5 +54,5 @@ filter_configured_new(const config_param &param, Error &error)
return nullptr;
}
- return filter_new(plugin, param, error);
+ return filter_new(plugin, block, error);
}
diff --git a/src/filter/FilterPlugin.hxx b/src/filter/FilterPlugin.hxx
index 443d29881..b60566c49 100644
--- a/src/filter/FilterPlugin.hxx
+++ b/src/filter/FilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#ifndef MPD_FILTER_PLUGIN_HXX
#define MPD_FILTER_PLUGIN_HXX
-struct config_param;
+struct ConfigBlock;
class Filter;
class Error;
@@ -36,7 +36,7 @@ struct filter_plugin {
/**
* Allocates and configures a filter.
*/
- Filter *(*init)(const config_param &param, Error &error);
+ Filter *(*init)(const ConfigBlock &block, Error &error);
};
/**
@@ -50,7 +50,7 @@ struct filter_plugin {
*/
Filter *
filter_new(const struct filter_plugin *plugin,
- const config_param &param, Error &error);
+ const ConfigBlock &block, Error &error);
/**
* Creates a new filter, loads configuration and the plugin name from
@@ -62,6 +62,6 @@ filter_new(const struct filter_plugin *plugin,
* @return a new filter object, or nullptr on error
*/
Filter *
-filter_configured_new(const config_param &param, Error &error);
+filter_configured_new(const ConfigBlock &block, Error &error);
#endif
diff --git a/src/filter/FilterRegistry.cxx b/src/filter/FilterRegistry.cxx
index 286fb8db3..8c679940f 100644
--- a/src/filter/FilterRegistry.cxx
+++ b/src/filter/FilterRegistry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/FilterRegistry.hxx b/src/filter/FilterRegistry.hxx
index 24618a87a..51fac615f 100644
--- a/src/filter/FilterRegistry.hxx
+++ b/src/filter/FilterRegistry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/plugins/AutoConvertFilterPlugin.cxx b/src/filter/plugins/AutoConvertFilterPlugin.cxx
index 8586cb86e..52918080e 100644
--- a/src/filter/plugins/AutoConvertFilterPlugin.cxx
+++ b/src/filter/plugins/AutoConvertFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
#include "filter/FilterInternal.hxx"
#include "filter/FilterRegistry.hxx"
#include "AudioFormat.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "util/ConstBuffer.hxx"
#include <assert.h>
@@ -70,7 +70,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
if (in_audio_format != child_audio_format) {
/* yes - create a convert_filter */
- const config_param empty;
+ const ConfigBlock empty;
convert = filter_new(&convert_filter_plugin, empty, error);
if (convert == nullptr) {
filter->Close();
diff --git a/src/filter/plugins/AutoConvertFilterPlugin.hxx b/src/filter/plugins/AutoConvertFilterPlugin.hxx
index c5dfdd2f6..1b9061331 100644
--- a/src/filter/plugins/AutoConvertFilterPlugin.hxx
+++ b/src/filter/plugins/AutoConvertFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/plugins/ChainFilterPlugin.cxx b/src/filter/plugins/ChainFilterPlugin.cxx
index 4aeee69af..b965295f7 100644
--- a/src/filter/plugins/ChainFilterPlugin.cxx
+++ b/src/filter/plugins/ChainFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -70,7 +70,7 @@ private:
static constexpr Domain chain_filter_domain("chain_filter");
static Filter *
-chain_filter_init(gcc_unused const config_param &param,
+chain_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new ChainFilter();
diff --git a/src/filter/plugins/ChainFilterPlugin.hxx b/src/filter/plugins/ChainFilterPlugin.hxx
index b36aa3322..708b62126 100644
--- a/src/filter/plugins/ChainFilterPlugin.hxx
+++ b/src/filter/plugins/ChainFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/plugins/ConvertFilterPlugin.cxx b/src/filter/plugins/ConvertFilterPlugin.cxx
index 5c6a07ba1..18053abd0 100644
--- a/src/filter/plugins/ConvertFilterPlugin.cxx
+++ b/src/filter/plugins/ConvertFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -59,7 +59,7 @@ public:
};
static Filter *
-convert_filter_init(gcc_unused const config_param &param,
+convert_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new ConvertFilter();
diff --git a/src/filter/plugins/ConvertFilterPlugin.hxx b/src/filter/plugins/ConvertFilterPlugin.hxx
index bb4673651..8dd0bcd8e 100644
--- a/src/filter/plugins/ConvertFilterPlugin.hxx
+++ b/src/filter/plugins/ConvertFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/plugins/NormalizeFilterPlugin.cxx b/src/filter/plugins/NormalizeFilterPlugin.cxx
index 372ab53ac..77e8c1535 100644
--- a/src/filter/plugins/NormalizeFilterPlugin.cxx
+++ b/src/filter/plugins/NormalizeFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@ public:
};
static Filter *
-normalize_filter_init(gcc_unused const config_param &param,
+normalize_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new NormalizeFilter();
diff --git a/src/filter/plugins/NullFilterPlugin.cxx b/src/filter/plugins/NullFilterPlugin.cxx
index ebd8e4ec5..0bd8170f0 100644
--- a/src/filter/plugins/NullFilterPlugin.cxx
+++ b/src/filter/plugins/NullFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -48,7 +48,7 @@ public:
};
static Filter *
-null_filter_init(gcc_unused const config_param &param,
+null_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new NullFilter();
diff --git a/src/filter/plugins/ReplayGainFilterPlugin.cxx b/src/filter/plugins/ReplayGainFilterPlugin.cxx
index f76e48e37..ca1119331 100644
--- a/src/filter/plugins/ReplayGainFilterPlugin.cxx
+++ b/src/filter/plugins/ReplayGainFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -150,7 +150,7 @@ ReplayGainFilter::Update()
}
static Filter *
-replay_gain_filter_init(gcc_unused const config_param &param,
+replay_gain_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new ReplayGainFilter();
diff --git a/src/filter/plugins/ReplayGainFilterPlugin.hxx b/src/filter/plugins/ReplayGainFilterPlugin.hxx
index 346541b97..6c20aa872 100644
--- a/src/filter/plugins/ReplayGainFilterPlugin.hxx
+++ b/src/filter/plugins/ReplayGainFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/filter/plugins/RouteFilterPlugin.cxx b/src/filter/plugins/RouteFilterPlugin.cxx
index 4094119f2..11eb534c9 100644
--- a/src/filter/plugins/RouteFilterPlugin.cxx
+++ b/src/filter/plugins/RouteFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#include "config.h"
#include "config/ConfigError.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "AudioFormat.hxx"
#include "filter/FilterPlugin.hxx"
#include "filter/FilterInternal.hxx"
@@ -114,11 +114,11 @@ public:
* a>b, c>d, e>f, ...
* where a... are non-unique, non-negative integers
* and input channel a gets copied to output channel b, etc.
- * @param param the configuration block to read
+ * @param block the configuration block to read
* @param filter a route_filter whose min_channels and sources[] to set
* @return true on success, false on error
*/
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
/* virtual methods from class Filter */
AudioFormat Open(AudioFormat &af, Error &error) override;
@@ -128,7 +128,7 @@ public:
};
bool
-RouteFilter::Configure(const config_param &param, Error &error) {
+RouteFilter::Configure(const ConfigBlock &block, Error &error) {
/* TODO:
* With a more clever way of marking "don't copy to output N",
@@ -142,7 +142,7 @@ RouteFilter::Configure(const config_param &param, Error &error) {
min_output_channels = 0;
// A cowardly default, just passthrough stereo
- const char *routes = param.GetBlockValue("routes", "0>0, 1>1");
+ const char *routes = block.GetBlockValue("routes", "0>0, 1>1");
while (true) {
routes = StripLeft(routes);
@@ -205,10 +205,10 @@ RouteFilter::Configure(const config_param &param, Error &error) {
}
static Filter *
-route_filter_init(const config_param &param, Error &error)
+route_filter_init(const ConfigBlock &block, Error &error)
{
RouteFilter *filter = new RouteFilter();
- if (!filter->Configure(param, error)) {
+ if (!filter->Configure(block, error)) {
delete filter;
return nullptr;
}
diff --git a/src/filter/plugins/VolumeFilterPlugin.cxx b/src/filter/plugins/VolumeFilterPlugin.cxx
index 17e061476..b9c3c277e 100644
--- a/src/filter/plugins/VolumeFilterPlugin.cxx
+++ b/src/filter/plugins/VolumeFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ public:
static constexpr Domain volume_domain("pcm_volume");
static Filter *
-volume_filter_init(gcc_unused const config_param &param,
+volume_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new VolumeFilter();
diff --git a/src/filter/plugins/VolumeFilterPlugin.hxx b/src/filter/plugins/VolumeFilterPlugin.hxx
index b5317dc6f..93191b2d3 100644
--- a/src/filter/plugins/VolumeFilterPlugin.hxx
+++ b/src/filter/plugins/VolumeFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/AllocatedPath.cxx b/src/fs/AllocatedPath.cxx
index ceaad73ea..45447de69 100644
--- a/src/fs/AllocatedPath.cxx
+++ b/src/fs/AllocatedPath.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,33 +24,14 @@
#include "util/Error.hxx"
#include "Compiler.h"
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
-
-#include <string.h>
-
-#ifdef HAVE_GLIB
-
-inline AllocatedPath::AllocatedPath(Donate, pointer _value)
- :value(_value) {
- g_free(_value);
-}
-
-#endif
-
/* no inlining, please */
AllocatedPath::~AllocatedPath() {}
AllocatedPath
AllocatedPath::FromUTF8(const char *path_utf8)
{
-#ifdef HAVE_GLIB
- char *path = ::PathFromUTF8(path_utf8);
- if (path == nullptr)
- return AllocatedPath::Null();
-
- return AllocatedPath(Donate(), path);
+#ifdef HAVE_FS_CHARSET
+ return AllocatedPath(::PathFromUTF8(path_utf8));
#else
return FromFS(path_utf8);
#endif
@@ -111,7 +92,7 @@ AllocatedPath::ChopSeparators()
while (l >= 2 && PathTraitsFS::IsSeparator(p[l - 1])) {
--l;
-#if GCC_CHECK_VERSION(4,7) && !defined(__clang__)
+#if GCC_CHECK_VERSION(4,7)
value.pop_back();
#else
value.erase(value.end() - 1, value.end());
diff --git a/src/fs/AllocatedPath.hxx b/src/fs/AllocatedPath.hxx
index c345470c8..7195a3345 100644
--- a/src/fs/AllocatedPath.hxx
+++ b/src/fs/AllocatedPath.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -44,13 +44,6 @@ class AllocatedPath {
string value;
- struct Donate {};
-
- /**
- * Donate the allocated pointer to a new #AllocatedPath object.
- */
- AllocatedPath(Donate, pointer _value);
-
AllocatedPath(const_pointer _value):value(_value) {}
AllocatedPath(string &&_value):value(std::move(_value)) {}
@@ -169,6 +162,16 @@ public:
return *this;
}
+ gcc_pure
+ bool operator==(const AllocatedPath &other) const {
+ return value == other.value;
+ }
+
+ gcc_pure
+ bool operator!=(const AllocatedPath &other) const {
+ return value != other.value;
+ }
+
/**
* Allows the caller to "steal" the internal value by
* providing a rvalue reference to the std::string attribute.
diff --git a/src/fs/Charset.cxx b/src/fs/Charset.cxx
index c634c9340..cbfe6ea3e 100644
--- a/src/fs/Charset.cxx
+++ b/src/fs/Charset.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,66 +21,52 @@
#include "Charset.hxx"
#include "Domain.hxx"
#include "Limits.hxx"
-#include "system/FatalError.hxx"
#include "Log.hxx"
#include "Traits.hxx"
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
+#include "lib/icu/Converter.hxx"
+#include "util/Error.hxx"
#include <algorithm>
#include <assert.h>
#include <string.h>
-#ifdef HAVE_GLIB
-
-/**
- * Maximal number of bytes required to represent path name in UTF-8
- * (including nul-terminator).
- * This value is a rought estimate of upper bound.
- * It's based on path name limit in bytes (MPD_PATH_MAX)
- * and assumption that some weird encoding could represent some UTF-8 4 byte
- * sequences with single byte.
- */
-static constexpr size_t MPD_PATH_MAX_UTF8 = (MPD_PATH_MAX - 1) * 4 + 1;
+#ifdef HAVE_FS_CHARSET
static std::string fs_charset;
-gcc_pure
-static bool
-IsSupportedCharset(const char *charset)
-{
- /* convert a space to check if the charset is valid */
- char *test = g_convert(" ", 1, charset, "UTF-8", nullptr, nullptr, nullptr);
- if (test == nullptr)
- return false;
-
- g_free(test);
- return true;
-}
+static IcuConverter *fs_converter;
-void
-SetFSCharset(const char *charset)
+bool
+SetFSCharset(const char *charset, Error &error)
{
assert(charset != nullptr);
+ assert(fs_converter == nullptr);
- if (!IsSupportedCharset(charset))
- FormatFatalError("invalid filesystem charset: %s", charset);
-
- fs_charset = charset;
+ fs_converter = IcuConverter::Create(charset, error);
+ if (fs_converter == nullptr)
+ return false;
FormatDebug(path_domain,
"SetFSCharset: fs charset is: %s", fs_charset.c_str());
+ return true;
}
#endif
+void
+DeinitFSCharset()
+{
+#ifdef HAVE_ICU_CONVERTER
+ delete fs_converter;
+ fs_converter = nullptr;
+#endif
+}
+
const char *
GetFSCharset()
{
-#ifdef HAVE_GLIB
+#ifdef HAVE_FS_CHARSET
return fs_charset.empty() ? "UTF-8" : fs_charset.c_str();
#else
return "UTF-8";
@@ -108,43 +94,24 @@ PathToUTF8(const char *path_fs)
assert(path_fs != nullptr);
#endif
-#ifdef HAVE_GLIB
- if (fs_charset.empty()) {
+#ifdef HAVE_FS_CHARSET
+ if (fs_converter == nullptr) {
#endif
auto result = std::string(path_fs);
FixSeparators(result);
return result;
-#ifdef HAVE_GLIB
+#ifdef HAVE_FS_CHARSET
}
- GIConv conv = g_iconv_open("utf-8", fs_charset.c_str());
- if (conv == reinterpret_cast<GIConv>(-1))
- return std::string();
-
- // g_iconv() does not need nul-terminator,
- // std::string could be created without it too.
- char path_utf8[MPD_PATH_MAX_UTF8 - 1];
- char *in = const_cast<char *>(path_fs);
- char *out = path_utf8;
- size_t in_left = strlen(path_fs);
- size_t out_left = sizeof(path_utf8);
-
- size_t ret = g_iconv(conv, &in, &in_left, &out, &out_left);
-
- g_iconv_close(conv);
-
- if (ret == static_cast<size_t>(-1) || in_left > 0)
- return std::string();
-
- auto result_path = std::string(path_utf8, sizeof(path_utf8) - out_left);
+ auto result_path = fs_converter->ToUTF8(path_fs);
FixSeparators(result_path);
return result_path;
#endif
}
-#ifdef HAVE_GLIB
+#ifdef HAVE_FS_CHARSET
-char *
+std::string
PathFromUTF8(const char *path_utf8)
{
#if !CLANG_CHECK_VERSION(3,6)
@@ -152,12 +119,10 @@ PathFromUTF8(const char *path_utf8)
assert(path_utf8 != nullptr);
#endif
- if (fs_charset.empty())
- return g_strdup(path_utf8);
+ if (fs_converter == nullptr)
+ return path_utf8;
- return g_convert(path_utf8, -1,
- fs_charset.c_str(), "utf-8",
- nullptr, nullptr, nullptr);
+ return fs_converter->FromUTF8(path_utf8);
}
#endif
diff --git a/src/fs/Charset.hxx b/src/fs/Charset.hxx
index 0a71d7c58..dd5ca168a 100644
--- a/src/fs/Charset.hxx
+++ b/src/fs/Charset.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,12 @@
#include <string>
+#if defined(HAVE_ICU) || defined(HAVE_GLIB)
+#define HAVE_FS_CHARSET
+#endif
+
+class Error;
+
/**
* Gets file system character set name.
*/
@@ -32,8 +38,11 @@ gcc_const
const char *
GetFSCharset();
+bool
+SetFSCharset(const char *charset, Error &error);
+
void
-SetFSCharset(const char *charset);
+DeinitFSCharset();
/**
* Convert the path to UTF-8.
@@ -43,8 +52,12 @@ gcc_pure gcc_nonnull_all
std::string
PathToUTF8(const char *path_fs);
-gcc_malloc gcc_nonnull_all
-char *
+/**
+ * Convert the path from UTF-8.
+ * Returns empty string on error.
+ */
+gcc_pure gcc_nonnull_all
+std::string
PathFromUTF8(const char *path_utf8);
#endif
diff --git a/src/fs/CheckFile.cxx b/src/fs/CheckFile.cxx
index a35443674..3f44e8397 100644
--- a/src/fs/CheckFile.cxx
+++ b/src/fs/CheckFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/CheckFile.hxx b/src/fs/CheckFile.hxx
index 00559647d..52fe45f0a 100644
--- a/src/fs/CheckFile.hxx
+++ b/src/fs/CheckFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Config.cxx b/src/fs/Config.cxx
index 6aa23005c..623736c54 100644
--- a/src/fs/Config.cxx
+++ b/src/fs/Config.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,21 +29,15 @@
#include <glib.h>
#endif
-void
-ConfigureFS()
+bool
+ConfigureFS(Error &error)
{
-#if defined(HAVE_GLIB) || defined(WIN32)
+#ifdef HAVE_FS_CHARSET
const char *charset = nullptr;
- charset = config_get_string(CONF_FS_CHARSET, nullptr);
+ charset = config_get_string(ConfigOption::FS_CHARSET, nullptr);
if (charset == nullptr) {
-#ifndef WIN32
- const gchar **encodings;
- g_get_filename_charsets(&encodings);
-
- if (encodings[0] != nullptr && *encodings[0] != '\0')
- charset = encodings[0];
-#else
+#ifdef WIN32
/* Glib claims that file system encoding is always utf-8
* on native Win32 (i.e. not Cygwin).
* However this is true only if <gstdio.h> helpers are used.
@@ -52,10 +46,26 @@ ConfigureFS()
static char win_charset[13];
sprintf(win_charset, "cp%u", GetACP());
charset = win_charset;
+#elif defined(HAVE_GLIB)
+ const gchar **encodings;
+ g_get_filename_charsets(&encodings);
+
+ if (encodings[0] != nullptr && *encodings[0] != '\0')
+ charset = encodings[0];
#endif
}
- if (charset != nullptr)
- SetFSCharset(charset);
+ return charset == nullptr || SetFSCharset(charset, error);
+#else
+ (void)error;
+ return true;
+#endif
+}
+
+void
+DeinitFS()
+{
+#ifdef HAVE_FS_CHARSET
+ DeinitFSCharset();
#endif
}
diff --git a/src/fs/Config.hxx b/src/fs/Config.hxx
index d4f1709f5..1db710551 100644
--- a/src/fs/Config.hxx
+++ b/src/fs/Config.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,10 +22,15 @@
#include "check.h"
+class Error;
+
/**
* Performs global one-time initialization of this class.
*/
+bool
+ConfigureFS(Error &error);
+
void
-ConfigureFS();
+DeinitFS();
#endif
diff --git a/src/fs/DirectoryReader.hxx b/src/fs/DirectoryReader.hxx
index f77c0629f..cd15952a1 100644
--- a/src/fs/DirectoryReader.hxx
+++ b/src/fs/DirectoryReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Domain.cxx b/src/fs/Domain.cxx
index 4f3129219..d278ba1bf 100644
--- a/src/fs/Domain.cxx
+++ b/src/fs/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Domain.hxx b/src/fs/Domain.hxx
index 1fd17b37f..77ca64549 100644
--- a/src/fs/Domain.hxx
+++ b/src/fs/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/FileSystem.cxx b/src/fs/FileSystem.cxx
index 4e7c87415..554915b61 100644
--- a/src/fs/FileSystem.cxx
+++ b/src/fs/FileSystem.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/FileSystem.hxx b/src/fs/FileSystem.hxx
index 4dbb064cb..fd88ba572 100644
--- a/src/fs/FileSystem.hxx
+++ b/src/fs/FileSystem.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Limits.hxx b/src/fs/Limits.hxx
index 432897a69..b574a9c9a 100644
--- a/src/fs/Limits.hxx
+++ b/src/fs/Limits.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx
index 8288a4fec..5a21b698f 100644
--- a/src/fs/Path.cxx
+++ b/src/fs/Path.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx
index 9e0fa5aeb..f9cc9839b 100644
--- a/src/fs/Path.hxx
+++ b/src/fs/Path.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,8 @@
#include <assert.h>
#include <string.h>
+class AllocatedPath;
+
/**
* A path name in the native file system character set.
*
@@ -129,6 +131,22 @@ public:
std::string ToUTF8() const;
/**
+ * Determine the "base" file name.
+ * The return value points inside this object.
+ */
+ gcc_pure
+ Path GetBase() const {
+ return FromFS(PathTraitsFS::GetBase(value));
+ }
+
+ /**
+ * Gets directory name of this path.
+ * Returns a "nulled" instance on error.
+ */
+ gcc_pure
+ AllocatedPath GetDirectoryName() const;
+
+ /**
* Determine the relative part of the given path to this
* object, not including the directory separator. Returns an
* empty string if the given path equals this object or
diff --git a/src/fs/Path2.cxx b/src/fs/Path2.cxx
new file mode 100644
index 000000000..b85909f79
--- /dev/null
+++ b/src/fs/Path2.cxx
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Path.hxx"
+#include "AllocatedPath.hxx"
+
+AllocatedPath
+Path::GetDirectoryName() const
+{
+ return AllocatedPath::FromFS(PathTraitsFS::GetParent(c_str()));
+}
diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx
index 7a836f906..1fc76ce9f 100644
--- a/src/fs/StandardDirectory.cxx
+++ b/src/fs/StandardDirectory.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/StandardDirectory.hxx b/src/fs/StandardDirectory.hxx
index e3fba375a..d453d109d 100644
--- a/src/fs/StandardDirectory.hxx
+++ b/src/fs/StandardDirectory.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Traits.cxx b/src/fs/Traits.cxx
index 166b31f4e..4c8d7012c 100644
--- a/src/fs/Traits.cxx
+++ b/src/fs/Traits.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx
index 1af8f8672..1b5e1e6f8 100644
--- a/src/fs/Traits.hxx
+++ b/src/fs/Traits.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/AutoGunzipReader.cxx b/src/fs/io/AutoGunzipReader.cxx
index 2552f7b99..b6d30dfd7 100644
--- a/src/fs/io/AutoGunzipReader.cxx
+++ b/src/fs/io/AutoGunzipReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/AutoGunzipReader.hxx b/src/fs/io/AutoGunzipReader.hxx
index 9f031e0f5..29a794aed 100644
--- a/src/fs/io/AutoGunzipReader.hxx
+++ b/src/fs/io/AutoGunzipReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/BufferedOutputStream.cxx b/src/fs/io/BufferedOutputStream.cxx
index 088a3e279..7d3cd3815 100644
--- a/src/fs/io/BufferedOutputStream.cxx
+++ b/src/fs/io/BufferedOutputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/BufferedOutputStream.hxx b/src/fs/io/BufferedOutputStream.hxx
index f2de758a2..9be4c125a 100644
--- a/src/fs/io/BufferedOutputStream.hxx
+++ b/src/fs/io/BufferedOutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/BufferedReader.cxx b/src/fs/io/BufferedReader.cxx
index ba2f17dcf..9a296d815 100644
--- a/src/fs/io/BufferedReader.cxx
+++ b/src/fs/io/BufferedReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -59,8 +59,10 @@ BufferedReader::ReadLine()
{
do {
char *line = ReadBufferedLine(buffer);
- if (line != nullptr)
+ if (line != nullptr) {
+ ++line_number;
return line;
+ }
} while (Fill(true));
if (last_error.IsDefined() || !eof || buffer.IsEmpty())
@@ -78,5 +80,6 @@ BufferedReader::ReadLine()
char *line = buffer.Read().data;
buffer.Clear();
+ ++line_number;
return line;
}
diff --git a/src/fs/io/BufferedReader.hxx b/src/fs/io/BufferedReader.hxx
index 61cc8df83..a0c42d23c 100644
--- a/src/fs/io/BufferedReader.hxx
+++ b/src/fs/io/BufferedReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,9 +41,12 @@ class BufferedReader {
bool eof;
+ unsigned line_number;
+
public:
BufferedReader(Reader &_reader)
- :reader(_reader), buffer(4096), eof(false) {}
+ :reader(_reader), buffer(4096), eof(false),
+ line_number(0) {}
gcc_pure
bool Check() const {
@@ -70,6 +73,10 @@ public:
}
char *ReadLine();
+
+ unsigned GetLineNumber() const {
+ return line_number;
+ }
};
#endif
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index dc4456d1f..11b5b2351 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,9 +20,20 @@
#include "config.h"
#include "FileOutputStream.hxx"
#include "fs/FileSystem.hxx"
-#include "system/fd_util.h"
#include "util/Error.hxx"
+FileOutputStream *
+FileOutputStream::Create(Path path, Error &error)
+{
+ FileOutputStream *f = new FileOutputStream(path, error);
+ if (!f->IsDefined()) {
+ delete f;
+ f = nullptr;
+ }
+
+ return f;
+}
+
#ifdef WIN32
FileOutputStream::FileOutputStream(Path _path, Error &error)
@@ -80,14 +91,47 @@ FileOutputStream::Cancel()
#include <unistd.h>
#include <errno.h>
+#ifdef HAVE_LINKAT
+#ifndef O_TMPFILE
+/* supported since Linux 3.11 */
+#define __O_TMPFILE 020000000
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#include <stdio.h>
+#endif
+
+/**
+ * Open a file using Linux's O_TMPFILE for writing the given file.
+ */
+static int
+OpenTempFile(Path path)
+{
+ const auto directory = path.GetDirectoryName();
+ if (directory.IsNull())
+ return -1;
+
+ return OpenFile(directory, O_TMPFILE|O_WRONLY, 0666);
+}
+
+#endif /* HAVE_LINKAT */
+
FileOutputStream::FileOutputStream(Path _path, Error &error)
- :path(_path),
- fd(open_cloexec(path.c_str(),
- O_WRONLY|O_CREAT|O_TRUNC,
- 0666))
+ :path(_path)
{
- if (fd < 0)
- error.FormatErrno("Failed to create %s", path.c_str());
+#ifdef HAVE_LINKAT
+ /* try Linux's O_TMPFILE first */
+ fd = OpenTempFile(path);
+ is_tmpfile = fd >= 0;
+ if (!is_tmpfile) {
+#endif
+ /* fall back to plain POSIX */
+ fd = OpenFile(path,
+ O_WRONLY|O_CREAT|O_TRUNC,
+ 0666);
+ if (fd < 0)
+ error.FormatErrno("Failed to create %s", path.c_str());
+#ifdef HAVE_LINKAT
+ }
+#endif
}
bool
@@ -113,6 +157,22 @@ FileOutputStream::Commit(Error &error)
{
assert(IsDefined());
+#if HAVE_LINKAT
+ if (is_tmpfile) {
+ RemoveFile(path);
+
+ /* hard-link the temporary file to the final path */
+ char fd_path[64];
+ snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", fd);
+ if (linkat(AT_FDCWD, fd_path, AT_FDCWD, path.c_str(),
+ AT_SYMLINK_FOLLOW) < 0) {
+ error.FormatErrno("Failed to commit %s", path.c_str());
+ close(fd);
+ return false;
+ }
+ }
+#endif
+
bool success = close(fd) == 0;
fd = -1;
if (!success)
@@ -129,7 +189,10 @@ FileOutputStream::Cancel()
close(fd);
fd = -1;
- RemoveFile(path);
+#ifdef HAVE_LINKAT
+ if (!is_tmpfile)
+#endif
+ RemoveFile(path);
}
#endif
diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index 5b6309957..f66554ec9 100644
--- a/src/fs/io/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -42,6 +42,14 @@ class FileOutputStream final : public OutputStream {
int fd;
#endif
+#ifdef HAVE_LINKAT
+ /**
+ * Was O_TMPFILE used? If yes, then linkat() must be used to
+ * create a link to this file.
+ */
+ bool is_tmpfile;
+#endif
+
public:
FileOutputStream(Path _path, Error &error);
@@ -50,6 +58,7 @@ public:
Cancel();
}
+ static FileOutputStream *Create(Path path, Error &error);
bool IsDefined() const {
#ifdef WIN32
diff --git a/src/fs/io/FileReader.cxx b/src/fs/io/FileReader.cxx
index d63cd8ab0..01ffe95f2 100644
--- a/src/fs/io/FileReader.cxx
+++ b/src/fs/io/FileReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,7 @@
#include "config.h"
#include "FileReader.hxx"
-#include "system/fd_util.h"
+#include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#ifdef WIN32
@@ -64,9 +64,9 @@ FileReader::Close()
FileReader::FileReader(Path _path, Error &error)
:path(_path),
- fd(open_cloexec(path.c_str(),
- O_RDONLY,
- 0))
+ fd(OpenFile(path,
+ O_RDONLY,
+ 0))
{
if (fd < 0)
error.FormatErrno("Failed to open %s", path.c_str());
diff --git a/src/fs/io/FileReader.hxx b/src/fs/io/FileReader.hxx
index 9f459aee2..96054d936 100644
--- a/src/fs/io/FileReader.hxx
+++ b/src/fs/io/FileReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/GunzipReader.cxx b/src/fs/io/GunzipReader.cxx
index ad5e41784..78f5b2c69 100644
--- a/src/fs/io/GunzipReader.cxx
+++ b/src/fs/io/GunzipReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/GunzipReader.hxx b/src/fs/io/GunzipReader.hxx
index 06c44bad6..381d1af5e 100644
--- a/src/fs/io/GunzipReader.hxx
+++ b/src/fs/io/GunzipReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/GzipOutputStream.cxx b/src/fs/io/GzipOutputStream.cxx
index 27ae6b2ad..d2a693b87 100644
--- a/src/fs/io/GzipOutputStream.cxx
+++ b/src/fs/io/GzipOutputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/GzipOutputStream.hxx b/src/fs/io/GzipOutputStream.hxx
index 27ee2dd24..fdab7bca4 100644
--- a/src/fs/io/GzipOutputStream.hxx
+++ b/src/fs/io/GzipOutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/OutputStream.hxx b/src/fs/io/OutputStream.hxx
index 71311c71f..f7d101180 100644
--- a/src/fs/io/OutputStream.hxx
+++ b/src/fs/io/OutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/PeekReader.cxx b/src/fs/io/PeekReader.cxx
index 2e8042ab6..ec9520a37 100644
--- a/src/fs/io/PeekReader.cxx
+++ b/src/fs/io/PeekReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/PeekReader.hxx b/src/fs/io/PeekReader.hxx
index 32180b0a8..c00ed66be 100644
--- a/src/fs/io/PeekReader.hxx
+++ b/src/fs/io/PeekReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/Reader.hxx b/src/fs/io/Reader.hxx
index d41e92dd0..657f96ac2 100644
--- a/src/fs/io/Reader.hxx
+++ b/src/fs/io/Reader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/StdioOutputStream.hxx b/src/fs/io/StdioOutputStream.hxx
index c1c0a00bd..88dbe6f00 100644
--- a/src/fs/io/StdioOutputStream.hxx
+++ b/src/fs/io/StdioOutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/fs/io/TextFile.cxx b/src/fs/io/TextFile.cxx
index 28d6dabcb..9866da08a 100644
--- a/src/fs/io/TextFile.cxx
+++ b/src/fs/io/TextFile.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,14 +28,14 @@
TextFile::TextFile(Path path_fs, Error &error)
:file_reader(new FileReader(path_fs, error)),
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
gunzip_reader(file_reader->IsDefined()
? new AutoGunzipReader(*file_reader)
: nullptr),
#endif
buffered_reader(file_reader->IsDefined()
? new BufferedReader(*
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
gunzip_reader
#else
file_reader
@@ -48,7 +48,7 @@ TextFile::TextFile(Path path_fs, Error &error)
TextFile::~TextFile()
{
delete buffered_reader;
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
delete gunzip_reader;
#endif
delete file_reader;
diff --git a/src/fs/io/TextFile.hxx b/src/fs/io/TextFile.hxx
index 5577363e7..b116565d6 100644
--- a/src/fs/io/TextFile.hxx
+++ b/src/fs/io/TextFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@ class BufferedReader;
class TextFile {
FileReader *const file_reader;
-#ifdef HAVE_ZLIB
+#ifdef ENABLE_ZLIB
AutoGunzipReader *const gunzip_reader;
#endif
diff --git a/src/input/AsyncInputStream.cxx b/src/input/AsyncInputStream.cxx
index 5795ecead..68cb8ff68 100644
--- a/src/input/AsyncInputStream.cxx
+++ b/src/input/AsyncInputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx
index d1f0c3b9d..64f566a97 100644
--- a/src/input/AsyncInputStream.hxx
+++ b/src/input/AsyncInputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -62,6 +62,10 @@ protected:
Error postponed_error;
public:
+ /**
+ * @param _buffer a buffer allocated with HugeAllocate(); the
+ * destructor will free it using HugeFree()
+ */
AsyncInputStream(const char *_url,
Mutex &_mutex, Cond &_cond,
void *_buffer, size_t _buffer_size,
diff --git a/src/input/Domain.cxx b/src/input/Domain.cxx
index 26ae298a4..12417af34 100644
--- a/src/input/Domain.cxx
+++ b/src/input/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/Domain.hxx b/src/input/Domain.hxx
index 16fa5e0f1..a18a26426 100644
--- a/src/input/Domain.hxx
+++ b/src/input/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/IcyInputStream.cxx b/src/input/IcyInputStream.cxx
index fb82cdec6..5344a71ec 100644
--- a/src/input/IcyInputStream.cxx
+++ b/src/input/IcyInputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/IcyInputStream.hxx b/src/input/IcyInputStream.hxx
index d8968a741..4fca11eb3 100644
--- a/src/input/IcyInputStream.hxx
+++ b/src/input/IcyInputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/Init.cxx b/src/input/Init.cxx
index 0ee87c4d8..4ed44f100 100644
--- a/src/input/Init.cxx
+++ b/src/input/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
#include "util/Error.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "Log.hxx"
#include <assert.h>
@@ -33,7 +33,7 @@
bool
input_stream_global_init(Error &error)
{
- const config_param empty;
+ const ConfigBlock empty;
for (unsigned i = 0; input_plugins[i] != nullptr; ++i) {
const InputPlugin *plugin = input_plugins[i];
@@ -42,16 +42,17 @@ input_stream_global_init(Error &error)
assert(*plugin->name != 0);
assert(plugin->open != nullptr);
- const struct config_param *param =
- config_find_block(CONF_INPUT, "plugin", plugin->name);
- if (param == nullptr) {
- param = &empty;
- } else if (!param->GetBlockValue("enabled", true))
+ const auto *block =
+ config_find_block(ConfigBlockOption::INPUT, "plugin",
+ plugin->name);
+ if (block == nullptr) {
+ block = &empty;
+ } else if (!block->GetBlockValue("enabled", true))
/* the plugin is disabled in mpd.conf */
continue;
InputPlugin::InitResult result = plugin->init != nullptr
- ? plugin->init(*param, error)
+ ? plugin->init(*block, error)
: InputPlugin::InitResult::SUCCESS;
switch (result) {
diff --git a/src/input/Init.hxx b/src/input/Init.hxx
index 875fdce7c..b19bc112f 100644
--- a/src/input/Init.hxx
+++ b/src/input/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/InputPlugin.hxx b/src/input/InputPlugin.hxx
index c2adb419c..9e83c2a5f 100644
--- a/src/input/InputPlugin.hxx
+++ b/src/input/InputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#endif
#endif
-struct config_param;
+struct ConfigBlock;
class InputStream;
class Error;
struct Tag;
@@ -69,7 +69,7 @@ struct InputPlugin {
* @return true on success, false if the plugin should be
* disabled
*/
- InitResult (*init)(const config_param &param, Error &error);
+ InitResult (*init)(const ConfigBlock &block, Error &error);
/**
* Global deinitialization. Called once before MPD shuts
diff --git a/src/input/InputStream.cxx b/src/input/InputStream.cxx
index 44f726a62..419c4f07f 100644
--- a/src/input/InputStream.cxx
+++ b/src/input/InputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/InputStream.hxx b/src/input/InputStream.hxx
index 81b903ba2..98bc93035 100644
--- a/src/input/InputStream.hxx
+++ b/src/input/InputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/LocalOpen.cxx b/src/input/LocalOpen.cxx
index ad8eba8ce..25644bae1 100644
--- a/src/input/LocalOpen.cxx
+++ b/src/input/LocalOpen.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/LocalOpen.hxx b/src/input/LocalOpen.hxx
index cf1b2b632..6f4ef2a2c 100644
--- a/src/input/LocalOpen.hxx
+++ b/src/input/LocalOpen.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/Offset.hxx b/src/input/Offset.hxx
index 552397904..fbda933ba 100644
--- a/src/input/Offset.hxx
+++ b/src/input/Offset.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/Open.cxx b/src/input/Open.cxx
index 66ccdce74..d3c9b7530 100644
--- a/src/input/Open.cxx
+++ b/src/input/Open.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/ProxyInputStream.cxx b/src/input/ProxyInputStream.cxx
index 74a272f6a..013d880d8 100644
--- a/src/input/ProxyInputStream.cxx
+++ b/src/input/ProxyInputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/ProxyInputStream.hxx b/src/input/ProxyInputStream.hxx
index 727ae5917..c91c1a952 100644
--- a/src/input/ProxyInputStream.hxx
+++ b/src/input/ProxyInputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/Registry.cxx b/src/input/Registry.cxx
index 748c18ca8..e33e51bb9 100644
--- a/src/input/Registry.cxx
+++ b/src/input/Registry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
#include "util/Macros.hxx"
#include "plugins/FileInputPlugin.hxx"
-#ifdef HAVE_ALSA
+#ifdef ENABLE_ALSA
#include "plugins/AlsaInputPlugin.hxx"
#endif
@@ -34,7 +34,7 @@
#include "plugins/CurlInputPlugin.hxx"
#endif
-#ifdef HAVE_FFMPEG
+#ifdef ENABLE_FFMPEG
#include "plugins/FfmpegInputPlugin.hxx"
#endif
@@ -56,7 +56,7 @@
const InputPlugin *const input_plugins[] = {
&input_plugin_file,
-#ifdef HAVE_ALSA
+#ifdef ENABLE_ALSA
&input_plugin_alsa,
#endif
#ifdef ENABLE_ARCHIVE
@@ -65,7 +65,7 @@ const InputPlugin *const input_plugins[] = {
#ifdef ENABLE_CURL
&input_plugin_curl,
#endif
-#ifdef HAVE_FFMPEG
+#ifdef ENABLE_FFMPEG
&input_plugin_ffmpeg,
#endif
#ifdef ENABLE_SMBCLIENT
diff --git a/src/input/Registry.hxx b/src/input/Registry.hxx
index 1b81f8f06..af1b3be8b 100644
--- a/src/input/Registry.hxx
+++ b/src/input/Registry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/TextInputStream.cxx b/src/input/TextInputStream.cxx
index 5a8dcc065..897b2b472 100644
--- a/src/input/TextInputStream.cxx
+++ b/src/input/TextInputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/TextInputStream.hxx b/src/input/TextInputStream.hxx
index 6f39d22cf..6b3a18d0b 100644
--- a/src/input/TextInputStream.hxx
+++ b/src/input/TextInputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/ThreadInputStream.cxx b/src/input/ThreadInputStream.cxx
index 235ed2b01..061d5cbfe 100644
--- a/src/input/ThreadInputStream.cxx
+++ b/src/input/ThreadInputStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/ThreadInputStream.hxx b/src/input/ThreadInputStream.hxx
index c6ac7669c..6fc3e2e7b 100644
--- a/src/input/ThreadInputStream.hxx
+++ b/src/input/ThreadInputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx
index f03f745c6..d2be734b5 100644
--- a/src/input/plugins/AlsaInputPlugin.cxx
+++ b/src/input/plugins/AlsaInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/AlsaInputPlugin.hxx b/src/input/plugins/AlsaInputPlugin.hxx
index dddf7dfd7..eb50ec8d6 100644
--- a/src/input/plugins/AlsaInputPlugin.hxx
+++ b/src/input/plugins/AlsaInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/ArchiveInputPlugin.cxx b/src/input/plugins/ArchiveInputPlugin.cxx
index da3d7ca71..b6472e00a 100644
--- a/src/input/plugins/ArchiveInputPlugin.cxx
+++ b/src/input/plugins/ArchiveInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/ArchiveInputPlugin.hxx b/src/input/plugins/ArchiveInputPlugin.hxx
index b6158684a..79331cd5a 100644
--- a/src/input/plugins/ArchiveInputPlugin.hxx
+++ b/src/input/plugins/ArchiveInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx
index f847b35c1..dda5cb83f 100644
--- a/src/input/plugins/CdioParanoiaInputPlugin.cxx
+++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
#include "system/ByteOrder.hxx"
#include "fs/AllocatedPath.hxx"
#include "Log.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "config/ConfigError.hxx"
#include <stdio.h>
@@ -39,7 +39,6 @@
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
-#include <glib.h>
#include <assert.h>
#ifdef HAVE_CDIO_PARANOIA_PARANOIA_H
@@ -107,9 +106,9 @@ static constexpr Domain cdio_domain("cdio");
static bool default_reverse_endian;
static InputPlugin::InitResult
-input_cdio_init(const config_param &param, Error &error)
+input_cdio_init(const ConfigBlock &block, Error &error)
{
- const char *value = param.GetBlockValue("default_byte_order");
+ const char *value = block.GetBlockValue("default_byte_order");
if (value != nullptr) {
if (strcmp(value, "little_endian") == 0)
default_reverse_endian = IsBigEndian();
@@ -149,7 +148,7 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, Error &error)
const char *slash = strrchr(src, '/');
if (slash == nullptr) {
/* play the whole CD in the specified drive */
- g_strlcpy(dest->device, src, sizeof(dest->device));
+ CopyString(dest->device, src, sizeof(dest->device));
dest->track = -1;
return true;
}
diff --git a/src/input/plugins/CdioParanoiaInputPlugin.hxx b/src/input/plugins/CdioParanoiaInputPlugin.hxx
index e2804e8c7..a51b43827 100644
--- a/src/input/plugins/CdioParanoiaInputPlugin.hxx
+++ b/src/input/plugins/CdioParanoiaInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx
index abb7e312c..fb5845b2b 100644
--- a/src/input/plugins/CurlInputPlugin.cxx
+++ b/src/input/plugins/CurlInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,7 +23,7 @@
#include "../IcyInputStream.hxx"
#include "../InputPlugin.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "tag/Tag.hxx"
#include "tag/TagBuilder.hxx"
#include "event/SocketMonitor.hxx"
@@ -535,7 +535,7 @@ CurlMulti::OnTimeout()
*/
static InputPlugin::InitResult
-input_curl_init(const config_param &param, Error &error)
+input_curl_init(const ConfigBlock &block, Error &error)
{
CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
if (code != CURLE_OK) {
@@ -557,22 +557,22 @@ input_curl_init(const config_param &param, Error &error)
http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK");
- proxy = param.GetBlockValue("proxy");
- proxy_port = param.GetBlockValue("proxy_port", 0u);
- proxy_user = param.GetBlockValue("proxy_user");
- proxy_password = param.GetBlockValue("proxy_password");
+ proxy = block.GetBlockValue("proxy");
+ proxy_port = block.GetBlockValue("proxy_port", 0u);
+ proxy_user = block.GetBlockValue("proxy_user");
+ proxy_password = block.GetBlockValue("proxy_password");
if (proxy == nullptr) {
/* deprecated proxy configuration */
- proxy = config_get_string(CONF_HTTP_PROXY_HOST, nullptr);
- proxy_port = config_get_positive(CONF_HTTP_PROXY_PORT, 0);
- proxy_user = config_get_string(CONF_HTTP_PROXY_USER, nullptr);
- proxy_password = config_get_string(CONF_HTTP_PROXY_PASSWORD,
+ proxy = config_get_string(ConfigOption::HTTP_PROXY_HOST, nullptr);
+ proxy_port = config_get_positive(ConfigOption::HTTP_PROXY_PORT, 0);
+ proxy_user = config_get_string(ConfigOption::HTTP_PROXY_USER, nullptr);
+ proxy_password = config_get_string(ConfigOption::HTTP_PROXY_PASSWORD,
"");
}
- verify_peer = param.GetBlockValue("verify_peer", true);
- verify_host = param.GetBlockValue("verify_host", true);
+ verify_peer = block.GetBlockValue("verify_peer", true);
+ verify_host = block.GetBlockValue("verify_host", true);
CURLM *multi = curl_multi_init();
if (multi == nullptr) {
@@ -649,7 +649,10 @@ CurlInputStream::HeaderReceived(const char *name, std::string &&value)
return;
size_t icy_metaint = ParseUint64(value.c_str());
+#ifndef WIN32
+ /* Windows doesn't know "%z" */
FormatDebug(curl_domain, "icy-metaint=%zu", icy_metaint);
+#endif
if (icy_metaint > 0) {
icy->Enable(icy_metaint);
diff --git a/src/input/plugins/CurlInputPlugin.hxx b/src/input/plugins/CurlInputPlugin.hxx
index 4acb18bfc..57bbe714b 100644
--- a/src/input/plugins/CurlInputPlugin.hxx
+++ b/src/input/plugins/CurlInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx
index 669f8d403..444273d90 100644
--- a/src/input/plugins/FfmpegInputPlugin.cxx
+++ b/src/input/plugins/FfmpegInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include "config.h"
#include "FfmpegInputPlugin.hxx"
+#include "lib/ffmpeg/Init.hxx"
#include "lib/ffmpeg/Domain.hxx"
#include "lib/ffmpeg/Error.hxx"
#include "../InputStream.hxx"
@@ -31,7 +32,6 @@
extern "C" {
#include <libavformat/avio.h>
-#include <libavformat/avformat.h>
}
struct FfmpegInputStream final : public InputStream {
@@ -72,10 +72,10 @@ input_ffmpeg_supported(void)
}
static InputPlugin::InitResult
-input_ffmpeg_init(gcc_unused const config_param &param,
+input_ffmpeg_init(gcc_unused const ConfigBlock &block,
Error &error)
{
- av_register_all();
+ FfmpegInit();
/* disable this plugin if there's no registered protocol */
if (!input_ffmpeg_supported()) {
diff --git a/src/input/plugins/FfmpegInputPlugin.hxx b/src/input/plugins/FfmpegInputPlugin.hxx
index 43f829e89..40a834bdc 100644
--- a/src/input/plugins/FfmpegInputPlugin.hxx
+++ b/src/input/plugins/FfmpegInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/FileInputPlugin.cxx b/src/input/plugins/FileInputPlugin.cxx
index 867b5722d..bfee71cce 100644
--- a/src/input/plugins/FileInputPlugin.cxx
+++ b/src/input/plugins/FileInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/FileInputPlugin.hxx b/src/input/plugins/FileInputPlugin.hxx
index ee194ec34..a00401c53 100644
--- a/src/input/plugins/FileInputPlugin.hxx
+++ b/src/input/plugins/FileInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/MmsInputPlugin.cxx b/src/input/plugins/MmsInputPlugin.cxx
index d01cff3b3..244dfd945 100644
--- a/src/input/plugins/MmsInputPlugin.cxx
+++ b/src/input/plugins/MmsInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/MmsInputPlugin.hxx b/src/input/plugins/MmsInputPlugin.hxx
index b4017ffd6..cf1b9ba65 100644
--- a/src/input/plugins/MmsInputPlugin.hxx
+++ b/src/input/plugins/MmsInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/NfsInputPlugin.cxx b/src/input/plugins/NfsInputPlugin.cxx
index c6c0970b9..077362c18 100644
--- a/src/input/plugins/NfsInputPlugin.cxx
+++ b/src/input/plugins/NfsInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,10 +28,6 @@
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
-extern "C" {
-#include <nfsc/libnfs.h>
-}
-
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -225,7 +221,7 @@ NfsInputStream::OnNfsFileError(Error &&error)
*/
static InputPlugin::InitResult
-input_nfs_init(const config_param &, Error &)
+input_nfs_init(const ConfigBlock &, Error &)
{
nfs_init();
return InputPlugin::InitResult::SUCCESS;
diff --git a/src/input/plugins/NfsInputPlugin.hxx b/src/input/plugins/NfsInputPlugin.hxx
index d2cc87549..5420ec967 100644
--- a/src/input/plugins/NfsInputPlugin.hxx
+++ b/src/input/plugins/NfsInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/RewindInputPlugin.cxx b/src/input/plugins/RewindInputPlugin.cxx
index 95f604044..cd027299c 100644
--- a/src/input/plugins/RewindInputPlugin.cxx
+++ b/src/input/plugins/RewindInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/RewindInputPlugin.hxx b/src/input/plugins/RewindInputPlugin.hxx
index 56b01b585..099921e7a 100644
--- a/src/input/plugins/RewindInputPlugin.hxx
+++ b/src/input/plugins/RewindInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx
index 79987180f..6aab556f2 100644
--- a/src/input/plugins/SmbclientInputPlugin.cxx
+++ b/src/input/plugins/SmbclientInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -66,14 +66,14 @@ public:
*/
static InputPlugin::InitResult
-input_smbclient_init(gcc_unused const config_param &param, Error &error)
+input_smbclient_init(gcc_unused const ConfigBlock &block, Error &error)
{
if (!SmbclientInit(error))
return InputPlugin::InitResult::UNAVAILABLE;
// TODO: create one global SMBCCTX here?
- // TODO: evaluate config_param, call smbc_setOption*()
+ // TODO: evaluate ConfigBlock, call smbc_setOption*()
return InputPlugin::InitResult::SUCCESS;
}
diff --git a/src/input/plugins/SmbclientInputPlugin.hxx b/src/input/plugins/SmbclientInputPlugin.hxx
index a0539d020..31c55196c 100644
--- a/src/input/plugins/SmbclientInputPlugin.hxx
+++ b/src/input/plugins/SmbclientInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/expat/ExpatParser.cxx b/src/lib/expat/ExpatParser.cxx
index c6b1abe76..7d9f1d587 100644
--- a/src/lib/expat/ExpatParser.cxx
+++ b/src/lib/expat/ExpatParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/expat/ExpatParser.hxx b/src/lib/expat/ExpatParser.hxx
index 9d2ac65e5..1ec7bfa02 100644
--- a/src/lib/expat/ExpatParser.hxx
+++ b/src/lib/expat/ExpatParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Buffer.hxx b/src/lib/ffmpeg/Buffer.hxx
new file mode 100644
index 000000000..fed5cb6e6
--- /dev/null
+++ b/src/lib/ffmpeg/Buffer.hxx
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_BUFFER_HXX
+#define MPD_FFMPEG_BUFFER_HXX
+
+extern "C" {
+#include <libavutil/mem.h>
+
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0)
+#define HAVE_AV_FAST_MALLOC
+#else
+#include <libavcodec/avcodec.h>
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0)
+#define HAVE_AV_FAST_MALLOC
+#endif
+#endif
+}
+
+#include <stddef.h>
+
+/* suppress the ffmpeg compatibility macro */
+#ifdef SampleFormat
+#undef SampleFormat
+#endif
+
+class FfmpegBuffer {
+ void *data;
+ unsigned size;
+
+public:
+ FfmpegBuffer():data(nullptr), size(0) {}
+
+ ~FfmpegBuffer() {
+ av_free(data);
+ }
+
+ void *Get(size_t min_size) {
+#ifdef HAVE_AV_FAST_MALLOC
+ av_fast_malloc(&data, &size, min_size);
+#else
+ void *new_data = av_fast_realloc(data, &size, min_size);
+ if (new_data == nullptr)
+ return AVERROR(ENOMEM);
+ data = new_data;
+#endif
+ return data;
+ }
+
+ template<typename T>
+ T *GetT(size_t n) {
+ return (T *)Get(n * sizeof(T));
+ }
+};
+
+#endif
diff --git a/src/lib/ffmpeg/Domain.cxx b/src/lib/ffmpeg/Domain.cxx
index 78db30bae..08b3c6b43 100644
--- a/src/lib/ffmpeg/Domain.cxx
+++ b/src/lib/ffmpeg/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Domain.hxx b/src/lib/ffmpeg/Domain.hxx
index f21498a32..c6d82f800 100644
--- a/src/lib/ffmpeg/Domain.hxx
+++ b/src/lib/ffmpeg/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Error.cxx b/src/lib/ffmpeg/Error.cxx
index bcc12fb1d..53f4d65f5 100644
--- a/src/lib/ffmpeg/Error.cxx
+++ b/src/lib/ffmpeg/Error.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Error.hxx b/src/lib/ffmpeg/Error.hxx
index 943dca6ce..a92394b2c 100644
--- a/src/lib/ffmpeg/Error.hxx
+++ b/src/lib/ffmpeg/Error.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Init.cxx b/src/lib/ffmpeg/Init.cxx
new file mode 100644
index 000000000..44c641f89
--- /dev/null
+++ b/src/lib/ffmpeg/Init.cxx
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "Init.hxx"
+#include "LogCallback.hxx"
+
+extern "C" {
+#include <libavformat/avformat.h>
+}
+
+void
+FfmpegInit()
+{
+ av_log_set_callback(FfmpegLogCallback);
+
+ av_register_all();
+}
+
diff --git a/src/lib/ffmpeg/Init.hxx b/src/lib/ffmpeg/Init.hxx
new file mode 100644
index 000000000..ca5f9d691
--- /dev/null
+++ b/src/lib/ffmpeg/Init.hxx
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_INIT_HXX
+#define MPD_FFMPEG_INIT_HXX
+
+void
+FfmpegInit();
+
+#endif
diff --git a/src/lib/ffmpeg/LogCallback.cxx b/src/lib/ffmpeg/LogCallback.cxx
new file mode 100644
index 000000000..ce2caeabb
--- /dev/null
+++ b/src/lib/ffmpeg/LogCallback.cxx
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "LogCallback.hxx"
+#include "Domain.hxx"
+#include "LogV.hxx"
+#include "util/Domain.hxx"
+
+extern "C" {
+#include <libavutil/log.h>
+}
+
+#include <stdio.h>
+
+gcc_const
+static LogLevel
+FfmpegImportLogLevel(int level)
+{
+ if (level <= AV_LOG_FATAL)
+ return LogLevel::ERROR;
+
+ if (level <= AV_LOG_WARNING)
+ return LogLevel::WARNING;
+
+ if (level <= AV_LOG_INFO)
+ return LogLevel::INFO;
+
+ return LogLevel::DEBUG;
+}
+
+void
+FfmpegLogCallback(gcc_unused void *ptr, int level, const char *fmt, va_list vl)
+{
+ const AVClass * cls = nullptr;
+
+ if (ptr != nullptr)
+ cls = *(const AVClass *const*)ptr;
+
+ if (cls != nullptr) {
+ char domain[64];
+ snprintf(domain, sizeof(domain), "%s/%s",
+ ffmpeg_domain.GetName(), cls->item_name(ptr));
+ const Domain d(domain);
+ LogFormatV(d, FfmpegImportLogLevel(level), fmt, vl);
+ }
+}
diff --git a/src/lib/ffmpeg/LogCallback.hxx b/src/lib/ffmpeg/LogCallback.hxx
new file mode 100644
index 000000000..f1b114366
--- /dev/null
+++ b/src/lib/ffmpeg/LogCallback.hxx
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_LOG_CALLBACK_HXX
+#define MPD_FFMPEG_LOG_CALLBACK_HXX
+
+#include "check.h"
+
+#include <stdarg.h>
+
+void
+FfmpegLogCallback(void *ptr, int level, const char *fmt, va_list vl);
+
+#endif
diff --git a/src/lib/ffmpeg/LogError.cxx b/src/lib/ffmpeg/LogError.cxx
new file mode 100644
index 000000000..8a0675a1c
--- /dev/null
+++ b/src/lib/ffmpeg/LogError.cxx
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "LogError.hxx"
+#include "Domain.hxx"
+#include "Log.hxx"
+
+#include <cstdint> /* needed due to libavutil bug */
+
+extern "C" {
+#include <libavutil/error.h>
+}
+
+void
+LogFfmpegError(int errnum)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ LogError(ffmpeg_domain, msg);
+}
+
+void
+LogFfmpegError(int errnum, const char *prefix)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ FormatError(ffmpeg_domain, "%s: %s", prefix, msg);
+}
diff --git a/src/lib/ffmpeg/LogError.hxx b/src/lib/ffmpeg/LogError.hxx
new file mode 100644
index 000000000..e6d96988d
--- /dev/null
+++ b/src/lib/ffmpeg/LogError.hxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_LOG_ERROR_HXX
+#define MPD_FFMPEG_LOG_ERROR_HXX
+
+void
+LogFfmpegError(int errnum);
+
+void
+LogFfmpegError(int errnum, const char *prefix);
+
+#endif
diff --git a/src/lib/ffmpeg/Time.hxx b/src/lib/ffmpeg/Time.hxx
new file mode 100644
index 000000000..92c076d0d
--- /dev/null
+++ b/src/lib/ffmpeg/Time.hxx
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_FFMPEG_TIME_HXX
+#define MPD_FFMPEG_TIME_HXX
+
+#include "Chrono.hxx"
+#include "Compiler.h"
+
+extern "C" {
+#include <libavutil/avutil.h>
+#include <libavutil/mathematics.h>
+}
+
+#include <assert.h>
+#include <stdint.h>
+
+/* suppress the ffmpeg compatibility macro */
+#ifdef SampleFormat
+#undef SampleFormat
+#endif
+
+/**
+ * Convert a FFmpeg time stamp to a floating point value (in seconds).
+ */
+gcc_const
+static inline double
+FfmpegTimeToDouble(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
+ / (double)1024;
+}
+
+/**
+ * Convert a std::ratio to a #AVRational.
+ */
+template<typename Ratio>
+static inline constexpr AVRational
+RatioToAVRational()
+{
+ return { Ratio::num, Ratio::den };
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SongTime.
+ */
+gcc_const
+static inline SongTime
+FromFfmpegTime(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return SongTime::FromMS(av_rescale_q(t, time_base,
+ (AVRational){1, 1000}));
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SignedSongTime.
+ */
+gcc_const
+static inline SignedSongTime
+FromFfmpegTimeChecked(int64_t t, const AVRational time_base)
+{
+ return t != (int64_t)AV_NOPTS_VALUE
+ ? SignedSongTime(FromFfmpegTime(t, time_base))
+ : SignedSongTime::Negative();
+}
+
+/**
+ * Convert a #SongTime to a FFmpeg time stamp with the given base.
+ */
+gcc_const
+static inline int64_t
+ToFfmpegTime(SongTime t, const AVRational time_base)
+{
+ return av_rescale_q(t.count(),
+ RatioToAVRational<SongTime::period>(),
+ time_base);
+}
+
+/**
+ * Replace #AV_NOPTS_VALUE with the given fallback.
+ */
+static constexpr int64_t
+FfmpegTimestampFallback(int64_t t, int64_t fallback)
+{
+ return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
+ ? t
+ : fallback;
+}
+
+#endif
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx
index 17b536b37..ddb6313d6 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/Collate.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#include "Collate.hxx"
#ifdef HAVE_ICU
+#include "Util.hxx"
#include "Error.hxx"
#include "util/WritableBuffer.hxx"
#include "util/ConstBuffer.hxx"
@@ -71,50 +72,6 @@ IcuCollateFinish()
ucol_close(collator);
}
-static WritableBuffer<UChar>
-UCharFromUTF8(const char *src)
-{
- assert(src != nullptr);
-
- const size_t src_length = strlen(src);
- const size_t dest_capacity = src_length;
- UChar *dest = new UChar[dest_capacity];
-
- UErrorCode error_code = U_ZERO_ERROR;
- int32_t dest_length;
- u_strFromUTF8(dest, dest_capacity, &dest_length,
- src, src_length,
- &error_code);
- if (U_FAILURE(error_code)) {
- delete[] dest;
- return nullptr;
- }
-
- return { dest, size_t(dest_length) };
-}
-
-static WritableBuffer<char>
-UCharToUTF8(ConstBuffer<UChar> src)
-{
- assert(!src.IsNull());
-
- /* worst-case estimate */
- size_t dest_capacity = 4 * src.size;
-
- char *dest = new char[dest_capacity];
-
- UErrorCode error_code = U_ZERO_ERROR;
- int32_t dest_length;
- u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size,
- &error_code);
- if (U_FAILURE(error_code)) {
- delete[] dest;
- return nullptr;
- }
-
- return { dest, size_t(dest_length) };
-}
-
#endif
gcc_pure
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx
index 8ae8de46a..9f8ea43ab 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/Collate.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Converter.cxx b/src/lib/icu/Converter.cxx
new file mode 100644
index 000000000..ea10a9a03
--- /dev/null
+++ b/src/lib/icu/Converter.cxx
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Converter.hxx"
+#include "Error.hxx"
+#include "util/Error.hxx"
+#include "util/Macros.hxx"
+#include "util/WritableBuffer.hxx"
+#include "util/ConstBuffer.hxx"
+
+#include <string.h>
+
+#ifdef HAVE_ICU
+#include "Util.hxx"
+#include <unicode/ucnv.h>
+#elif defined(HAVE_GLIB)
+#include "util/Domain.hxx"
+static constexpr Domain g_iconv_domain("g_iconv");
+#endif
+
+#ifdef HAVE_ICU
+
+IcuConverter::~IcuConverter()
+{
+ ucnv_close(converter);
+}
+
+#endif
+
+#ifdef HAVE_ICU_CONVERTER
+
+IcuConverter *
+IcuConverter::Create(const char *charset, Error &error)
+{
+#ifdef HAVE_ICU
+ UErrorCode code = U_ZERO_ERROR;
+ UConverter *converter = ucnv_open(charset, &code);
+ if (converter == nullptr) {
+ error.Format(icu_domain, int(code),
+ "Failed to initialize charset '%s': %s",
+ charset, u_errorName(code));
+ return nullptr;
+ }
+
+ return new IcuConverter(converter);
+#elif defined(HAVE_GLIB)
+ GIConv to = g_iconv_open("utf-8", charset);
+ GIConv from = g_iconv_open(charset, "utf-8");
+ if (to == (GIConv)-1 || from == (GIConv)-1) {
+ if (to != (GIConv)-1)
+ g_iconv_close(to);
+ if (from != (GIConv)-1)
+ g_iconv_close(from);
+ error.Format(g_iconv_domain,
+ "Failed to initialize charset '%s'", charset);
+ return nullptr;
+ }
+
+ return new IcuConverter(to, from);
+#endif
+}
+
+#ifdef HAVE_ICU
+#elif defined(HAVE_GLIB)
+
+static std::string
+DoConvert(GIConv conv, const char *src)
+{
+ // TODO: dynamic buffer?
+ char buffer[4096];
+ char *in = const_cast<char *>(src);
+ char *out = buffer;
+ size_t in_left = strlen(src);
+ size_t out_left = sizeof(buffer);
+
+ size_t n = g_iconv(conv, &in, &in_left, &out, &out_left);
+
+ if (n == static_cast<size_t>(-1) || in_left > 0)
+ return std::string();
+
+ return std::string(buffer, sizeof(buffer) - out_left);
+}
+
+#endif
+
+std::string
+IcuConverter::ToUTF8(const char *s) const
+{
+#ifdef HAVE_ICU
+ const ScopeLock protect(mutex);
+
+ ucnv_resetToUnicode(converter);
+
+ // TODO: dynamic buffer?
+ UChar buffer[4096], *target = buffer;
+ const char *source = s;
+
+ UErrorCode code = U_ZERO_ERROR;
+
+ ucnv_toUnicode(converter, &target, buffer + ARRAY_SIZE(buffer),
+ &source, source + strlen(source),
+ nullptr, true, &code);
+ if (code != U_ZERO_ERROR)
+ return std::string();
+
+ const size_t target_length = target - buffer;
+ const auto u = UCharToUTF8({buffer, target_length});
+ if (u.IsNull())
+ return std::string();
+
+ std::string result(u.data, u.size);
+ delete[] u.data;
+ return result;
+
+#elif defined(HAVE_GLIB)
+ return DoConvert(to_utf8, s);
+#endif
+}
+
+std::string
+IcuConverter::FromUTF8(const char *s) const
+{
+#ifdef HAVE_ICU
+ const ScopeLock protect(mutex);
+
+ const auto u = UCharFromUTF8(s);
+ if (u.IsNull())
+ return std::string();
+
+ ucnv_resetFromUnicode(converter);
+
+ // TODO: dynamic buffer?
+ char buffer[4096], *target = buffer;
+ const UChar *source = u.data;
+ UErrorCode code = U_ZERO_ERROR;
+
+ ucnv_fromUnicode(converter, &target, buffer + ARRAY_SIZE(buffer),
+ &source, u.end(),
+ nullptr, true, &code);
+ delete[] u.data;
+
+ if (code != U_ZERO_ERROR)
+ return std::string();
+
+ return std::string(buffer, target);
+
+#elif defined(HAVE_GLIB)
+ return DoConvert(from_utf8, s);
+#endif
+}
+
+#endif
diff --git a/src/lib/icu/Converter.hxx b/src/lib/icu/Converter.hxx
new file mode 100644
index 000000000..3eba86c25
--- /dev/null
+++ b/src/lib/icu/Converter.hxx
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_ICU_CONVERTER_HXX
+#define MPD_ICU_CONVERTER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#ifdef HAVE_ICU
+#include "thread/Mutex.hxx"
+#define HAVE_ICU_CONVERTER
+#elif defined(HAVE_GLIB)
+#include <glib.h>
+#define HAVE_ICU_CONVERTER
+#endif
+
+#ifdef HAVE_ICU_CONVERTER
+
+#include <string>
+
+class Error;
+
+#ifdef HAVE_ICU
+struct UConverter;
+#endif
+
+/**
+ * This class can convert strings with a certain character set to and
+ * from UTF-8.
+ */
+class IcuConverter {
+#ifdef HAVE_ICU
+ /**
+ * ICU's UConverter class is not thread-safe. This mutex
+ * serializes simultaneous calls.
+ */
+ mutable Mutex mutex;
+
+ UConverter *const converter;
+
+ IcuConverter(UConverter *_converter):converter(_converter) {}
+#elif defined(HAVE_GLIB)
+ const GIConv to_utf8, from_utf8;
+
+ IcuConverter(GIConv _to, GIConv _from)
+ :to_utf8(_to), from_utf8(_from) {}
+#endif
+
+public:
+#ifdef HAVE_ICU
+ ~IcuConverter();
+#elif defined(HAVE_GLIB)
+ ~IcuConverter() {
+ g_iconv_close(to_utf8);
+ g_iconv_close(from_utf8);
+ }
+#endif
+
+ static IcuConverter *Create(const char *charset, Error &error);
+
+ /**
+ * Convert the string to UTF-8.
+ * Returns empty string on error.
+ */
+ gcc_pure gcc_nonnull_all
+ std::string ToUTF8(const char *s) const;
+
+ /**
+ * Convert the string from UTF-8.
+ * Returns empty string on error.
+ */
+ gcc_pure gcc_nonnull_all
+ std::string FromUTF8(const char *s) const;
+};
+
+#endif
+
+#endif
diff --git a/src/lib/icu/Error.cxx b/src/lib/icu/Error.cxx
index 1fef078ac..f49ede352 100644
--- a/src/lib/icu/Error.cxx
+++ b/src/lib/icu/Error.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Error.hxx b/src/lib/icu/Error.hxx
index e96667f57..37cdb12fe 100644
--- a/src/lib/icu/Error.hxx
+++ b/src/lib/icu/Error.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Init.cxx b/src/lib/icu/Init.cxx
index 1d0ad0777..6b70d60ee 100644
--- a/src/lib/icu/Init.cxx
+++ b/src/lib/icu/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Init.hxx b/src/lib/icu/Init.hxx
index 9f585e2bd..402e7b957 100644
--- a/src/lib/icu/Init.hxx
+++ b/src/lib/icu/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Util.cxx b/src/lib/icu/Util.cxx
new file mode 100644
index 000000000..ae47423ad
--- /dev/null
+++ b/src/lib/icu/Util.cxx
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Util.hxx"
+#include "util/WritableBuffer.hxx"
+#include "util/ConstBuffer.hxx"
+
+#include <unicode/ustring.h>
+
+#include <assert.h>
+#include <string.h>
+
+WritableBuffer<UChar>
+UCharFromUTF8(const char *src)
+{
+ assert(src != nullptr);
+
+ const size_t src_length = strlen(src);
+ const size_t dest_capacity = src_length;
+ UChar *dest = new UChar[dest_capacity];
+
+ UErrorCode error_code = U_ZERO_ERROR;
+ int32_t dest_length;
+ u_strFromUTF8(dest, dest_capacity, &dest_length,
+ src, src_length,
+ &error_code);
+ if (U_FAILURE(error_code)) {
+ delete[] dest;
+ return nullptr;
+ }
+
+ return { dest, size_t(dest_length) };
+}
+
+WritableBuffer<char>
+UCharToUTF8(ConstBuffer<UChar> src)
+{
+ assert(!src.IsNull());
+
+ /* worst-case estimate */
+ size_t dest_capacity = 4 * src.size;
+
+ char *dest = new char[dest_capacity];
+
+ UErrorCode error_code = U_ZERO_ERROR;
+ int32_t dest_length;
+ u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size,
+ &error_code);
+ if (U_FAILURE(error_code)) {
+ delete[] dest;
+ return nullptr;
+ }
+
+ return { dest, size_t(dest_length) };
+}
diff --git a/src/lib/icu/Util.hxx b/src/lib/icu/Util.hxx
new file mode 100644
index 000000000..f26b72494
--- /dev/null
+++ b/src/lib/icu/Util.hxx
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_ICU_UTIL_HXX
+#define MPD_ICU_UTIL_HXX
+
+#include "check.h"
+
+#include <unicode/utypes.h>
+
+template<typename T> struct WritableBuffer;
+template<typename T> struct ConstBuffer;
+
+/**
+ * Wrapper for u_strFromUTF8(). The returned pointer must be freed
+ * with delete[].
+ */
+WritableBuffer<UChar>
+UCharFromUTF8(const char *src);
+
+/**
+ * Wrapper for u_strToUTF8(). The returned pointer must be freed with
+ * delete[].
+ */
+WritableBuffer<char>
+UCharToUTF8(ConstBuffer<UChar> src);
+
+#endif
diff --git a/src/lib/nfs/Base.cxx b/src/lib/nfs/Base.cxx
index 3004cd11b..588176ef6 100644
--- a/src/lib/nfs/Base.cxx
+++ b/src/lib/nfs/Base.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Base.hxx b/src/lib/nfs/Base.hxx
index 3a92a86d3..e007bfbd2 100644
--- a/src/lib/nfs/Base.hxx
+++ b/src/lib/nfs/Base.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Blocking.cxx b/src/lib/nfs/Blocking.cxx
index 58eaf6af2..7bccfa532 100644
--- a/src/lib/nfs/Blocking.cxx
+++ b/src/lib/nfs/Blocking.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Blocking.hxx b/src/lib/nfs/Blocking.hxx
index eb16dfb8c..47721363c 100644
--- a/src/lib/nfs/Blocking.hxx
+++ b/src/lib/nfs/Blocking.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Callback.hxx b/src/lib/nfs/Callback.hxx
index ae82ecc3c..849fbfbb9 100644
--- a/src/lib/nfs/Callback.hxx
+++ b/src/lib/nfs/Callback.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Cancellable.hxx b/src/lib/nfs/Cancellable.hxx
index 151be0528..6c207d9b2 100644
--- a/src/lib/nfs/Cancellable.hxx
+++ b/src/lib/nfs/Cancellable.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx
index 6e9f77345..3b3358be0 100644
--- a/src/lib/nfs/Connection.cxx
+++ b/src/lib/nfs/Connection.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Connection.hxx b/src/lib/nfs/Connection.hxx
index 3969a7e8f..3402116b7 100644
--- a/src/lib/nfs/Connection.hxx
+++ b/src/lib/nfs/Connection.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Domain.cxx b/src/lib/nfs/Domain.cxx
index fefe0dbf3..af79e45a8 100644
--- a/src/lib/nfs/Domain.cxx
+++ b/src/lib/nfs/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Domain.hxx b/src/lib/nfs/Domain.hxx
index 6730b92e1..15856657f 100644
--- a/src/lib/nfs/Domain.hxx
+++ b/src/lib/nfs/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx
index 1b80f2c86..97522321b 100644
--- a/src/lib/nfs/FileReader.cxx
+++ b/src/lib/nfs/FileReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx
index 1495a2832..5e3b5221f 100644
--- a/src/lib/nfs/FileReader.hxx
+++ b/src/lib/nfs/FileReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Glue.cxx b/src/lib/nfs/Glue.cxx
index 6e1e0f99b..fa894f59a 100644
--- a/src/lib/nfs/Glue.cxx
+++ b/src/lib/nfs/Glue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Glue.hxx b/src/lib/nfs/Glue.hxx
index 6da8957cb..d661b3fe0 100644
--- a/src/lib/nfs/Glue.hxx
+++ b/src/lib/nfs/Glue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Lease.hxx b/src/lib/nfs/Lease.hxx
index 6f88acf53..3276cfc31 100644
--- a/src/lib/nfs/Lease.hxx
+++ b/src/lib/nfs/Lease.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx
index 6d50cce18..8b0a9ba9a 100644
--- a/src/lib/nfs/Manager.cxx
+++ b/src/lib/nfs/Manager.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx
index 130c81aca..1eb01590a 100644
--- a/src/lib/nfs/Manager.hxx
+++ b/src/lib/nfs/Manager.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/pulse/Domain.cxx b/src/lib/pulse/Domain.cxx
new file mode 100644
index 000000000..ac4821cae
--- /dev/null
+++ b/src/lib/pulse/Domain.cxx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Domain.hxx"
+#include "util/Domain.hxx"
+
+const Domain pulse_domain("pulse");
diff --git a/src/lib/pulse/Domain.hxx b/src/lib/pulse/Domain.hxx
new file mode 100644
index 000000000..bacf8b7eb
--- /dev/null
+++ b/src/lib/pulse/Domain.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_PULSE_DOMAIN_HXX
+#define MPD_PULSE_DOMAIN_HXX
+
+class Domain;
+
+extern const Domain pulse_domain;
+
+#endif
diff --git a/src/lib/pulse/Error.cxx b/src/lib/pulse/Error.cxx
new file mode 100644
index 000000000..60ca0198a
--- /dev/null
+++ b/src/lib/pulse/Error.cxx
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Error.hxx"
+#include "Domain.hxx"
+#include "util/Error.hxx"
+
+#include <pulse/context.h>
+#include <pulse/error.h>
+
+void
+SetPulseError(Error &error, pa_context *context, const char *prefix)
+{
+ const int e = pa_context_errno(context);
+ error.Format(pulse_domain, e, "%s: %s", prefix, pa_strerror(e));
+}
diff --git a/src/lib/pulse/Error.hxx b/src/lib/pulse/Error.hxx
new file mode 100644
index 000000000..c9225a7c2
--- /dev/null
+++ b/src/lib/pulse/Error.hxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_PULSE_ERROR_HXX
+#define MPD_PULSE_ERROR_HXX
+
+class Error;
+struct pa_context;
+
+void
+SetPulseError(Error &error, pa_context *context, const char *prefix);
+
+#endif
diff --git a/src/lib/pulse/LogError.cxx b/src/lib/pulse/LogError.cxx
new file mode 100644
index 000000000..a322e7e75
--- /dev/null
+++ b/src/lib/pulse/LogError.cxx
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "LogError.hxx"
+#include "Domain.hxx"
+#include "Log.hxx"
+
+#include <pulse/context.h>
+#include <pulse/error.h>
+
+void
+LogPulseError(pa_context *context, const char *prefix)
+{
+ const int e = pa_context_errno(context);
+ FormatError(pulse_domain, "%s: %s", prefix, pa_strerror(e));
+}
diff --git a/src/lib/pulse/LogError.hxx b/src/lib/pulse/LogError.hxx
new file mode 100644
index 000000000..2e0859366
--- /dev/null
+++ b/src/lib/pulse/LogError.hxx
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_PULSE_LOG_ERROR_HXX
+#define MPD_PULSE_LOG_ERROR_HXX
+
+struct pa_context;
+
+void
+LogPulseError(pa_context *context, const char *prefix);
+
+#endif
diff --git a/src/lib/smbclient/Domain.cxx b/src/lib/smbclient/Domain.cxx
index 00f5ee6c1..c6f6b143d 100644
--- a/src/lib/smbclient/Domain.cxx
+++ b/src/lib/smbclient/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Domain.hxx b/src/lib/smbclient/Domain.hxx
index 3b21c4e60..dc9812fed 100644
--- a/src/lib/smbclient/Domain.hxx
+++ b/src/lib/smbclient/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Init.cxx b/src/lib/smbclient/Init.cxx
index a7f2da4dd..999e60fcd 100644
--- a/src/lib/smbclient/Init.cxx
+++ b/src/lib/smbclient/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Init.hxx b/src/lib/smbclient/Init.hxx
index 21014ec8d..1ccaec033 100644
--- a/src/lib/smbclient/Init.hxx
+++ b/src/lib/smbclient/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Mutex.cxx b/src/lib/smbclient/Mutex.cxx
index 4dfc5a9d3..fd78e9948 100644
--- a/src/lib/smbclient/Mutex.cxx
+++ b/src/lib/smbclient/Mutex.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Mutex.hxx b/src/lib/smbclient/Mutex.hxx
index dc7372e6e..893f6204d 100644
--- a/src/lib/smbclient/Mutex.hxx
+++ b/src/lib/smbclient/Mutex.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/sqlite/Domain.cxx b/src/lib/sqlite/Domain.cxx
new file mode 100644
index 000000000..4f6fe4c45
--- /dev/null
+++ b/src/lib/sqlite/Domain.cxx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Domain.hxx"
+#include "util/Domain.hxx"
+
+const Domain sqlite_domain("sqlite");
diff --git a/src/lib/sqlite/Domain.hxx b/src/lib/sqlite/Domain.hxx
new file mode 100644
index 000000000..0b9965025
--- /dev/null
+++ b/src/lib/sqlite/Domain.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_SQLITE_DOMAIN_HXX
+#define MPD_SQLITE_DOMAIN_HXX
+
+class Domain;
+
+extern const Domain sqlite_domain;
+
+#endif
diff --git a/src/lib/sqlite/Util.hxx b/src/lib/sqlite/Util.hxx
new file mode 100644
index 000000000..151eac6c2
--- /dev/null
+++ b/src/lib/sqlite/Util.hxx
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_SQLITE_UTIL_HXX
+#define MPD_SQLITE_UTIL_HXX
+
+#include "Domain.hxx"
+#include "util/Error.hxx"
+
+#include <sqlite3.h>
+
+#include <assert.h>
+
+static void
+SetError(Error &error, sqlite3 *db, int code, const char *msg)
+{
+ error.Format(sqlite_domain, code, "%s: %s",
+ msg, sqlite3_errmsg(db));
+}
+
+static void
+SetError(Error &error, sqlite3_stmt *stmt, int code, const char *msg)
+{
+ SetError(error, sqlite3_db_handle(stmt), code, msg);
+}
+
+static bool
+Bind(sqlite3_stmt *stmt, unsigned i, const char *value, Error &error)
+{
+ int result = sqlite3_bind_text(stmt, i, value, -1, nullptr);
+ if (result != SQLITE_OK) {
+ SetError(error, stmt, result, "sqlite3_bind_text() failed");
+ return false;
+ }
+
+ return true;
+}
+
+template<typename... Args>
+static bool
+BindAll2(gcc_unused Error &error, gcc_unused sqlite3_stmt *stmt,
+ gcc_unused unsigned i)
+{
+ assert(int(i - 1) == sqlite3_bind_parameter_count(stmt));
+
+ return true;
+}
+
+template<typename... Args>
+static bool
+BindAll2(Error &error, sqlite3_stmt *stmt, unsigned i,
+ const char *value, Args&&... args)
+{
+ return Bind(stmt, i, value, error) &&
+ BindAll2(error, stmt, i + 1, std::forward<Args>(args)...);
+}
+
+template<typename... Args>
+static bool
+BindAll(Error &error, sqlite3_stmt *stmt, Args&&... args)
+{
+ assert(int(sizeof...(args)) == sqlite3_bind_parameter_count(stmt));
+
+ return BindAll2(error, stmt, 1, std::forward<Args>(args)...);
+}
+
+/**
+ * Wrapper for BindAll() that returns the specified sqlite3_stmt* on
+ * success and nullptr on error.
+ */
+template<typename... Args>
+static sqlite3_stmt *
+BindAllOrNull(Error &error, sqlite3_stmt *stmt, Args&&... args)
+{
+ return BindAll(error, stmt, std::forward<Args>(args)...)
+ ? stmt
+ : nullptr;
+}
+
+/**
+ * Call sqlite3_stmt() repepatedly until something other than
+ * SQLITE_BUSY is returned.
+ */
+static int
+ExecuteBusy(sqlite3_stmt *stmt)
+{
+ int result;
+ do {
+ result = sqlite3_step(stmt);
+ } while (result == SQLITE_BUSY);
+
+ return result;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that returns true on SQLITE_ROW.
+ */
+static bool
+ExecuteRow(sqlite3_stmt *stmt, Error &error)
+{
+ int result = ExecuteBusy(stmt);
+ if (result == SQLITE_ROW)
+ return true;
+
+ if (result != SQLITE_DONE)
+ SetError(error, stmt, result, "sqlite3_step() failed");
+
+ return false;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that interprets everything other than
+ * SQLITE_DONE as error.
+ */
+static bool
+ExecuteCommand(sqlite3_stmt *stmt, Error &error)
+{
+ int result = ExecuteBusy(stmt);
+ if (result != SQLITE_DONE) {
+ SetError(error, stmt, result, "sqlite3_step() failed");
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Wrapper for ExecuteCommand() that returns the number of rows
+ * modified via sqlite3_changes(). Returns -1 on error.
+ */
+static inline int
+ExecuteChanges(sqlite3_stmt *stmt, Error &error)
+{
+ if (!ExecuteCommand(stmt, error))
+ return -1;
+
+ return sqlite3_changes(sqlite3_db_handle(stmt));
+}
+
+/**
+ * Wrapper for ExecuteChanges() that returns true if at least one row
+ * was modified. Returns false if nothing was modified or if an error
+ * occurred.
+ */
+static inline bool
+ExecuteModified(sqlite3_stmt *stmt, Error &error)
+{
+ return ExecuteChanges(stmt, error) > 0;
+}
+
+template<typename F>
+static inline bool
+ExecuteForEach(sqlite3_stmt *stmt, Error &error, F &&f)
+{
+ while (true) {
+ int result = ExecuteBusy(stmt);
+ switch (result) {
+ case SQLITE_ROW:
+ f();
+ break;
+
+ case SQLITE_DONE:
+ return true;
+
+ default:
+ SetError(error, stmt, result, "sqlite3_step() failed");
+ return false;
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/upnp/Action.hxx b/src/lib/upnp/Action.hxx
index 28c88be92..bad398e1a 100644
--- a/src/lib/upnp/Action.hxx
+++ b/src/lib/upnp/Action.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Callback.hxx b/src/lib/upnp/Callback.hxx
index 85daf0a7e..4d86c0b53 100644
--- a/src/lib/upnp/Callback.hxx
+++ b/src/lib/upnp/Callback.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ClientInit.cxx b/src/lib/upnp/ClientInit.cxx
index 77d9cf03d..50fcbdb16 100644
--- a/src/lib/upnp/ClientInit.cxx
+++ b/src/lib/upnp/ClientInit.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ClientInit.hxx b/src/lib/upnp/ClientInit.hxx
index 645e64ca6..f49f255ee 100644
--- a/src/lib/upnp/ClientInit.hxx
+++ b/src/lib/upnp/ClientInit.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ContentDirectoryService.cxx b/src/lib/upnp/ContentDirectoryService.cxx
index 0e5d2d955..0636505ab 100644
--- a/src/lib/upnp/ContentDirectoryService.cxx
+++ b/src/lib/upnp/ContentDirectoryService.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ContentDirectoryService.hxx b/src/lib/upnp/ContentDirectoryService.hxx
index 0b03df2e7..576c6ec8c 100644
--- a/src/lib/upnp/ContentDirectoryService.hxx
+++ b/src/lib/upnp/ContentDirectoryService.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Device.cxx b/src/lib/upnp/Device.cxx
index 26bffd0f0..402a39166 100644
--- a/src/lib/upnp/Device.cxx
+++ b/src/lib/upnp/Device.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Device.hxx b/src/lib/upnp/Device.hxx
index dd7ecac2d..cdb065434 100644
--- a/src/lib/upnp/Device.hxx
+++ b/src/lib/upnp/Device.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Discovery.cxx b/src/lib/upnp/Discovery.cxx
index 1539e1512..8759278ce 100644
--- a/src/lib/upnp/Discovery.cxx
+++ b/src/lib/upnp/Discovery.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Discovery.hxx b/src/lib/upnp/Discovery.hxx
index 767811840..4f947f67a 100644
--- a/src/lib/upnp/Discovery.hxx
+++ b/src/lib/upnp/Discovery.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Domain.cxx b/src/lib/upnp/Domain.cxx
index 010d4c7c2..d7700a067 100644
--- a/src/lib/upnp/Domain.cxx
+++ b/src/lib/upnp/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Domain.hxx b/src/lib/upnp/Domain.hxx
index ec01ef735..ff0cd9b85 100644
--- a/src/lib/upnp/Domain.hxx
+++ b/src/lib/upnp/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Init.cxx b/src/lib/upnp/Init.cxx
index 4fc606de9..1b471f53d 100644
--- a/src/lib/upnp/Init.cxx
+++ b/src/lib/upnp/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Init.hxx b/src/lib/upnp/Init.hxx
index b23f8e2ab..796251862 100644
--- a/src/lib/upnp/Init.hxx
+++ b/src/lib/upnp/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Util.cxx b/src/lib/upnp/Util.cxx
index 79cfb111c..912d993b4 100644
--- a/src/lib/upnp/Util.cxx
+++ b/src/lib/upnp/Util.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Util.hxx b/src/lib/upnp/Util.hxx
index a59f23521..d3b0b049f 100644
--- a/src/lib/upnp/Util.hxx
+++ b/src/lib/upnp/Util.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/WorkQueue.hxx b/src/lib/upnp/WorkQueue.hxx
index fe8ce53f9..90de44529 100644
--- a/src/lib/upnp/WorkQueue.hxx
+++ b/src/lib/upnp/WorkQueue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/zlib/Domain.cxx b/src/lib/zlib/Domain.cxx
index 96aad1350..b94076053 100644
--- a/src/lib/zlib/Domain.cxx
+++ b/src/lib/zlib/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/zlib/Domain.hxx b/src/lib/zlib/Domain.hxx
index 653ac0209..9f0b9c5b0 100644
--- a/src/lib/zlib/Domain.hxx
+++ b/src/lib/zlib/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/ls.cxx b/src/ls.cxx
index 6ab68b6ab..0287f5137 100644
--- a/src/ls.cxx
+++ b/src/ls.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,7 @@
* is detected at runtime and displayed as a urlhandler if the client is
* connected by IPC socket.
*/
-static const char *remoteUrlPrefixes[] = {
+static const char *const remoteUrlPrefixes[] = {
#if defined(ENABLE_CURL)
"http://",
"https://",
@@ -41,7 +41,7 @@ static const char *remoteUrlPrefixes[] = {
"mmst://",
"mmsu://",
#endif
-#ifdef HAVE_FFMPEG
+#ifdef ENABLE_FFMPEG
"gopher://",
"rtp://",
"rtsp://",
@@ -58,7 +58,7 @@ static const char *remoteUrlPrefixes[] = {
#ifdef ENABLE_CDIO_PARANOIA
"cdda://",
#endif
-#ifdef HAVE_ALSA
+#ifdef ENABLE_ALSA
"alsa://",
#endif
NULL
@@ -66,7 +66,7 @@ static const char *remoteUrlPrefixes[] = {
void print_supported_uri_schemes_to_fp(FILE *fp)
{
- const char **prefixes = remoteUrlPrefixes;
+ const char *const*prefixes = remoteUrlPrefixes;
#ifdef HAVE_UN
fprintf(fp, " file://");
@@ -80,7 +80,7 @@ void print_supported_uri_schemes_to_fp(FILE *fp)
void print_supported_uri_schemes(Client &client)
{
- const char **prefixes = remoteUrlPrefixes;
+ const char *const *prefixes = remoteUrlPrefixes;
while (*prefixes) {
client_printf(client, "handler: %s\n", *prefixes);
@@ -90,7 +90,7 @@ void print_supported_uri_schemes(Client &client)
bool uri_supported_scheme(const char *uri)
{
- const char **urlPrefixes = remoteUrlPrefixes;
+ const char *const*urlPrefixes = remoteUrlPrefixes;
assert(uri_has_scheme(uri));
diff --git a/src/ls.hxx b/src/ls.hxx
index f4b9be967..27843a657 100644
--- a/src/ls.hxx
+++ b/src/ls.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/Listener.hxx b/src/mixer/Listener.hxx
index 6f48fbd4d..c65934dd8 100644
--- a/src/mixer/Listener.hxx
+++ b/src/mixer/Listener.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/MixerAll.cxx b/src/mixer/MixerAll.cxx
index 5fef6a92f..f652a9a95 100644
--- a/src/mixer/MixerAll.cxx
+++ b/src/mixer/MixerAll.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -149,7 +149,8 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume)
const auto mixer = ao->mixer;
if (mixer != nullptr &&
- &mixer->plugin == &software_mixer_plugin)
+ (&mixer->plugin == &software_mixer_plugin ||
+ &mixer->plugin == &null_mixer_plugin))
mixer_set_volume(mixer, volume, IgnoreError());
}
}
diff --git a/src/mixer/MixerControl.cxx b/src/mixer/MixerControl.cxx
index 6d08140db..9de7809ec 100644
--- a/src/mixer/MixerControl.cxx
+++ b/src/mixer/MixerControl.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,10 +28,10 @@ Mixer *
mixer_new(EventLoop &event_loop,
const MixerPlugin &plugin, AudioOutput &ao,
MixerListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error)
{
- Mixer *mixer = plugin.init(event_loop, ao, listener, param, error);
+ Mixer *mixer = plugin.init(event_loop, ao, listener, block, error);
assert(mixer == nullptr || mixer->IsPlugin(plugin));
diff --git a/src/mixer/MixerControl.hxx b/src/mixer/MixerControl.hxx
index 75255d98c..6401544dd 100644
--- a/src/mixer/MixerControl.hxx
+++ b/src/mixer/MixerControl.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -31,12 +31,12 @@ class EventLoop;
struct AudioOutput;
struct MixerPlugin;
class MixerListener;
-struct config_param;
+struct ConfigBlock;
Mixer *
mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao,
MixerListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
void
diff --git a/src/mixer/MixerInternal.hxx b/src/mixer/MixerInternal.hxx
index 7b2cf2b32..02e06d85d 100644
--- a/src/mixer/MixerInternal.hxx
+++ b/src/mixer/MixerInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/MixerList.hxx b/src/mixer/MixerList.hxx
index e75b2e6ff..070008400 100644
--- a/src/mixer/MixerList.hxx
+++ b/src/mixer/MixerList.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
struct MixerPlugin;
+extern const MixerPlugin null_mixer_plugin;
extern const MixerPlugin software_mixer_plugin;
extern const MixerPlugin alsa_mixer_plugin;
extern const MixerPlugin oss_mixer_plugin;
diff --git a/src/mixer/MixerPlugin.hxx b/src/mixer/MixerPlugin.hxx
index 02bae844e..a40b4bb95 100644
--- a/src/mixer/MixerPlugin.hxx
+++ b/src/mixer/MixerPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@
#ifndef MPD_MIXER_PLUGIN_HXX
#define MPD_MIXER_PLUGIN_HXX
-struct config_param;
+struct ConfigBlock;
struct AudioOutput;
class Mixer;
class MixerListener;
@@ -46,7 +46,7 @@ struct MixerPlugin {
*/
Mixer *(*init)(EventLoop &event_loop, AudioOutput &ao,
MixerListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
/**
diff --git a/src/mixer/MixerType.cxx b/src/mixer/MixerType.cxx
index cd45db0d9..23ca3f08a 100644
--- a/src/mixer/MixerType.cxx
+++ b/src/mixer/MixerType.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,17 +23,19 @@
#include <assert.h>
#include <string.h>
-enum mixer_type
+MixerType
mixer_type_parse(const char *input)
{
assert(input != NULL);
if (strcmp(input, "none") == 0 || strcmp(input, "disabled") == 0)
- return MIXER_TYPE_NONE;
+ return MixerType::NONE;
else if (strcmp(input, "hardware") == 0)
- return MIXER_TYPE_HARDWARE;
+ return MixerType::HARDWARE;
else if (strcmp(input, "software") == 0)
- return MIXER_TYPE_SOFTWARE;
+ return MixerType::SOFTWARE;
+ else if (strcmp(input, "null") == 0)
+ return MixerType::NULL_;
else
- return MIXER_TYPE_UNKNOWN;
+ return MixerType::UNKNOWN;
}
diff --git a/src/mixer/MixerType.hxx b/src/mixer/MixerType.hxx
index bfa2637b7..86037787f 100644
--- a/src/mixer/MixerType.hxx
+++ b/src/mixer/MixerType.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,28 +20,31 @@
#ifndef MPD_MIXER_TYPE_HXX
#define MPD_MIXER_TYPE_HXX
-enum mixer_type {
+enum class MixerType {
/** parser error */
- MIXER_TYPE_UNKNOWN,
+ UNKNOWN,
/** mixer disabled */
- MIXER_TYPE_NONE,
+ NONE,
+
+ /** "null" mixer (virtual fake) */
+ NULL_,
/** software mixer with pcm_volume() */
- MIXER_TYPE_SOFTWARE,
+ SOFTWARE,
/** hardware mixer (output's plugin) */
- MIXER_TYPE_HARDWARE,
+ HARDWARE,
};
/**
- * Parses a "mixer_type" setting from the configuration file.
+ * Parses a #MixerType setting from the configuration file.
*
- * @param input the configured string value; must not be NULL
- * @return a #mixer_type value; MIXER_TYPE_UNKNOWN means #input could
- * not be parsed
+ * @param input the configured string value; must not be NULL @return
+ * a #MixerType value; #MixerType::UNKNOWN means #input could not be
+ * parsed
*/
-enum mixer_type
+MixerType
mixer_type_parse(const char *input);
#endif
diff --git a/src/mixer/Volume.cxx b/src/mixer/Volume.cxx
index abb01fb40..8bc8d879d 100644
--- a/src/mixer/Volume.cxx
+++ b/src/mixer/Volume.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/Volume.hxx b/src/mixer/Volume.hxx
index d787a6415..d5f3f09b1 100644
--- a/src/mixer/Volume.hxx
+++ b/src/mixer/Volume.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx
index cd787182a..2b89f24e1 100644
--- a/src/mixer/plugins/AlsaMixerPlugin.cxx
+++ b/src/mixer/plugins/AlsaMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -82,7 +82,7 @@ public:
virtual ~AlsaMixer();
- void Configure(const config_param &param);
+ void Configure(const ConfigBlock &block);
bool Setup(Error &error);
/* virtual methods from class Mixer */
@@ -162,24 +162,24 @@ alsa_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned mask)
*/
inline void
-AlsaMixer::Configure(const config_param &param)
+AlsaMixer::Configure(const ConfigBlock &block)
{
- device = param.GetBlockValue("mixer_device",
+ device = block.GetBlockValue("mixer_device",
VOLUME_MIXER_ALSA_DEFAULT);
- control = param.GetBlockValue("mixer_control",
+ control = block.GetBlockValue("mixer_control",
VOLUME_MIXER_ALSA_CONTROL_DEFAULT);
- index = param.GetBlockValue("mixer_index",
+ index = block.GetBlockValue("mixer_index",
VOLUME_MIXER_ALSA_INDEX_DEFAULT);
}
static Mixer *
alsa_mixer_init(EventLoop &event_loop, gcc_unused AudioOutput &ao,
MixerListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
gcc_unused Error &error)
{
AlsaMixer *am = new AlsaMixer(event_loop, listener);
- am->Configure(param);
+ am->Configure(block);
return am;
}
diff --git a/src/mixer/plugins/NullMixerPlugin.cxx b/src/mixer/plugins/NullMixerPlugin.cxx
new file mode 100644
index 000000000..d846a6be1
--- /dev/null
+++ b/src/mixer/plugins/NullMixerPlugin.cxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "mixer/MixerInternal.hxx"
+
+class NullMixer final : public Mixer {
+ /**
+ * The current volume in percent (0..100).
+ */
+ unsigned volume;
+
+public:
+ NullMixer(MixerListener &_listener)
+ :Mixer(null_mixer_plugin, _listener),
+ volume(100)
+ {
+ }
+
+ /* virtual methods from class Mixer */
+ bool Open(gcc_unused Error &error) override {
+ return true;
+ }
+
+ void Close() override {
+ }
+
+ int GetVolume(gcc_unused Error &error) override {
+ return volume;
+ }
+
+ bool SetVolume(unsigned _volume, gcc_unused Error &error) override {
+ volume = _volume;
+ return true;
+ }
+};
+
+static Mixer *
+null_mixer_init(gcc_unused EventLoop &event_loop,
+ gcc_unused AudioOutput &ao,
+ MixerListener &listener,
+ gcc_unused const ConfigBlock &block,
+ gcc_unused Error &error)
+{
+ return new NullMixer(listener);
+}
+
+const MixerPlugin null_mixer_plugin = {
+ null_mixer_init,
+ true,
+};
diff --git a/src/mixer/plugins/OssMixerPlugin.cxx b/src/mixer/plugins/OssMixerPlugin.cxx
index 6615c7022..ae198492c 100644
--- a/src/mixer/plugins/OssMixerPlugin.cxx
+++ b/src/mixer/plugins/OssMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,7 @@
#include "config.h"
#include "mixer/MixerInternal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "system/fd_util.h"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
@@ -52,7 +52,7 @@ public:
OssMixer(MixerListener &_listener)
:Mixer(oss_mixer_plugin, _listener) {}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
/* virtual methods from class Mixer */
virtual bool Open(Error &error) override;
@@ -79,10 +79,10 @@ oss_find_mixer(const char *name)
}
inline bool
-OssMixer::Configure(const config_param &param, Error &error)
+OssMixer::Configure(const ConfigBlock &block, Error &error)
{
- device = param.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT);
- control = param.GetBlockValue("mixer_control");
+ device = block.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT);
+ control = block.GetBlockValue("mixer_control");
if (control != NULL) {
volume_control = oss_find_mixer(control);
@@ -100,12 +100,12 @@ OssMixer::Configure(const config_param &param, Error &error)
static Mixer *
oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao,
MixerListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error)
{
OssMixer *om = new OssMixer(listener);
- if (!om->Configure(param, error)) {
+ if (!om->Configure(block, error)) {
delete om;
return nullptr;
}
diff --git a/src/mixer/plugins/PulseMixerPlugin.cxx b/src/mixer/plugins/PulseMixerPlugin.cxx
index c5f20723b..f2b17a75a 100644
--- a/src/mixer/plugins/PulseMixerPlugin.cxx
+++ b/src/mixer/plugins/PulseMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,18 +19,18 @@
#include "config.h"
#include "PulseMixerPlugin.hxx"
+#include "lib/pulse/Domain.hxx"
+#include "lib/pulse/LogError.hxx"
#include "mixer/MixerInternal.hxx"
#include "mixer/Listener.hxx"
#include "output/plugins/PulseOutputPlugin.hxx"
#include "util/Error.hxx"
-#include "util/Domain.hxx"
#include "Log.hxx"
#include <pulse/context.h>
#include <pulse/introspect.h>
#include <pulse/stream.h>
#include <pulse/subscribe.h>
-#include <pulse/error.h>
#include <assert.h>
@@ -55,19 +55,17 @@ public:
int GetVolumeInternal(Error &error);
/* virtual methods from class Mixer */
- virtual bool Open(gcc_unused Error &error) override {
+ bool Open(gcc_unused Error &error) override {
return true;
}
- virtual void Close() override {
+ void Close() override {
}
- virtual int GetVolume(Error &error) override;
- virtual bool SetVolume(unsigned volume, Error &error) override;
+ int GetVolume(Error &error) override;
+ bool SetVolume(unsigned volume, Error &error) override;
};
-static constexpr Domain pulse_mixer_domain("pulse_mixer");
-
void
PulseMixer::Offline()
{
@@ -120,9 +118,8 @@ PulseMixer::Update(pa_context *context, pa_stream *stream)
pa_stream_get_index(stream),
pulse_mixer_volume_cb, this);
if (o == nullptr) {
- FormatError(pulse_mixer_domain,
- "pa_context_get_sink_input_info() failed: %s",
- pa_strerror(pa_context_errno(context)));
+ LogPulseError(context,
+ "pa_context_get_sink_input_info() failed");
Offline();
return;
}
@@ -142,9 +139,8 @@ pulse_mixer_on_connect(gcc_unused PulseMixer &pm,
(pa_subscription_mask_t)PA_SUBSCRIPTION_MASK_SINK_INPUT,
nullptr, nullptr);
if (o == nullptr) {
- FormatError(pulse_mixer_domain,
- "pa_context_subscribe() failed: %s",
- pa_strerror(pa_context_errno(context)));
+ LogPulseError(context,
+ "pa_context_subscribe() failed");
return;
}
@@ -167,7 +163,7 @@ pulse_mixer_on_change(PulseMixer &pm,
static Mixer *
pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
MixerListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
PulseOutput &po = (PulseOutput &)ao;
@@ -212,7 +208,7 @@ PulseMixer::SetVolume(unsigned new_volume, Error &error)
if (!online) {
pulse_output_unlock(output);
- error.Set(pulse_mixer_domain, "disconnected");
+ error.Set(pulse_domain, "disconnected");
return false;
}
diff --git a/src/mixer/plugins/PulseMixerPlugin.hxx b/src/mixer/plugins/PulseMixerPlugin.hxx
index 9b3a6daf1..64605ea8d 100644
--- a/src/mixer/plugins/PulseMixerPlugin.hxx
+++ b/src/mixer/plugins/PulseMixerPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/plugins/RoarMixerPlugin.cxx b/src/mixer/plugins/RoarMixerPlugin.cxx
index 8e198478d..9123762f2 100644
--- a/src/mixer/plugins/RoarMixerPlugin.cxx
+++ b/src/mixer/plugins/RoarMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft
* Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen
*
@@ -48,7 +48,7 @@ public:
static Mixer *
roar_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
MixerListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new RoarMixer((RoarOutput &)ao, listener);
diff --git a/src/mixer/plugins/SoftwareMixerPlugin.cxx b/src/mixer/plugins/SoftwareMixerPlugin.cxx
index f14766002..d35e7f469 100644
--- a/src/mixer/plugins/SoftwareMixerPlugin.cxx
+++ b/src/mixer/plugins/SoftwareMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,7 +25,7 @@
#include "filter/FilterInternal.hxx"
#include "filter/plugins/VolumeFilterPlugin.hxx"
#include "pcm/Volume.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "util/Error.hxx"
#include <assert.h>
@@ -34,7 +34,7 @@
static Filter *
CreateVolumeFilter()
{
- return filter_new(&volume_filter_plugin, config_param(),
+ return filter_new(&volume_filter_plugin, ConfigBlock(),
IgnoreError());
}
@@ -90,7 +90,7 @@ static Mixer *
software_mixer_init(gcc_unused EventLoop &event_loop,
gcc_unused AudioOutput &ao,
MixerListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new SoftwareMixer(listener);
diff --git a/src/mixer/plugins/SoftwareMixerPlugin.hxx b/src/mixer/plugins/SoftwareMixerPlugin.hxx
index 581d2ac17..f9be1d9d9 100644
--- a/src/mixer/plugins/SoftwareMixerPlugin.hxx
+++ b/src/mixer/plugins/SoftwareMixerPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/mixer/plugins/WinmmMixerPlugin.cxx b/src/mixer/plugins/WinmmMixerPlugin.cxx
index e0436011a..51d8092f9 100644
--- a/src/mixer/plugins/WinmmMixerPlugin.cxx
+++ b/src/mixer/plugins/WinmmMixerPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 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 @@ winmm_volume_encode(int volume)
static Mixer *
winmm_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
MixerListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new WinmmMixer((WinmmOutput &)ao, listener);
diff --git a/src/neighbor/Explorer.hxx b/src/neighbor/Explorer.hxx
index 84a54840c..abf426cd9 100644
--- a/src/neighbor/Explorer.hxx
+++ b/src/neighbor/Explorer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/Glue.cxx b/src/neighbor/Glue.cxx
index fbf25cc8d..4d5d7b4b0 100644
--- a/src/neighbor/Glue.cxx
+++ b/src/neighbor/Glue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,8 +24,8 @@
#include "NeighborPlugin.hxx"
#include "Info.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
#include "config/ConfigError.hxx"
+#include "config/Block.hxx"
#include "util/Error.hxx"
NeighborGlue::Explorer::~Explorer()
@@ -37,9 +37,9 @@ NeighborGlue::~NeighborGlue() {}
static NeighborExplorer *
CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener,
- const config_param &param, Error &error)
+ const ConfigBlock &block, Error &error)
{
- const char *plugin_name = param.GetBlockValue("plugin");
+ const char *plugin_name = block.GetBlockValue("plugin");
if (plugin_name == nullptr) {
error.Set(config_domain,
"Missing \"plugin\" configuration");
@@ -53,18 +53,18 @@ CreateNeighborExplorer(EventLoop &loop, NeighborListener &listener,
return nullptr;
}
- return plugin->create(loop, listener, param, error);
+ return plugin->create(loop, listener, block, error);
}
bool
NeighborGlue::Init(EventLoop &loop, NeighborListener &listener, Error &error)
{
- for (const config_param *param = config_get_param(CONF_NEIGHBORS);
- param != nullptr; param = param->next) {
+ for (const auto *block = config_get_block(ConfigBlockOption::NEIGHBORS);
+ block != nullptr; block = block->next) {
NeighborExplorer *explorer =
- CreateNeighborExplorer(loop, listener, *param, error);
+ CreateNeighborExplorer(loop, listener, *block, error);
if (explorer == nullptr) {
- error.FormatPrefix("Line %i: ", param->line);
+ error.FormatPrefix("Line %i: ", block->line);
return false;
}
diff --git a/src/neighbor/Glue.hxx b/src/neighbor/Glue.hxx
index 92c612d22..fc1778d05 100644
--- a/src/neighbor/Glue.hxx
+++ b/src/neighbor/Glue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/Info.hxx b/src/neighbor/Info.hxx
index ac4806f14..a9e629213 100644
--- a/src/neighbor/Info.hxx
+++ b/src/neighbor/Info.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/Listener.hxx b/src/neighbor/Listener.hxx
index 20295f5a9..dcf6cafff 100644
--- a/src/neighbor/Listener.hxx
+++ b/src/neighbor/Listener.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/NeighborPlugin.hxx b/src/neighbor/NeighborPlugin.hxx
index 0d4ebaa7b..116f47c50 100644
--- a/src/neighbor/NeighborPlugin.hxx
+++ b/src/neighbor/NeighborPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#ifndef MPD_NEIGHBOR_PLUGIN_HXX
#define MPD_NEIGHBOR_PLUGIN_HXX
-struct config_param;
+struct ConfigBlock;
class Error;
class EventLoop;
class NeighborListener;
@@ -33,7 +33,7 @@ struct NeighborPlugin {
* Allocates and configures a #NeighborExplorer instance.
*/
NeighborExplorer *(*create)(EventLoop &loop, NeighborListener &listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
};
diff --git a/src/neighbor/Registry.cxx b/src/neighbor/Registry.cxx
index f6d1f97b3..d58e3b974 100644
--- a/src/neighbor/Registry.cxx
+++ b/src/neighbor/Registry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@ const NeighborPlugin *const neighbor_plugins[] = {
#ifdef ENABLE_SMBCLIENT
&smbclient_neighbor_plugin,
#endif
-#ifdef HAVE_LIBUPNP
+#ifdef ENABLE_UPNP
&upnp_neighbor_plugin,
#endif
nullptr
diff --git a/src/neighbor/Registry.hxx b/src/neighbor/Registry.hxx
index 0b89e537d..59c9f1fb2 100644
--- a/src/neighbor/Registry.hxx
+++ b/src/neighbor/Registry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/plugins/SmbclientNeighborPlugin.cxx b/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
index 2701b0ccd..d4c73f9a8 100644
--- a/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
+++ b/src/neighbor/plugins/SmbclientNeighborPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -216,7 +216,7 @@ SmbclientNeighborExplorer::Run()
prev = i;
} else {
/* can't see it anymore: move to "lost" */
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
lost.splice_after(lost.before_begin(), list, prev);
#else
/* the forward_list::splice_after() lvalue
@@ -273,7 +273,7 @@ SmbclientNeighborExplorer::ThreadFunc(void *ctx)
static NeighborExplorer *
smbclient_neighbor_create(gcc_unused EventLoop &loop,
NeighborListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
if (!SmbclientInit(error))
diff --git a/src/neighbor/plugins/SmbclientNeighborPlugin.hxx b/src/neighbor/plugins/SmbclientNeighborPlugin.hxx
index 12ec9c0cd..be5560eee 100644
--- a/src/neighbor/plugins/SmbclientNeighborPlugin.hxx
+++ b/src/neighbor/plugins/SmbclientNeighborPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/neighbor/plugins/UpnpNeighborPlugin.cxx b/src/neighbor/plugins/UpnpNeighborPlugin.cxx
index 253e4c13b..28775df4c 100644
--- a/src/neighbor/plugins/UpnpNeighborPlugin.cxx
+++ b/src/neighbor/plugins/UpnpNeighborPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -127,7 +127,7 @@ UpnpNeighborExplorer::LostUPnP(const ContentDirectoryService &service)
static NeighborExplorer *
upnp_neighbor_create(gcc_unused EventLoop &loop,
NeighborListener &listener,
- gcc_unused const config_param &param,
+ gcc_unused const ConfigBlock &block,
gcc_unused Error &error)
{
return new UpnpNeighborExplorer(listener);
diff --git a/src/neighbor/plugins/UpnpNeighborPlugin.hxx b/src/neighbor/plugins/UpnpNeighborPlugin.hxx
index 78e4ccf13..abda3addd 100644
--- a/src/neighbor/plugins/UpnpNeighborPlugin.hxx
+++ b/src/neighbor/plugins/UpnpNeighborPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/notify.cxx b/src/notify.cxx
index 5b0b4baa0..06a4da611 100644
--- a/src/notify.cxx
+++ b/src/notify.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/notify.hxx b/src/notify.hxx
index 3e62a0103..c5a963e23 100644
--- a/src/notify.hxx
+++ b/src/notify.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/open.h b/src/open.h
index b05167188..71629f520 100644
--- a/src/open.h
+++ b/src/open.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Domain.cxx b/src/output/Domain.cxx
index 878e5f3c5..abfdb6a5e 100644
--- a/src/output/Domain.cxx
+++ b/src/output/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Domain.hxx b/src/output/Domain.hxx
index e3a20142f..136a2b8a9 100644
--- a/src/output/Domain.hxx
+++ b/src/output/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Finish.cxx b/src/output/Finish.cxx
index be2ca463e..2dd4acda5 100644
--- a/src/output/Finish.cxx
+++ b/src/output/Finish.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Init.cxx b/src/output/Init.cxx
index 79ef4f998..ae34bf846 100644
--- a/src/output/Init.cxx
+++ b/src/output/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,6 +35,7 @@
#include "filter/plugins/ChainFilterPlugin.hxx"
#include "config/ConfigError.hxx"
#include "config/ConfigGlobal.hxx"
+#include "config/Block.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
@@ -58,7 +59,7 @@ AudioOutput::AudioOutput(const AudioOutputPlugin &_plugin)
filter(nullptr),
replay_gain_filter(nullptr),
other_replay_gain_filter(nullptr),
- command(AO_COMMAND_NONE)
+ command(Command::NONE)
{
assert(plugin.finish != nullptr);
assert(plugin.open != nullptr);
@@ -94,27 +95,27 @@ audio_output_detect(Error &error)
* mixer_enabled, if the mixer_type setting is not configured.
*/
gcc_pure
-static enum mixer_type
-audio_output_mixer_type(const config_param &param)
+static MixerType
+audio_output_mixer_type(const ConfigBlock &block)
{
/* read the local "mixer_type" setting */
- const char *p = param.GetBlockValue("mixer_type");
+ const char *p = block.GetBlockValue("mixer_type");
if (p != nullptr)
return mixer_type_parse(p);
/* try the local "mixer_enabled" setting next (deprecated) */
- if (!param.GetBlockValue("mixer_enabled", true))
- return MIXER_TYPE_NONE;
+ if (!block.GetBlockValue("mixer_enabled", true))
+ return MixerType::NONE;
/* fall back to the global "mixer_type" setting (also
deprecated) */
- return mixer_type_parse(config_get_string(CONF_MIXER_TYPE,
+ return mixer_type_parse(config_get_string(ConfigOption::MIXER_TYPE,
"hardware"));
}
static Mixer *
audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
- const config_param &param,
+ const ConfigBlock &block,
const MixerPlugin *plugin,
Filter &filter_chain,
MixerListener &listener,
@@ -122,22 +123,26 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
{
Mixer *mixer;
- switch (audio_output_mixer_type(param)) {
- case MIXER_TYPE_NONE:
- case MIXER_TYPE_UNKNOWN:
+ switch (audio_output_mixer_type(block)) {
+ case MixerType::NONE:
+ case MixerType::UNKNOWN:
return nullptr;
- case MIXER_TYPE_HARDWARE:
+ case MixerType::NULL_:
+ return mixer_new(event_loop, null_mixer_plugin, ao, listener,
+ block, error);
+
+ case MixerType::HARDWARE:
if (plugin == nullptr)
return nullptr;
return mixer_new(event_loop, *plugin, ao, listener,
- param, error);
+ block, error);
- case MIXER_TYPE_SOFTWARE:
+ case MixerType::SOFTWARE:
mixer = mixer_new(event_loop, software_mixer_plugin, ao,
listener,
- config_param(),
+ ConfigBlock(),
IgnoreError());
assert(mixer != nullptr);
@@ -151,17 +156,17 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao,
}
bool
-AudioOutput::Configure(const config_param &param, Error &error)
+AudioOutput::Configure(const ConfigBlock &block, Error &error)
{
- if (!param.IsNull()) {
- name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
+ if (!block.IsNull()) {
+ name = block.GetBlockValue(AUDIO_OUTPUT_NAME);
if (name == nullptr) {
error.Set(config_domain,
"Missing \"name\" configuration");
return false;
}
- const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT);
+ const char *p = block.GetBlockValue(AUDIO_OUTPUT_FORMAT);
if (p != nullptr) {
bool success =
audio_format_parse(config_audio_format,
@@ -176,9 +181,9 @@ AudioOutput::Configure(const config_param &param, Error &error)
config_audio_format.Clear();
}
- tags = param.GetBlockValue("tags", true);
- always_on = param.GetBlockValue("always_on", false);
- enabled = param.GetBlockValue("enabled", true);
+ tags = block.GetBlockValue("tags", true);
+ always_on = block.GetBlockValue("always_on", false);
+ enabled = block.GetBlockValue("enabled", true);
/* set up the filter chain */
@@ -187,9 +192,9 @@ AudioOutput::Configure(const config_param &param, Error &error)
/* create the normalization filter (if configured) */
- if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) {
+ if (config_get_bool(ConfigOption::VOLUME_NORMALIZATION, false)) {
Filter *normalize_filter =
- filter_new(&normalize_filter_plugin, config_param(),
+ filter_new(&normalize_filter_plugin, ConfigBlock(),
IgnoreError());
assert(normalize_filter != nullptr);
@@ -199,7 +204,7 @@ AudioOutput::Configure(const config_param &param, Error &error)
Error filter_error;
filter_chain_parse(*filter,
- param.GetBlockValue(AUDIO_FILTERS, ""),
+ block.GetBlockValue(AUDIO_FILTERS, ""),
filter_error);
// It's not really fatal - Part of the filter chain has been set up already
@@ -217,24 +222,24 @@ AudioOutput::Configure(const config_param &param, Error &error)
static bool
audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
MixerListener &mixer_listener,
- const config_param &param,
+ const ConfigBlock &block,
Error &error)
{
/* create the replay_gain filter */
const char *replay_gain_handler =
- param.GetBlockValue("replay_gain_handler", "software");
+ block.GetBlockValue("replay_gain_handler", "software");
if (strcmp(replay_gain_handler, "none") != 0) {
ao.replay_gain_filter = filter_new(&replay_gain_filter_plugin,
- param, IgnoreError());
+ block, IgnoreError());
assert(ao.replay_gain_filter != nullptr);
ao.replay_gain_serial = 0;
ao.other_replay_gain_filter = filter_new(&replay_gain_filter_plugin,
- param,
+ block,
IgnoreError());
assert(ao.other_replay_gain_filter != nullptr);
@@ -247,7 +252,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
/* set up the mixer */
Error mixer_error;
- ao.mixer = audio_output_load_mixer(event_loop, ao, param,
+ ao.mixer = audio_output_load_mixer(event_loop, ao, block,
ao.plugin.mixer_plugin,
*ao.filter,
mixer_listener,
@@ -275,7 +280,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
/* the "convert" filter must be the last one in the chain */
- ao.convert_filter = filter_new(&convert_filter_plugin, config_param(),
+ ao.convert_filter = filter_new(&convert_filter_plugin, ConfigBlock(),
IgnoreError());
assert(ao.convert_filter != nullptr);
@@ -285,17 +290,17 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao,
}
AudioOutput *
-audio_output_new(EventLoop &event_loop, const config_param &param,
+audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
MixerListener &mixer_listener,
PlayerControl &pc,
Error &error)
{
const AudioOutputPlugin *plugin;
- if (!param.IsNull()) {
+ if (!block.IsNull()) {
const char *p;
- p = param.GetBlockValue(AUDIO_OUTPUT_TYPE);
+ p = block.GetBlockValue(AUDIO_OUTPUT_TYPE);
if (p == nullptr) {
error.Set(config_domain,
"Missing \"type\" configuration");
@@ -321,12 +326,12 @@ audio_output_new(EventLoop &event_loop, const config_param &param,
plugin->name);
}
- AudioOutput *ao = ao_plugin_init(plugin, param, error);
+ AudioOutput *ao = ao_plugin_init(plugin, block, error);
if (ao == nullptr)
return nullptr;
if (!audio_output_setup(event_loop, *ao, mixer_listener,
- param, error)) {
+ block, error)) {
ao_plugin_finish(ao);
return nullptr;
}
diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx
index 6e6ffb442..23b027c54 100644
--- a/src/output/Internal.hxx
+++ b/src/output/Internal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -36,36 +36,36 @@ class EventLoop;
class Mixer;
class MixerListener;
struct MusicChunk;
-struct config_param;
+struct ConfigBlock;
struct PlayerControl;
struct AudioOutputPlugin;
-enum audio_output_command {
- AO_COMMAND_NONE = 0,
- AO_COMMAND_ENABLE,
- AO_COMMAND_DISABLE,
- AO_COMMAND_OPEN,
+struct AudioOutput {
+ enum class Command {
+ NONE,
+ ENABLE,
+ DISABLE,
+ OPEN,
- /**
- * This command is invoked when the input audio format
- * changes.
- */
- AO_COMMAND_REOPEN,
+ /**
+ * This command is invoked when the input audio format
+ * changes.
+ */
+ REOPEN,
- AO_COMMAND_CLOSE,
- AO_COMMAND_PAUSE,
+ CLOSE,
+ PAUSE,
- /**
- * Drains the internal (hardware) buffers of the device. This
- * operation may take a while to complete.
- */
- AO_COMMAND_DRAIN,
+ /**
+ * Drains the internal (hardware) buffers of the device. This
+ * operation may take a while to complete.
+ */
+ DRAIN,
- AO_COMMAND_CANCEL,
- AO_COMMAND_KILL
-};
+ CANCEL,
+ KILL
+ };
-struct AudioOutput {
/**
* The device's configured display name.
*/
@@ -231,7 +231,7 @@ struct AudioOutput {
/**
* The next command to be performed by the output thread.
*/
- enum audio_output_command command;
+ Command command;
/**
* The music pipe which provides music chunks to be played.
@@ -272,7 +272,7 @@ struct AudioOutput {
AudioOutput(const AudioOutputPlugin &_plugin);
~AudioOutput();
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
void StartThread();
void StopThread();
@@ -284,7 +284,7 @@ struct AudioOutput {
}
bool IsCommandFinished() const {
- return command == AO_COMMAND_NONE;
+ return command == Command::NONE;
}
/**
@@ -299,7 +299,7 @@ struct AudioOutput {
*
* Caller must lock the mutex.
*/
- void CommandAsync(audio_output_command cmd);
+ void CommandAsync(Command cmd);
/**
* Sends a command to the #AudioOutput object and waits for
@@ -307,13 +307,13 @@ struct AudioOutput {
*
* Caller must lock the mutex.
*/
- void CommandWait(audio_output_command cmd);
+ void CommandWait(Command cmd);
/**
* Lock the #AudioOutput object and execute the command
* synchronously.
*/
- void LockCommandWait(audio_output_command cmd);
+ void LockCommandWait(Command cmd);
/**
* Enables the device.
@@ -430,7 +430,7 @@ private:
extern struct notify audio_output_client_notify;
AudioOutput *
-audio_output_new(EventLoop &event_loop, const config_param &param,
+audio_output_new(EventLoop &event_loop, const ConfigBlock &block,
MixerListener &mixer_listener,
PlayerControl &pc,
Error &error);
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index 33ab57894..a2260f19c 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@
#include "MusicChunk.hxx"
#include "system/FatalError.hxx"
#include "util/Error.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "notify.hxx"
@@ -53,16 +53,16 @@ MultipleOutputs::~MultipleOutputs()
static AudioOutput *
LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
- PlayerControl &pc, const config_param &param)
+ PlayerControl &pc, const ConfigBlock &block)
{
Error error;
- AudioOutput *output = audio_output_new(event_loop, param,
+ AudioOutput *output = audio_output_new(event_loop, block,
mixer_listener,
pc, error);
if (output == nullptr) {
- if (param.line > 0)
+ if (block.line > 0)
FormatFatalError("line %i: %s",
- param.line,
+ block.line,
error.GetMessage());
else
FatalError(error);
@@ -74,7 +74,7 @@ LoadOutput(EventLoop &event_loop, MixerListener &mixer_listener,
void
MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
{
- for (const config_param *param = config_get_param(CONF_AUDIO_OUTPUT);
+ for (const auto *param = config_get_block(ConfigBlockOption::AUDIO_OUTPUT);
param != nullptr; param = param->next) {
auto output = LoadOutput(event_loop, mixer_listener,
pc, *param);
@@ -87,7 +87,7 @@ MultipleOutputs::Configure(EventLoop &event_loop, PlayerControl &pc)
if (outputs.empty()) {
/* auto-detect device */
- const config_param empty;
+ const ConfigBlock empty;
auto output = LoadOutput(event_loop, mixer_listener,
pc, empty);
outputs.push_back(output);
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index 2c6536e2a..a5bdc7b56 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputAPI.hxx b/src/output/OutputAPI.hxx
index e0fd6eec8..af3f90344 100644
--- a/src/output/OutputAPI.hxx
+++ b/src/output/OutputAPI.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include "Internal.hxx"
#include "AudioFormat.hxx"
#include "tag/Tag.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
// IWYU pragma: end_exports
diff --git a/src/output/OutputCommand.cxx b/src/output/OutputCommand.cxx
index 6afb70cf1..0297ebbcd 100644
--- a/src/output/OutputCommand.cxx
+++ b/src/output/OutputCommand.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputCommand.hxx b/src/output/OutputCommand.hxx
index 53fc5c95e..5b53cd1c2 100644
--- a/src/output/OutputCommand.hxx
+++ b/src/output/OutputCommand.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputControl.cxx b/src/output/OutputControl.cxx
index 89428fa87..6da18e3a0 100644
--- a/src/output/OutputControl.cxx
+++ b/src/output/OutputControl.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -46,7 +46,7 @@ AudioOutput::WaitForCommand()
}
void
-AudioOutput::CommandAsync(audio_output_command cmd)
+AudioOutput::CommandAsync(Command cmd)
{
assert(IsCommandFinished());
@@ -55,14 +55,14 @@ AudioOutput::CommandAsync(audio_output_command cmd)
}
void
-AudioOutput::CommandWait(audio_output_command cmd)
+AudioOutput::CommandWait(Command cmd)
{
CommandAsync(cmd);
WaitForCommand();
}
void
-AudioOutput::LockCommandWait(audio_output_command cmd)
+AudioOutput::LockCommandWait(Command cmd)
{
const ScopeLock protect(mutex);
CommandWait(cmd);
@@ -92,7 +92,7 @@ AudioOutput::LockEnableWait()
StartThread();
}
- LockCommandWait(AO_COMMAND_ENABLE);
+ LockCommandWait(Command::ENABLE);
}
void
@@ -109,7 +109,7 @@ AudioOutput::LockDisableWait()
return;
}
- LockCommandWait(AO_COMMAND_DISABLE);
+ LockCommandWait(Command::DISABLE);
}
inline bool
@@ -134,7 +134,7 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
/* we're not using audio_output_cancel() here,
because that function is asynchronous */
- CommandWait(AO_COMMAND_CANCEL);
+ CommandWait(Command::CANCEL);
}
return true;
@@ -148,7 +148,9 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
if (!thread.IsDefined())
StartThread();
- CommandWait(open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN);
+ CommandWait(open
+ ? Command::REOPEN
+ : Command::OPEN);
const bool open2 = open;
if (open2 && mixer != nullptr) {
@@ -172,7 +174,7 @@ AudioOutput::CloseWait()
assert(!open || !fail_timer.IsDefined());
if (open)
- CommandWait(AO_COMMAND_CLOSE);
+ CommandWait(Command::CLOSE);
else
fail_timer.Reset();
}
@@ -219,7 +221,7 @@ AudioOutput::LockPauseAsync()
assert(allow_play);
if (IsOpen())
- CommandAsync(AO_COMMAND_PAUSE);
+ CommandAsync(Command::PAUSE);
}
void
@@ -229,7 +231,7 @@ AudioOutput::LockDrainAsync()
assert(allow_play);
if (IsOpen())
- CommandAsync(AO_COMMAND_DRAIN);
+ CommandAsync(Command::DRAIN);
}
void
@@ -239,7 +241,7 @@ AudioOutput::LockCancelAsync()
if (IsOpen()) {
allow_play = false;
- CommandAsync(AO_COMMAND_CANCEL);
+ CommandAsync(Command::CANCEL);
}
}
@@ -277,7 +279,7 @@ AudioOutput::StopThread()
assert(thread.IsDefined());
assert(allow_play);
- LockCommandWait(AO_COMMAND_KILL);
+ LockCommandWait(Command::KILL);
thread.Join();
}
diff --git a/src/output/OutputControl.hxx b/src/output/OutputControl.hxx
index fff3fe406..5c8f49718 100644
--- a/src/output/OutputControl.hxx
+++ b/src/output/OutputControl.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputPlugin.cxx b/src/output/OutputPlugin.cxx
index 33bb854d4..7d95ef345 100644
--- a/src/output/OutputPlugin.cxx
+++ b/src/output/OutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,13 +23,13 @@
AudioOutput *
ao_plugin_init(const AudioOutputPlugin *plugin,
- const config_param &param,
+ const ConfigBlock &block,
Error &error)
{
assert(plugin != nullptr);
assert(plugin->init != nullptr);
- return plugin->init(param, error);
+ return plugin->init(block, error);
}
void
@@ -75,7 +75,7 @@ ao_plugin_delay(AudioOutput *ao)
}
void
-ao_plugin_send_tag(AudioOutput *ao, const Tag *tag)
+ao_plugin_send_tag(AudioOutput *ao, const Tag &tag)
{
if (ao->plugin.send_tag != nullptr)
ao->plugin.send_tag(ao, tag);
diff --git a/src/output/OutputPlugin.hxx b/src/output/OutputPlugin.hxx
index 00fa36bc0..63b774fd6 100644
--- a/src/output/OutputPlugin.hxx
+++ b/src/output/OutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
#include <stddef.h>
-struct config_param;
+struct ConfigBlock;
struct AudioFormat;
struct Tag;
struct AudioOutput;
@@ -55,8 +55,7 @@ struct AudioOutputPlugin {
* @return nullptr on error, or an opaque pointer to the plugin's
* data
*/
- AudioOutput *(*init)(const config_param &param,
- Error &error);
+ AudioOutput *(*init)(const ConfigBlock &block, Error &error);
/**
* Free resources allocated by this device.
@@ -107,7 +106,7 @@ struct AudioOutputPlugin {
* Display metadata for the next chunk. Optional method,
* because not all devices can display metadata.
*/
- void (*send_tag)(AudioOutput *data, const Tag *tag);
+ void (*send_tag)(AudioOutput *data, const Tag &tag);
/**
* Play a chunk of audio data.
@@ -162,7 +161,7 @@ ao_plugin_test_default_device(const AudioOutputPlugin *plugin)
gcc_malloc
AudioOutput *
ao_plugin_init(const AudioOutputPlugin *plugin,
- const config_param &param,
+ const ConfigBlock &block,
Error &error);
void
@@ -186,7 +185,7 @@ unsigned
ao_plugin_delay(AudioOutput *ao);
void
-ao_plugin_send_tag(AudioOutput *ao, const Tag *tag);
+ao_plugin_send_tag(AudioOutput *ao, const Tag &tag);
size_t
ao_plugin_play(AudioOutput *ao, const void *chunk, size_t size,
diff --git a/src/output/OutputPrint.cxx b/src/output/OutputPrint.cxx
index 414a86e32..831aea649 100644
--- a/src/output/OutputPrint.cxx
+++ b/src/output/OutputPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputPrint.hxx b/src/output/OutputPrint.hxx
index 29aa2b11c..2679f6a70 100644
--- a/src/output/OutputPrint.hxx
+++ b/src/output/OutputPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputState.cxx b/src/output/OutputState.cxx
index fb01b1c65..a1ca11b49 100644
--- a/src/output/OutputState.cxx
+++ b/src/output/OutputState.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputState.hxx b/src/output/OutputState.hxx
index 47f8429d5..85066acdf 100644
--- a/src/output/OutputState.hxx
+++ b/src/output/OutputState.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/OutputThread.cxx b/src/output/OutputThread.cxx
index 2ec0670c1..9baaaf0e0 100644
--- a/src/output/OutputThread.cxx
+++ b/src/output/OutputThread.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -45,8 +45,8 @@
void
AudioOutput::CommandFinished()
{
- assert(command != AO_COMMAND_NONE);
- command = AO_COMMAND_NONE;
+ assert(command != Command::NONE);
+ command = Command::NONE;
mutex.unlock();
audio_output_client_notify.Signal();
@@ -342,7 +342,7 @@ AudioOutput::WaitForDelay()
(void)cond.timed_wait(mutex, delay);
- if (command != AO_COMMAND_NONE)
+ if (command != Command::NONE)
return false;
}
}
@@ -455,7 +455,7 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
if (tags && gcc_unlikely(chunk->tag != nullptr)) {
mutex.unlock();
- ao_plugin_send_tag(this, chunk->tag);
+ ao_plugin_send_tag(this, *chunk->tag);
mutex.lock();
}
@@ -471,7 +471,7 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
Error error;
- while (!data.IsEmpty() && command == AO_COMMAND_NONE) {
+ while (!data.IsEmpty() && command == Command::NONE) {
if (!WaitForDelay())
break;
@@ -529,7 +529,7 @@ AudioOutput::Play()
assert(!in_playback_loop);
in_playback_loop = true;
- while (chunk != nullptr && command == AO_COMMAND_NONE) {
+ while (chunk != nullptr && command == Command::NONE) {
assert(!current_chunk_finished);
current_chunk = chunk;
@@ -577,7 +577,7 @@ AudioOutput::Pause()
Close(false);
break;
}
- } while (command == AO_COMMAND_NONE);
+ } while (command == Command::NONE);
pause = false;
}
@@ -594,30 +594,30 @@ AudioOutput::Task()
while (1) {
switch (command) {
- case AO_COMMAND_NONE:
+ case Command::NONE:
break;
- case AO_COMMAND_ENABLE:
+ case Command::ENABLE:
Enable();
CommandFinished();
break;
- case AO_COMMAND_DISABLE:
+ case Command::DISABLE:
Disable();
CommandFinished();
break;
- case AO_COMMAND_OPEN:
+ case Command::OPEN:
Open();
CommandFinished();
break;
- case AO_COMMAND_REOPEN:
+ case Command::REOPEN:
Reopen();
CommandFinished();
break;
- case AO_COMMAND_CLOSE:
+ case Command::CLOSE:
assert(open);
assert(pipe != nullptr);
@@ -625,7 +625,7 @@ AudioOutput::Task()
CommandFinished();
break;
- case AO_COMMAND_PAUSE:
+ case Command::PAUSE:
if (!open) {
/* the output has failed after
audio_output_all_pause() has
@@ -642,7 +642,7 @@ AudioOutput::Task()
the new command first */
continue;
- case AO_COMMAND_DRAIN:
+ case Command::DRAIN:
if (open) {
assert(current_chunk == nullptr);
assert(pipe->Peek() == nullptr);
@@ -655,7 +655,7 @@ AudioOutput::Task()
CommandFinished();
continue;
- case AO_COMMAND_CANCEL:
+ case Command::CANCEL:
current_chunk = nullptr;
if (open) {
@@ -667,7 +667,7 @@ AudioOutput::Task()
CommandFinished();
continue;
- case AO_COMMAND_KILL:
+ case Command::KILL:
current_chunk = nullptr;
CommandFinished();
mutex.unlock();
@@ -679,7 +679,7 @@ AudioOutput::Task()
chunks in the pipe */
continue;
- if (command == AO_COMMAND_NONE) {
+ if (command == Command::NONE) {
woken_for_play = false;
cond.wait(mutex);
}
@@ -696,7 +696,7 @@ AudioOutput::Task(void *arg)
void
AudioOutput::StartThread()
{
- assert(command == AO_COMMAND_NONE);
+ assert(command == Command::NONE);
Error error;
if (!thread.Start(Task, this, error))
diff --git a/src/output/Registry.cxx b/src/output/Registry.cxx
index 566f6b6a8..06928ce9a 100644
--- a/src/output/Registry.cxx
+++ b/src/output/Registry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -54,13 +54,13 @@ const AudioOutputPlugin *const audio_output_plugins[] = {
#ifdef ENABLE_PIPE_OUTPUT
&pipe_output_plugin,
#endif
-#ifdef HAVE_ALSA
+#ifdef ENABLE_ALSA
&alsa_output_plugin,
#endif
-#ifdef HAVE_ROAR
+#ifdef ENABLE_ROAR
&roar_output_plugin,
#endif
-#ifdef HAVE_AO
+#ifdef ENABLE_AO
&ao_output_plugin,
#endif
#ifdef HAVE_OSS
@@ -75,10 +75,10 @@ const AudioOutputPlugin *const audio_output_plugins[] = {
#ifdef ENABLE_SOLARIS_OUTPUT
&solaris_output_plugin,
#endif
-#ifdef HAVE_PULSE
+#ifdef ENABLE_PULSE
&pulse_output_plugin,
#endif
-#ifdef HAVE_JACK
+#ifdef ENABLE_JACK
&jack_output_plugin,
#endif
#ifdef ENABLE_HTTPD_OUTPUT
diff --git a/src/output/Registry.hxx b/src/output/Registry.hxx
index bc9c1ae2b..2c7202a75 100644
--- a/src/output/Registry.hxx
+++ b/src/output/Registry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Timer.cxx b/src/output/Timer.cxx
index d3dcc714d..a75744744 100644
--- a/src/output/Timer.cxx
+++ b/src/output/Timer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Timer.hxx b/src/output/Timer.hxx
index 3c935cfac..057090c1e 100644
--- a/src/output/Timer.hxx
+++ b/src/output/Timer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/Wrapper.hxx b/src/output/Wrapper.hxx
new file mode 100644
index 000000000..c043849bb
--- /dev/null
+++ b/src/output/Wrapper.hxx
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_OUTPUT_WRAPPER_HXX
+#define MPD_OUTPUT_WRAPPER_HXX
+
+#include "util/Cast.hxx"
+
+struct ConfigBlock;
+
+template<class T>
+struct AudioOutputWrapper {
+ static T &Cast(AudioOutput &ao) {
+ return ContainerCast(ao, &T::base);
+ }
+
+ static AudioOutput *Init(const ConfigBlock &block, Error &error) {
+ T *t = T::Create(block, error);
+ return t != nullptr
+ ? &t->base
+ : nullptr;
+ }
+
+ static void Finish(AudioOutput *ao) {
+ T *t = &Cast(*ao);
+ delete t;
+ }
+
+ static bool Enable(AudioOutput *ao, Error &error) {
+ T &t = Cast(*ao);
+ return t.Enable(error);
+ }
+
+ static void Disable(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ t.Disable();
+ }
+
+ static bool Open(AudioOutput *ao, AudioFormat &audio_format,
+ Error &error) {
+ T &t = Cast(*ao);
+ return t.Open(audio_format, error);
+ }
+
+ static void Close(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ t.Close();
+ }
+
+ gcc_pure
+ static unsigned Delay(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ return t.Delay();
+ }
+
+ gcc_pure
+ static void SendTag(AudioOutput *ao, const Tag &tag) {
+ T &t = Cast(*ao);
+ t.SendTag(tag);
+ }
+
+ static size_t Play(AudioOutput *ao, const void *chunk, size_t size,
+ Error &error) {
+ T &t = Cast(*ao);
+ return t.Play(chunk, size, error);
+ }
+
+ static void Drain(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ t.Drain();
+ }
+
+ static void Cancel(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ t.Cancel();
+ }
+
+ gcc_pure
+ static bool Pause(AudioOutput *ao) {
+ T &t = Cast(*ao);
+ return t.Pause();
+ }
+};
+
+#endif
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 28c374a00..8a7bb9643 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "AlsaOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "mixer/MixerList.hxx"
#include "pcm/PcmExport.hxx"
#include "config/ConfigError.hxx"
@@ -131,92 +132,108 @@ struct AlsaOutput {
mode(0), writei(snd_pcm_writei) {
}
- bool Configure(const config_param &param, Error &error);
+ ~AlsaOutput() {
+ /* free libasound's config cache */
+ snd_config_update_free_global();
+ }
+
+ gcc_pure
+ const char *GetDevice() {
+ return device.empty() ? default_device : device.c_str();
+ }
+
+ bool Configure(const ConfigBlock &block, Error &error);
+ static AlsaOutput *Create(const ConfigBlock &block, Error &error);
+
+ bool Enable(Error &error);
+ void Disable();
+
+ bool Open(AudioFormat &audio_format, Error &error);
+ void Close();
+
+ size_t Play(const void *chunk, size_t size, Error &error);
+ void Drain();
+ void Cancel();
+
+private:
+ bool SetupDop(AudioFormat audio_format,
+ bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
+ Error &error);
+ bool SetupOrDop(AudioFormat &audio_format, Error &error);
+
+ int Recover(int err);
+
+ /**
+ * Write silence to the ALSA device.
+ */
+ void WriteSilence(snd_pcm_uframes_t nframes) {
+ writei(pcm, silence, nframes);
+ }
+
};
static constexpr Domain alsa_output_domain("alsa_output");
-static const char *
-alsa_device(const AlsaOutput *ad)
-{
- return ad->device.empty() ? default_device : ad->device.c_str();
-}
-
inline bool
-AlsaOutput::Configure(const config_param &param, Error &error)
+AlsaOutput::Configure(const ConfigBlock &block, Error &error)
{
- if (!base.Configure(param, error))
+ if (!base.Configure(block, error))
return false;
- device = param.GetBlockValue("device", "");
+ device = block.GetBlockValue("device", "");
- use_mmap = param.GetBlockValue("use_mmap", false);
+ use_mmap = block.GetBlockValue("use_mmap", false);
- dop = param.GetBlockValue("dop", false) ||
+ dop = block.GetBlockValue("dop", false) ||
/* legacy name from MPD 0.18 and older: */
- param.GetBlockValue("dsd_usb", false);
+ block.GetBlockValue("dsd_usb", false);
- buffer_time = param.GetBlockValue("buffer_time",
+ buffer_time = block.GetBlockValue("buffer_time",
MPD_ALSA_BUFFER_TIME_US);
- period_time = param.GetBlockValue("period_time", 0u);
+ period_time = block.GetBlockValue("period_time", 0u);
#ifdef SND_PCM_NO_AUTO_RESAMPLE
- if (!param.GetBlockValue("auto_resample", true))
+ if (!block.GetBlockValue("auto_resample", true))
mode |= SND_PCM_NO_AUTO_RESAMPLE;
#endif
#ifdef SND_PCM_NO_AUTO_CHANNELS
- if (!param.GetBlockValue("auto_channels", true))
+ if (!block.GetBlockValue("auto_channels", true))
mode |= SND_PCM_NO_AUTO_CHANNELS;
#endif
#ifdef SND_PCM_NO_AUTO_FORMAT
- if (!param.GetBlockValue("auto_format", true))
+ if (!block.GetBlockValue("auto_format", true))
mode |= SND_PCM_NO_AUTO_FORMAT;
#endif
return true;
}
-static AudioOutput *
-alsa_init(const config_param &param, Error &error)
+inline AlsaOutput *
+AlsaOutput::Create(const ConfigBlock &block, Error &error)
{
AlsaOutput *ad = new AlsaOutput();
- if (!ad->Configure(param, error)) {
+ if (!ad->Configure(block, error)) {
delete ad;
return nullptr;
}
- return &ad->base;
+ return ad;
}
-static void
-alsa_finish(AudioOutput *ao)
-{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- delete ad;
-
- /* free libasound's config cache */
- snd_config_update_free_global();
-}
-
-static bool
-alsa_output_enable(AudioOutput *ao, gcc_unused Error &error)
+inline bool
+AlsaOutput::Enable(gcc_unused Error &error)
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- ad->pcm_export.Construct();
+ pcm_export.Construct();
return true;
}
-static void
-alsa_output_disable(AudioOutput *ao)
+inline void
+AlsaOutput::Disable()
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- ad->pcm_export.Destruct();
+ pcm_export.Destruct();
}
static bool
@@ -450,7 +467,7 @@ configure_hw:
if (err < 0) {
FormatWarning(alsa_output_domain,
"Cannot set mmap'ed mode on ALSA device \"%s\": %s",
- alsa_device(ad), snd_strerror(-err));
+ ad->GetDevice(), snd_strerror(-err));
LogWarning(alsa_output_domain,
"Falling back to direct write mode");
ad->use_mmap = false;
@@ -472,7 +489,7 @@ configure_hw:
if (err < 0) {
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support format %s: %s",
- alsa_device(ad),
+ ad->GetDevice(),
sample_format_to_string(audio_format.format),
snd_strerror(-err));
return false;
@@ -489,7 +506,7 @@ configure_hw:
if (err < 0) {
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %i channels: %s",
- alsa_device(ad), (int)audio_format.channels,
+ ad->GetDevice(), (int)audio_format.channels,
snd_strerror(-err));
return false;
}
@@ -500,7 +517,7 @@ configure_hw:
if (err < 0 || sample_rate == 0) {
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %u Hz audio",
- alsa_device(ad), audio_format.sample_rate);
+ ad->GetDevice(), audio_format.sample_rate);
return false;
}
audio_format.sample_rate = sample_rate;
@@ -631,16 +648,16 @@ configure_hw:
error:
error.Format(alsa_output_domain, err,
"Error opening ALSA device \"%s\" (%s): %s",
- alsa_device(ad), cmd, snd_strerror(-err));
+ ad->GetDevice(), cmd, snd_strerror(-err));
return false;
}
-static bool
-alsa_setup_dop(AlsaOutput *ad, const AudioFormat audio_format,
- bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
- Error &error)
+inline bool
+AlsaOutput::SetupDop(const AudioFormat audio_format,
+ bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
+ Error &error)
{
- assert(ad->dop);
+ assert(dop);
assert(audio_format.format == SampleFormat::DSD);
/* pass 24 bit to alsa_setup() */
@@ -651,7 +668,7 @@ alsa_setup_dop(AlsaOutput *ad, const AudioFormat audio_format,
const AudioFormat check = dop_format;
- if (!alsa_setup(ad, dop_format, packed_r, reverse_endian_r, error))
+ if (!alsa_setup(this, dop_format, packed_r, reverse_endian_r, error))
return false;
/* if the device allows only 32 bit, shift all DoP
@@ -668,102 +685,91 @@ alsa_setup_dop(AlsaOutput *ad, const AudioFormat audio_format,
for DSD over USB */
error.Format(alsa_output_domain,
"Failed to configure DSD-over-PCM on ALSA device \"%s\"",
- alsa_device(ad));
- delete[] ad->silence;
+ GetDevice());
+ delete[] silence;
return false;
}
return true;
}
-static bool
-alsa_setup_or_dop(AlsaOutput *ad, AudioFormat &audio_format,
- Error &error)
+inline bool
+AlsaOutput::SetupOrDop(AudioFormat &audio_format, Error &error)
{
bool shift8 = false, packed, reverse_endian;
- const bool dop = ad->dop &&
+ const bool dop2 = dop &&
audio_format.format == SampleFormat::DSD;
- const bool success = dop
- ? alsa_setup_dop(ad, audio_format,
- &shift8, &packed, &reverse_endian,
- error)
- : alsa_setup(ad, audio_format, &packed, &reverse_endian,
+ const bool success = dop2
+ ? SetupDop(audio_format,
+ &shift8, &packed, &reverse_endian,
+ error)
+ : alsa_setup(this, audio_format, &packed, &reverse_endian,
error);
if (!success)
return false;
- ad->pcm_export->Open(audio_format.format,
- audio_format.channels,
- dop, shift8, packed, reverse_endian);
+ pcm_export->Open(audio_format.format,
+ audio_format.channels,
+ dop2, shift8, packed, reverse_endian);
return true;
}
-static bool
-alsa_open(AudioOutput *ao, AudioFormat &audio_format, Error &error)
+inline bool
+AlsaOutput::Open(AudioFormat &audio_format, Error &error)
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
- SND_PCM_STREAM_PLAYBACK, ad->mode);
+ int err = snd_pcm_open(&pcm, GetDevice(),
+ SND_PCM_STREAM_PLAYBACK, mode);
if (err < 0) {
error.Format(alsa_output_domain, err,
"Failed to open ALSA device \"%s\": %s",
- alsa_device(ad), snd_strerror(err));
+ GetDevice(), snd_strerror(err));
return false;
}
FormatDebug(alsa_output_domain, "opened %s type=%s",
- snd_pcm_name(ad->pcm),
- snd_pcm_type_name(snd_pcm_type(ad->pcm)));
+ snd_pcm_name(pcm),
+ snd_pcm_type_name(snd_pcm_type(pcm)));
- if (!alsa_setup_or_dop(ad, audio_format, error)) {
- snd_pcm_close(ad->pcm);
+ if (!SetupOrDop(audio_format, error)) {
+ snd_pcm_close(pcm);
return false;
}
- ad->in_frame_size = audio_format.GetFrameSize();
- ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format);
+ in_frame_size = audio_format.GetFrameSize();
+ out_frame_size = pcm_export->GetFrameSize(audio_format);
- ad->must_prepare = false;
+ must_prepare = false;
return true;
}
-/**
- * Write silence to the ALSA device.
- */
-static void
-alsa_write_silence(AlsaOutput *ad, snd_pcm_uframes_t nframes)
-{
- ad->writei(ad->pcm, ad->silence, nframes);
-}
-
-static int
-alsa_recover(AlsaOutput *ad, int err)
+inline int
+AlsaOutput::Recover(int err)
{
if (err == -EPIPE) {
FormatDebug(alsa_output_domain,
- "Underrun on ALSA device \"%s\"", alsa_device(ad));
+ "Underrun on ALSA device \"%s\"",
+ GetDevice());
} else if (err == -ESTRPIPE) {
FormatDebug(alsa_output_domain,
"ALSA device \"%s\" was suspended",
- alsa_device(ad));
+ GetDevice());
}
- switch (snd_pcm_state(ad->pcm)) {
+ switch (snd_pcm_state(pcm)) {
case SND_PCM_STATE_PAUSED:
- err = snd_pcm_pause(ad->pcm, /* disable */ 0);
+ err = snd_pcm_pause(pcm, /* disable */ 0);
break;
case SND_PCM_STATE_SUSPENDED:
- err = snd_pcm_resume(ad->pcm);
+ err = snd_pcm_resume(pcm);
if (err == -EAGAIN)
return 0;
/* fall-through to snd_pcm_prepare: */
case SND_PCM_STATE_SETUP:
case SND_PCM_STATE_XRUN:
- ad->period_position = 0;
- err = snd_pcm_prepare(ad->pcm);
+ period_position = 0;
+ err = snd_pcm_prepare(pcm);
break;
case SND_PCM_STATE_DISCONNECTED:
break;
@@ -779,67 +785,58 @@ alsa_recover(AlsaOutput *ad, int err)
return err;
}
-static void
-alsa_drain(AudioOutput *ao)
+inline void
+AlsaOutput::Drain()
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- if (snd_pcm_state(ad->pcm) != SND_PCM_STATE_RUNNING)
+ if (snd_pcm_state(pcm) != SND_PCM_STATE_RUNNING)
return;
- if (ad->period_position > 0) {
+ if (period_position > 0) {
/* generate some silence to finish the partial
period */
snd_pcm_uframes_t nframes =
- ad->period_frames - ad->period_position;
- alsa_write_silence(ad, nframes);
+ period_frames - period_position;
+ WriteSilence(nframes);
}
- snd_pcm_drain(ad->pcm);
+ snd_pcm_drain(pcm);
- ad->period_position = 0;
+ period_position = 0;
}
-static void
-alsa_cancel(AudioOutput *ao)
+inline void
+AlsaOutput::Cancel()
{
- AlsaOutput *ad = (AlsaOutput *)ao;
+ period_position = 0;
+ must_prepare = true;
- ad->period_position = 0;
- ad->must_prepare = true;
-
- snd_pcm_drop(ad->pcm);
+ snd_pcm_drop(pcm);
}
-static void
-alsa_close(AudioOutput *ao)
+inline void
+AlsaOutput::Close()
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
- snd_pcm_close(ad->pcm);
- delete[] ad->silence;
+ snd_pcm_close(pcm);
+ delete[] silence;
}
-static size_t
-alsa_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+AlsaOutput::Play(const void *chunk, size_t size, Error &error)
{
- AlsaOutput *ad = (AlsaOutput *)ao;
-
assert(size > 0);
- assert(size % ad->in_frame_size == 0);
+ assert(size % in_frame_size == 0);
- if (ad->must_prepare) {
- ad->must_prepare = false;
+ if (must_prepare) {
+ must_prepare = false;
- int err = snd_pcm_prepare(ad->pcm);
+ int err = snd_pcm_prepare(pcm);
if (err < 0) {
error.Set(alsa_output_domain, err, snd_strerror(-err));
return 0;
}
}
- const auto e = ad->pcm_export->Export({chunk, size});
+ const auto e = pcm_export->Export({chunk, size});
if (e.size == 0)
/* the DoP (DSD over PCM) filter converts two frames
at a time and ignores the last odd frame; if there
@@ -852,43 +849,45 @@ alsa_play(AudioOutput *ao, const void *chunk, size_t size,
chunk = e.data;
size = e.size;
- assert(size % ad->out_frame_size == 0);
+ assert(size % out_frame_size == 0);
- size /= ad->out_frame_size;
+ size /= out_frame_size;
assert(size > 0);
while (true) {
- snd_pcm_sframes_t ret = ad->writei(ad->pcm, chunk, size);
+ snd_pcm_sframes_t ret = writei(pcm, chunk, size);
if (ret > 0) {
- ad->period_position = (ad->period_position + ret)
- % ad->period_frames;
+ period_position = (period_position + ret)
+ % period_frames;
- size_t bytes_written = ret * ad->out_frame_size;
- return ad->pcm_export->CalcSourceSize(bytes_written);
+ size_t bytes_written = ret * out_frame_size;
+ return pcm_export->CalcSourceSize(bytes_written);
}
if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
- alsa_recover(ad, ret) < 0) {
+ Recover(ret) < 0) {
error.Set(alsa_output_domain, ret, snd_strerror(-ret));
return 0;
}
}
}
+typedef AudioOutputWrapper<AlsaOutput> Wrapper;
+
const struct AudioOutputPlugin alsa_output_plugin = {
"alsa",
alsa_test_default_device,
- alsa_init,
- alsa_finish,
- alsa_output_enable,
- alsa_output_disable,
- alsa_open,
- alsa_close,
+ &Wrapper::Init,
+ &Wrapper::Finish,
+ &Wrapper::Enable,
+ &Wrapper::Disable,
+ &Wrapper::Open,
+ &Wrapper::Close,
nullptr,
nullptr,
- alsa_play,
- alsa_drain,
- alsa_cancel,
+ &Wrapper::Play,
+ &Wrapper::Drain,
+ &Wrapper::Cancel,
nullptr,
&alsa_mixer_plugin,
diff --git a/src/output/plugins/AlsaOutputPlugin.hxx b/src/output/plugins/AlsaOutputPlugin.hxx
index f72116f91..ff7d439a9 100644
--- a/src/output/plugins/AlsaOutputPlugin.hxx
+++ b/src/output/plugins/AlsaOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/AoOutputPlugin.cxx b/src/output/plugins/AoOutputPlugin.cxx
index af8c88fa1..3c0cf74a4 100644
--- a/src/output/plugins/AoOutputPlugin.cxx
+++ b/src/output/plugins/AoOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,12 +20,13 @@
#include "config.h"
#include "AoOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "util/DivideString.hxx"
+#include "util/SplitString.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#include <ao/ao.h>
-#include <glib.h>
#include <string.h>
@@ -45,11 +46,11 @@ struct AoOutput {
AoOutput()
:base(ao_output_plugin) {}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
};
static constexpr Domain ao_output_domain("ao_output");
@@ -89,20 +90,20 @@ ao_output_error(Error &error_r)
}
inline bool
-AoOutput::Configure(const config_param &param, Error &error)
+AoOutput::Configure(const ConfigBlock &block, Error &error)
{
const char *value;
options = nullptr;
- write_size = param.GetBlockValue("write_size", 1024u);
+ write_size = block.GetBlockValue("write_size", 1024u);
if (ao_output_ref == 0) {
ao_initialize();
}
ao_output_ref++;
- value = param.GetBlockValue("driver", "default");
+ value = block.GetBlockValue("driver", "default");
if (0 == strcmp(value, "default"))
driver = ao_default_driver_id();
else
@@ -122,45 +123,38 @@ AoOutput::Configure(const config_param &param, Error &error)
}
FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n",
- ai->short_name, param.GetBlockValue("name", nullptr));
+ ai->short_name, block.GetBlockValue("name", nullptr));
- value = param.GetBlockValue("options", nullptr);
+ value = block.GetBlockValue("options", nullptr);
if (value != nullptr) {
- gchar **_options = g_strsplit(value, ";", 0);
+ for (const auto &i : SplitString(value, ';')) {
+ const DivideString ss(i.c_str(), '=', true);
- for (unsigned i = 0; _options[i] != nullptr; ++i) {
- gchar **key_value = g_strsplit(_options[i], "=", 2);
-
- if (key_value[0] == nullptr || key_value[1] == nullptr) {
+ if (!ss.IsDefined()) {
error.Format(ao_output_domain,
"problems parsing options \"%s\"",
- _options[i]);
+ i.c_str());
return false;
}
- ao_append_option(&options, key_value[0],
- key_value[1]);
-
- g_strfreev(key_value);
+ ao_append_option(&options, ss.GetFirst(), ss.GetSecond());
}
-
- g_strfreev(_options);
}
return true;
}
static AudioOutput *
-ao_output_init(const config_param &param, Error &error)
+ao_output_init(const ConfigBlock &block, Error &error)
{
AoOutput *ad = new AoOutput();
- if (!ad->Initialize(param, error)) {
+ if (!ad->Initialize(block, error)) {
delete ad;
return nullptr;
}
- if (!ad->Configure(param, error)) {
+ if (!ad->Configure(block, error)) {
delete ad;
return nullptr;
}
diff --git a/src/output/plugins/AoOutputPlugin.hxx b/src/output/plugins/AoOutputPlugin.hxx
index 07c2ba16b..582070c47 100644
--- a/src/output/plugins/AoOutputPlugin.hxx
+++ b/src/output/plugins/AoOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx
index 9df5a74dd..ddc63489c 100644
--- a/src/output/plugins/FifoOutputPlugin.cxx
+++ b/src/output/plugins/FifoOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -51,8 +51,8 @@ struct FifoOutput {
path(AllocatedPath::Null()), input(-1), output(-1),
created(false) {}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
bool Create(Error &error);
@@ -169,11 +169,11 @@ fifo_open(FifoOutput *fd, Error &error)
}
static AudioOutput *
-fifo_output_init(const config_param &param, Error &error)
+fifo_output_init(const ConfigBlock &block, Error &error)
{
FifoOutput *fd = new FifoOutput();
- fd->path = param.GetBlockPath("path", error);
+ fd->path = block.GetBlockPath("path", error);
if (fd->path.IsNull()) {
delete fd;
@@ -185,7 +185,7 @@ fifo_output_init(const config_param &param, Error &error)
fd->path_utf8 = fd->path.ToUTF8();
- if (!fd->Initialize(param, error)) {
+ if (!fd->Initialize(block, error)) {
delete fd;
return nullptr;
}
@@ -260,14 +260,13 @@ fifo_output_play(AudioOutput *ao, const void *chunk, size_t size,
Error &error)
{
FifoOutput *fd = (FifoOutput *)ao;
- ssize_t bytes;
if (!fd->timer->IsStarted())
fd->timer->Start();
fd->timer->Add(size);
while (true) {
- bytes = write(fd->output, chunk, size);
+ ssize_t bytes = write(fd->output, chunk, size);
if (bytes > 0)
return (size_t)bytes;
diff --git a/src/output/plugins/FifoOutputPlugin.hxx b/src/output/plugins/FifoOutputPlugin.hxx
index f41ceded6..353be51a6 100644
--- a/src/output/plugins/FifoOutputPlugin.hxx
+++ b/src/output/plugins/FifoOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx
index e1dad7893..23843ab5e 100644
--- a/src/output/plugins/JackOutputPlugin.cxx
+++ b/src/output/plugins/JackOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,26 +20,27 @@
#include "config.h"
#include "JackOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "config/ConfigError.hxx"
+#include "util/ConstBuffer.hxx"
+#include "util/SplitString.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
#include <assert.h>
-#include <glib.h>
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/ringbuffer.h>
+#include <unistd.h> /* for usleep() */
#include <stdlib.h>
#include <string.h>
-enum {
- MAX_PORTS = 16,
-};
+static constexpr unsigned MAX_PORTS = 16;
-static const size_t jack_sample_size = sizeof(jack_default_audio_sample_t);
+static constexpr size_t jack_sample_size = sizeof(jack_default_audio_sample_t);
struct JackOutput {
AudioOutput base;
@@ -55,10 +56,10 @@ struct JackOutput {
/* configuration */
- char *source_ports[MAX_PORTS];
+ std::string source_ports[MAX_PORTS];
unsigned num_source_ports;
- char *destination_ports[MAX_PORTS];
+ std::string destination_ports[MAX_PORTS];
unsigned num_destination_ports;
size_t ringbuffer_size;
@@ -82,24 +83,65 @@ struct JackOutput {
JackOutput()
:base(jack_output_plugin) {}
- bool Initialize(const config_param &param, Error &error_r) {
- return base.Configure(param, error_r);
+ bool Configure(const ConfigBlock &block, Error &error);
+
+ bool Connect(Error &error);
+
+ /**
+ * Disconnect the JACK client.
+ */
+ void Disconnect();
+
+ void Shutdown() {
+ shutdown = true;
+ }
+
+ bool Enable(Error &error);
+ void Disable();
+
+ bool Open(AudioFormat &new_audio_format, Error &error);
+
+ void Close() {
+ Stop();
+ }
+
+ bool Start(Error &error);
+ void Stop();
+
+ /**
+ * Determine the number of frames guaranteed to be available
+ * on all channels.
+ */
+ gcc_pure
+ jack_nframes_t GetAvailable() const;
+
+ void Process(jack_nframes_t nframes);
+
+ /**
+ * @return the number of frames that were written
+ */
+ size_t WriteSamples(const float *src, size_t n_frames);
+
+ unsigned Delay() const {
+ return base.pause && pause && !shutdown
+ ? 1000
+ : 0;
}
+
+ size_t Play(const void *chunk, size_t size, Error &error);
+
+ bool Pause();
};
static constexpr Domain jack_output_domain("jack_output");
-/**
- * Determine the number of frames guaranteed to be available on all
- * channels.
- */
-static jack_nframes_t
-mpd_jack_available(const JackOutput *jd)
+inline jack_nframes_t
+JackOutput::GetAvailable() const
{
- size_t min = jack_ringbuffer_read_space(jd->ringbuffer[0]);
+ size_t min = jack_ringbuffer_read_space(ringbuffer[0]);
- for (unsigned i = 1; i < jd->audio_format.channels; ++i) {
- size_t current = jack_ringbuffer_read_space(jd->ringbuffer[i]);
+ for (unsigned i = 1; i < audio_format.channels; ++i) {
+ size_t current = jack_ringbuffer_read_space(ringbuffer[i]);
if (current < min)
min = current;
}
@@ -109,85 +151,121 @@ mpd_jack_available(const JackOutput *jd)
return min / jack_sample_size;
}
-static int
-mpd_jack_process(jack_nframes_t nframes, void *arg)
+/**
+ * Call jack_ringbuffer_read_advance() on all buffers in the list.
+ */
+static void
+MultiReadAdvance(ConstBuffer<jack_ringbuffer_t *> buffers,
+ size_t size)
{
- JackOutput *jd = (JackOutput *) arg;
+ for (auto *i : buffers)
+ jack_ringbuffer_read_advance(i, size);
+}
+/**
+ * Write a specific amount of "silence" to the given port.
+ */
+static void
+WriteSilence(jack_port_t &port, jack_nframes_t nframes)
+{
+ jack_default_audio_sample_t *out =
+ (jack_default_audio_sample_t *)
+ jack_port_get_buffer(&port, nframes);
+ if (out == nullptr)
+ /* workaround for libjack1 bug: if the server
+ connection fails, the process callback is invoked
+ anyway, but unable to get a buffer */
+ return;
+
+ std::fill_n(out, nframes, 0.0);
+}
+
+/**
+ * Write a specific amount of "silence" to all ports in the list.
+ */
+static void
+MultiWriteSilence(ConstBuffer<jack_port_t *> ports, jack_nframes_t nframes)
+{
+ for (auto *i : ports)
+ WriteSilence(*i, nframes);
+}
+
+/**
+ * Copy data from the buffer to the port. If the buffer underruns,
+ * fill with silence.
+ */
+static void
+Copy(jack_port_t &dest, jack_nframes_t nframes,
+ jack_ringbuffer_t &src, jack_nframes_t available)
+{
+ jack_default_audio_sample_t *out =
+ (jack_default_audio_sample_t *)
+ jack_port_get_buffer(&dest, nframes);
+ if (out == nullptr)
+ /* workaround for libjack1 bug: if the server
+ connection fails, the process callback is
+ invoked anyway, but unable to get a
+ buffer */
+ return;
+
+ /* copy from buffer to port */
+ jack_ringbuffer_read(&src, (char *)out,
+ available * jack_sample_size);
+
+ /* ringbuffer underrun, fill with silence */
+ std::fill(out + available, out + nframes, 0.0);
+}
+
+inline void
+JackOutput::Process(jack_nframes_t nframes)
+{
if (nframes <= 0)
- return 0;
+ return;
- if (jd->pause) {
+ jack_nframes_t available = GetAvailable();
+
+ const unsigned n_channels = audio_format.channels;
+
+ if (pause) {
/* empty the ring buffers */
- const jack_nframes_t available = mpd_jack_available(jd);
- for (unsigned i = 0; i < jd->audio_format.channels; ++i)
- jack_ringbuffer_read_advance(jd->ringbuffer[i],
- available * jack_sample_size);
+ MultiReadAdvance({ringbuffer, n_channels},
+ available * jack_sample_size);
/* generate silence while MPD is paused */
- for (unsigned i = 0; i < jd->audio_format.channels; ++i) {
- jack_default_audio_sample_t *out =
- (jack_default_audio_sample_t *)
- jack_port_get_buffer(jd->ports[i], nframes);
+ MultiWriteSilence({ports, n_channels}, nframes);
- for (jack_nframes_t f = 0; f < nframes; ++f)
- out[f] = 0.0;
- }
-
- return 0;
+ return;
}
- jack_nframes_t available = mpd_jack_available(jd);
if (available > nframes)
available = nframes;
- for (unsigned i = 0; i < jd->audio_format.channels; ++i) {
- jack_default_audio_sample_t *out =
- (jack_default_audio_sample_t *)
- jack_port_get_buffer(jd->ports[i], nframes);
- if (out == nullptr)
- /* workaround for libjack1 bug: if the server
- connection fails, the process callback is
- invoked anyway, but unable to get a
- buffer */
- continue;
-
- jack_ringbuffer_read(jd->ringbuffer[i],
- (char *)out, available * jack_sample_size);
-
- for (jack_nframes_t f = available; f < nframes; ++f)
- /* ringbuffer underrun, fill with silence */
- out[f] = 0.0;
- }
+ for (unsigned i = 0; i < n_channels; ++i)
+ Copy(*ports[i], nframes, *ringbuffer[i], available);
/* generate silence for the unused source ports */
- for (unsigned i = jd->audio_format.channels;
- i < jd->num_source_ports; ++i) {
- jack_default_audio_sample_t *out =
- (jack_default_audio_sample_t *)
- jack_port_get_buffer(jd->ports[i], nframes);
- if (out == nullptr)
- /* workaround for libjack1 bug: if the server
- connection fails, the process callback is
- invoked anyway, but unable to get a
- buffer */
- continue;
-
- for (jack_nframes_t f = 0; f < nframes; ++f)
- out[f] = 0.0;
- }
+ MultiWriteSilence({ports + n_channels, num_source_ports - n_channels},
+ nframes);
+}
+
+static int
+mpd_jack_process(jack_nframes_t nframes, void *arg)
+{
+ JackOutput &jo = *(JackOutput *) arg;
+ jo.Process(nframes);
return 0;
}
static void
mpd_jack_shutdown(void *arg)
{
- JackOutput *jd = (JackOutput *) arg;
- jd->shutdown = true;
+ JackOutput &jo = *(JackOutput *) arg;
+
+ jo.Shutdown();
}
static void
@@ -200,9 +278,10 @@ set_audioformat(JackOutput *jd, AudioFormat &audio_format)
else if (audio_format.channels > jd->num_source_ports)
audio_format.channels = 2;
- if (audio_format.format != SampleFormat::S16 &&
- audio_format.format != SampleFormat::S24_P32)
- audio_format.format = SampleFormat::S24_P32;
+ /* JACK uses 32 bit float in the range [-1 .. 1] - just like
+ MPD's SampleFormat::FLOAT*/
+ static_assert(jack_sample_size == sizeof(float), "Expected float32");
+ audio_format.format = SampleFormat::FLOAT;
}
static void
@@ -219,55 +298,47 @@ mpd_jack_info(const char *msg)
}
#endif
-/**
- * Disconnect the JACK client.
- */
-static void
-mpd_jack_disconnect(JackOutput *jd)
+void
+JackOutput::Disconnect()
{
- assert(jd != nullptr);
- assert(jd->client != nullptr);
+ assert(client != nullptr);
- jack_deactivate(jd->client);
- jack_client_close(jd->client);
- jd->client = nullptr;
+ jack_deactivate(client);
+ jack_client_close(client);
+ client = nullptr;
}
/**
* Connect the JACK client and performs some basic setup
* (e.g. register callbacks).
*/
-static bool
-mpd_jack_connect(JackOutput *jd, Error &error)
+bool
+JackOutput::Connect(Error &error)
{
- jack_status_t status;
-
- assert(jd != nullptr);
-
- jd->shutdown = false;
+ shutdown = false;
- jd->client = jack_client_open(jd->name, jd->options, &status,
- jd->server_name);
- if (jd->client == nullptr) {
+ jack_status_t status;
+ client = jack_client_open(name, options, &status, server_name);
+ if (client == nullptr) {
error.Format(jack_output_domain, status,
"Failed to connect to JACK server, status=%d",
status);
return false;
}
- jack_set_process_callback(jd->client, mpd_jack_process, jd);
- jack_on_shutdown(jd->client, mpd_jack_shutdown, jd);
+ jack_set_process_callback(client, mpd_jack_process, this);
+ jack_on_shutdown(client, mpd_jack_shutdown, this);
- for (unsigned i = 0; i < jd->num_source_ports; ++i) {
- jd->ports[i] = jack_port_register(jd->client,
- jd->source_ports[i],
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput, 0);
- if (jd->ports[i] == nullptr) {
+ for (unsigned i = 0; i < num_source_ports; ++i) {
+ ports[i] = jack_port_register(client,
+ source_ports[i].c_str(),
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput, 0);
+ if (ports[i] == nullptr) {
error.Format(jack_output_domain,
"Cannot register output port \"%s\"",
- jd->source_ports[i]);
- mpd_jack_disconnect(jd);
+ source_ports[i].c_str());
+ Disconnect();
return false;
}
}
@@ -282,23 +353,19 @@ mpd_jack_test_default_device(void)
}
static unsigned
-parse_port_list(const char *source, char **dest, Error &error)
+parse_port_list(const char *source, std::string dest[], Error &error)
{
- char **list = g_strsplit(source, ",", 0);
unsigned n = 0;
-
- for (n = 0; list[n] != nullptr; ++n) {
+ for (auto &&i : SplitString(source, ',')) {
if (n >= MAX_PORTS) {
error.Set(config_domain,
"too many port names");
return 0;
}
- dest[n] = list[n];
+ dest[n++] = std::move(i);
}
- g_free(list);
-
if (n == 0) {
error.Format(config_domain,
"at least one port name expected");
@@ -308,243 +375,221 @@ parse_port_list(const char *source, char **dest, Error &error)
return n;
}
-static AudioOutput *
-mpd_jack_init(const config_param &param, Error &error)
+bool
+JackOutput::Configure(const ConfigBlock &block, Error &error)
{
- JackOutput *jd = new JackOutput();
-
- if (!jd->Initialize(param, error)) {
- delete jd;
- return nullptr;
- }
-
- const char *value;
+ if (!base.Configure(block, error))
+ return false;
- jd->options = JackNullOption;
+ options = JackNullOption;
- jd->name = param.GetBlockValue("client_name", nullptr);
- if (jd->name != nullptr)
- jd->options = jack_options_t(jd->options | JackUseExactName);
+ name = block.GetBlockValue("client_name", nullptr);
+ if (name != nullptr)
+ options = jack_options_t(options | JackUseExactName);
else
/* if there's a no configured client name, we don't
care about the JackUseExactName option */
- jd->name = "Music Player Daemon";
+ name = "Music Player Daemon";
- jd->server_name = param.GetBlockValue("server_name", nullptr);
- if (jd->server_name != nullptr)
- jd->options = jack_options_t(jd->options | JackServerName);
+ server_name = block.GetBlockValue("server_name", nullptr);
+ if (server_name != nullptr)
+ options = jack_options_t(options | JackServerName);
- if (!param.GetBlockValue("autostart", false))
- jd->options = jack_options_t(jd->options | JackNoStartServer);
+ if (!block.GetBlockValue("autostart", false))
+ options = jack_options_t(options | JackNoStartServer);
/* configure the source ports */
- value = param.GetBlockValue("source_ports", "left,right");
- jd->num_source_ports = parse_port_list(value,
- jd->source_ports, error);
- if (jd->num_source_ports == 0)
- return nullptr;
+ const char *value = block.GetBlockValue("source_ports", "left,right");
+ num_source_ports = parse_port_list(value, source_ports, error);
+ if (num_source_ports == 0)
+ return false;
/* configure the destination ports */
- value = param.GetBlockValue("destination_ports", nullptr);
+ value = block.GetBlockValue("destination_ports", nullptr);
if (value == nullptr) {
/* compatibility with MPD < 0.16 */
- value = param.GetBlockValue("ports", nullptr);
+ value = block.GetBlockValue("ports", nullptr);
if (value != nullptr)
FormatWarning(jack_output_domain,
"deprecated option 'ports' in line %d",
- param.line);
+ block.line);
}
if (value != nullptr) {
- jd->num_destination_ports =
- parse_port_list(value,
- jd->destination_ports, error);
- if (jd->num_destination_ports == 0)
- return nullptr;
+ num_destination_ports =
+ parse_port_list(value, destination_ports, error);
+ if (num_destination_ports == 0)
+ return false;
} else {
- jd->num_destination_ports = 0;
+ num_destination_ports = 0;
}
- if (jd->num_destination_ports > 0 &&
- jd->num_destination_ports != jd->num_source_ports)
+ if (num_destination_ports > 0 &&
+ num_destination_ports != num_source_ports)
FormatWarning(jack_output_domain,
"number of source ports (%u) mismatches the "
"number of destination ports (%u) in line %d",
- jd->num_source_ports, jd->num_destination_ports,
- param.line);
-
- jd->ringbuffer_size = param.GetBlockValue("ringbuffer_size", 32768u);
+ num_source_ports, num_destination_ports,
+ block.line);
- jack_set_error_function(mpd_jack_error);
+ ringbuffer_size = block.GetBlockValue("ringbuffer_size", 32768u);
-#ifdef HAVE_JACK_SET_INFO_FUNCTION
- jack_set_info_function(mpd_jack_info);
-#endif
-
- return &jd->base;
+ return true;
}
-static void
-mpd_jack_finish(AudioOutput *ao)
+inline bool
+JackOutput::Enable(Error &error)
{
- JackOutput *jd = (JackOutput *)ao;
-
- for (unsigned i = 0; i < jd->num_source_ports; ++i)
- g_free(jd->source_ports[i]);
+ for (unsigned i = 0; i < num_source_ports; ++i)
+ ringbuffer[i] = nullptr;
- for (unsigned i = 0; i < jd->num_destination_ports; ++i)
- g_free(jd->destination_ports[i]);
-
- delete jd;
+ return Connect(error);
}
-static bool
-mpd_jack_enable(AudioOutput *ao, Error &error)
+inline void
+JackOutput::Disable()
{
- JackOutput *jd = (JackOutput *)ao;
+ if (client != nullptr)
+ Disconnect();
- for (unsigned i = 0; i < jd->num_source_ports; ++i)
- jd->ringbuffer[i] = nullptr;
-
- return mpd_jack_connect(jd, error);
+ for (unsigned i = 0; i < num_source_ports; ++i) {
+ if (ringbuffer[i] != nullptr) {
+ jack_ringbuffer_free(ringbuffer[i]);
+ ringbuffer[i] = nullptr;
+ }
+ }
}
-static void
-mpd_jack_disable(AudioOutput *ao)
+static AudioOutput *
+mpd_jack_init(const ConfigBlock &block, Error &error)
{
- JackOutput *jd = (JackOutput *)ao;
-
- if (jd->client != nullptr)
- mpd_jack_disconnect(jd);
+ JackOutput *jd = new JackOutput();
- for (unsigned i = 0; i < jd->num_source_ports; ++i) {
- if (jd->ringbuffer[i] != nullptr) {
- jack_ringbuffer_free(jd->ringbuffer[i]);
- jd->ringbuffer[i] = nullptr;
- }
+ if (!jd->Configure(block, error)) {
+ delete jd;
+ return nullptr;
}
+
+ jack_set_error_function(mpd_jack_error);
+
+#ifdef HAVE_JACK_SET_INFO_FUNCTION
+ jack_set_info_function(mpd_jack_info);
+#endif
+
+ return &jd->base;
}
/**
* Stops the playback on the JACK connection.
*/
-static void
-mpd_jack_stop(JackOutput *jd)
+void
+JackOutput::Stop()
{
- assert(jd != nullptr);
-
- if (jd->client == nullptr)
+ if (client == nullptr)
return;
- if (jd->shutdown)
+ if (shutdown)
/* the connection has failed; close it */
- mpd_jack_disconnect(jd);
+ Disconnect();
else
/* the connection is alive: just stop playback */
- jack_deactivate(jd->client);
+ jack_deactivate(client);
}
-static bool
-mpd_jack_start(JackOutput *jd, Error &error)
+inline bool
+JackOutput::Start(Error &error)
{
- const char *destination_ports[MAX_PORTS], **jports;
- const char *duplicate_port = nullptr;
- unsigned num_destination_ports;
-
- assert(jd->client != nullptr);
- assert(jd->audio_format.channels <= jd->num_source_ports);
+ assert(client != nullptr);
+ assert(audio_format.channels <= num_source_ports);
/* allocate the ring buffers on the first open(); these
persist until MPD exits. It's too unsafe to delete them
because we can never know when mpd_jack_process() gets
called */
- for (unsigned i = 0; i < jd->num_source_ports; ++i) {
- if (jd->ringbuffer[i] == nullptr)
- jd->ringbuffer[i] =
- jack_ringbuffer_create(jd->ringbuffer_size);
+ for (unsigned i = 0; i < num_source_ports; ++i) {
+ if (ringbuffer[i] == nullptr)
+ ringbuffer[i] =
+ jack_ringbuffer_create(ringbuffer_size);
/* clear the ring buffer to be sure that data from
previous playbacks are gone */
- jack_ringbuffer_reset(jd->ringbuffer[i]);
+ jack_ringbuffer_reset(ringbuffer[i]);
}
- if ( jack_activate(jd->client) ) {
+ if ( jack_activate(client) ) {
error.Set(jack_output_domain, "cannot activate client");
- mpd_jack_stop(jd);
+ Stop();
return false;
}
- if (jd->num_destination_ports == 0) {
+ const char *dports[MAX_PORTS], **jports;
+ unsigned num_dports;
+ if (num_destination_ports == 0) {
/* no output ports were configured - ask libjack for
defaults */
- jports = jack_get_ports(jd->client, nullptr, nullptr,
+ jports = jack_get_ports(client, nullptr, nullptr,
JackPortIsPhysical | JackPortIsInput);
if (jports == nullptr) {
error.Set(jack_output_domain, "no ports found");
- mpd_jack_stop(jd);
+ Stop();
return false;
}
assert(*jports != nullptr);
- for (num_destination_ports = 0;
- num_destination_ports < MAX_PORTS &&
- jports[num_destination_ports] != nullptr;
- ++num_destination_ports) {
+ for (num_dports = 0; num_dports < MAX_PORTS &&
+ jports[num_dports] != nullptr;
+ ++num_dports) {
FormatDebug(jack_output_domain,
"destination_port[%u] = '%s'\n",
- num_destination_ports,
- jports[num_destination_ports]);
- destination_ports[num_destination_ports] =
- jports[num_destination_ports];
+ num_dports,
+ jports[num_dports]);
+ dports[num_dports] = jports[num_dports];
}
} else {
/* use the configured output ports */
- num_destination_ports = jd->num_destination_ports;
- memcpy(destination_ports, jd->destination_ports,
- num_destination_ports * sizeof(*destination_ports));
+ num_dports = num_destination_ports;
+ for (unsigned i = 0; i < num_dports; ++i)
+ dports[i] = destination_ports[i].c_str();
jports = nullptr;
}
- assert(num_destination_ports > 0);
+ assert(num_dports > 0);
- if (jd->audio_format.channels >= 2 && num_destination_ports == 1) {
+ const char *duplicate_port = nullptr;
+ if (audio_format.channels >= 2 && num_dports == 1) {
/* mix stereo signal on one speaker */
- while (num_destination_ports < jd->audio_format.channels)
- destination_ports[num_destination_ports++] =
- destination_ports[0];
- } else if (num_destination_ports > jd->audio_format.channels) {
- if (jd->audio_format.channels == 1 && num_destination_ports > 2) {
+ std::fill(dports + num_dports, dports + audio_format.channels,
+ dports[0]);
+ } else if (num_dports > audio_format.channels) {
+ if (audio_format.channels == 1 && num_dports > 2) {
/* mono input file: connect the one source
channel to the both destination channels */
- duplicate_port = destination_ports[1];
- num_destination_ports = 1;
+ duplicate_port = dports[1];
+ num_dports = 1;
} else
/* connect only as many ports as we need */
- num_destination_ports = jd->audio_format.channels;
+ num_dports = audio_format.channels;
}
- assert(num_destination_ports <= jd->num_source_ports);
-
- for (unsigned i = 0; i < num_destination_ports; ++i) {
- int ret;
+ assert(num_dports <= num_source_ports);
- ret = jack_connect(jd->client, jack_port_name(jd->ports[i]),
- destination_ports[i]);
+ for (unsigned i = 0; i < num_dports; ++i) {
+ int ret = jack_connect(client, jack_port_name(ports[i]),
+ dports[i]);
if (ret != 0) {
error.Format(jack_output_domain,
- "Not a valid JACK port: %s",
- destination_ports[i]);
+ "Not a valid JACK port: %s", dports[i]);
if (jports != nullptr)
free(jports);
- mpd_jack_stop(jd);
+ Stop();
return false;
}
}
@@ -554,7 +599,7 @@ mpd_jack_start(JackOutput *jd, Error &error)
the both destination channels */
int ret;
- ret = jack_connect(jd->client, jack_port_name(jd->ports[0]),
+ ret = jack_connect(client, jack_port_name(ports[0]),
duplicate_port);
if (ret != 0) {
error.Format(jack_output_domain,
@@ -564,7 +609,7 @@ mpd_jack_start(JackOutput *jd, Error &error)
if (jports != nullptr)
free(jports);
- mpd_jack_stop(jd);
+ Stop();
return false;
}
}
@@ -575,188 +620,119 @@ mpd_jack_start(JackOutput *jd, Error &error)
return true;
}
-static bool
-mpd_jack_open(AudioOutput *ao, AudioFormat &audio_format,
- Error &error)
+inline bool
+JackOutput::Open(AudioFormat &new_audio_format, Error &error)
{
- JackOutput *jd = (JackOutput *)ao;
+ pause = false;
- assert(jd != nullptr);
+ if (client != nullptr && shutdown)
+ Disconnect();
- jd->pause = false;
-
- if (jd->client != nullptr && jd->shutdown)
- mpd_jack_disconnect(jd);
-
- if (jd->client == nullptr && !mpd_jack_connect(jd, error))
+ if (client == nullptr && !Connect(error))
return false;
- set_audioformat(jd, audio_format);
- jd->audio_format = audio_format;
+ set_audioformat(this, new_audio_format);
+ audio_format = new_audio_format;
- if (!mpd_jack_start(jd, error))
- return false;
-
- return true;
+ return Start(error);
}
-static void
-mpd_jack_close(gcc_unused AudioOutput *ao)
+inline size_t
+JackOutput::WriteSamples(const float *src, size_t n_frames)
{
- JackOutput *jd = (JackOutput *)ao;
+ assert(n_frames > 0);
- mpd_jack_stop(jd);
-}
+ const unsigned n_channels = audio_format.channels;
-static unsigned
-mpd_jack_delay(AudioOutput *ao)
-{
- JackOutput *jd = (JackOutput *)ao;
+ float *dest[MAX_CHANNELS];
+ size_t space = -1;
+ for (unsigned i = 0; i < n_channels; ++i) {
+ jack_ringbuffer_data_t d[2];
+ jack_ringbuffer_get_write_vector(ringbuffer[i], d);
- return jd->base.pause && jd->pause && !jd->shutdown
- ? 1000
- : 0;
-}
+ /* choose the first non-empty writable area */
+ const jack_ringbuffer_data_t &e = d[d[0].len == 0];
-static inline jack_default_audio_sample_t
-sample_16_to_jack(int16_t sample)
-{
- return sample / (jack_default_audio_sample_t)(1 << (16 - 1));
-}
+ if (e.len < space)
+ /* send data symmetrically */
+ space = e.len;
-static void
-mpd_jack_write_samples_16(JackOutput *jd, const int16_t *src,
- unsigned num_samples)
-{
- jack_default_audio_sample_t sample;
- unsigned i;
-
- while (num_samples-- > 0) {
- for (i = 0; i < jd->audio_format.channels; ++i) {
- sample = sample_16_to_jack(*src++);
- jack_ringbuffer_write(jd->ringbuffer[i],
- (const char *)&sample,
- sizeof(sample));
- }
+ dest[i] = (float *)e.buf;
}
-}
-static inline jack_default_audio_sample_t
-sample_24_to_jack(int32_t sample)
-{
- return sample / (jack_default_audio_sample_t)(1 << (24 - 1));
-}
+ space /= jack_sample_size;
+ if (space == 0)
+ return 0;
-static void
-mpd_jack_write_samples_24(JackOutput *jd, const int32_t *src,
- unsigned num_samples)
-{
- jack_default_audio_sample_t sample;
- unsigned i;
-
- while (num_samples-- > 0) {
- for (i = 0; i < jd->audio_format.channels; ++i) {
- sample = sample_24_to_jack(*src++);
- jack_ringbuffer_write(jd->ringbuffer[i],
- (const char *)&sample,
- sizeof(sample));
- }
- }
-}
+ const size_t result = n_frames = std::min(space, n_frames);
-static void
-mpd_jack_write_samples(JackOutput *jd, const void *src,
- unsigned num_samples)
-{
- switch (jd->audio_format.format) {
- case SampleFormat::S16:
- mpd_jack_write_samples_16(jd, (const int16_t*)src,
- num_samples);
- break;
-
- case SampleFormat::S24_P32:
- mpd_jack_write_samples_24(jd, (const int32_t*)src,
- num_samples);
- break;
-
- default:
- assert(false);
- gcc_unreachable();
- }
+ while (n_frames-- > 0)
+ for (unsigned i = 0; i < n_channels; ++i)
+ *dest[i]++ = *src++;
+
+ const size_t per_channel_advance = result * jack_sample_size;
+ for (unsigned i = 0; i < n_channels; ++i)
+ jack_ringbuffer_write_advance(ringbuffer[i],
+ per_channel_advance);
+
+ return result;
}
-static size_t
-mpd_jack_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+JackOutput::Play(const void *chunk, size_t size, Error &error)
{
- JackOutput *jd = (JackOutput *)ao;
- const size_t frame_size = jd->audio_format.GetFrameSize();
- size_t space = 0, space1;
-
- jd->pause = false;
+ pause = false;
+ const size_t frame_size = audio_format.GetFrameSize();
assert(size % frame_size == 0);
size /= frame_size;
while (true) {
- if (jd->shutdown) {
+ if (shutdown) {
error.Set(jack_output_domain,
"Refusing to play, because "
"there is no client thread");
return 0;
}
- space = jack_ringbuffer_write_space(jd->ringbuffer[0]);
- for (unsigned i = 1; i < jd->audio_format.channels; ++i) {
- space1 = jack_ringbuffer_write_space(jd->ringbuffer[i]);
- if (space > space1)
- /* send data symmetrically */
- space = space1;
- }
-
- if (space >= jack_sample_size)
- break;
+ size_t frames_written =
+ WriteSamples((const float *)chunk, size);
+ if (frames_written > 0)
+ return frames_written * frame_size;
/* XXX do something more intelligent to
synchronize */
- g_usleep(1000);
+ usleep(1000);
}
-
- space /= jack_sample_size;
- if (space < size)
- size = space;
-
- mpd_jack_write_samples(jd, chunk, size);
- return size * frame_size;
}
-static bool
-mpd_jack_pause(AudioOutput *ao)
+inline bool
+JackOutput::Pause()
{
- JackOutput *jd = (JackOutput *)ao;
-
- if (jd->shutdown)
+ if (shutdown)
return false;
- jd->pause = true;
+ pause = true;
return true;
}
+typedef AudioOutputWrapper<JackOutput> Wrapper;
+
const struct AudioOutputPlugin jack_output_plugin = {
"jack",
mpd_jack_test_default_device,
mpd_jack_init,
- mpd_jack_finish,
- mpd_jack_enable,
- mpd_jack_disable,
- mpd_jack_open,
- mpd_jack_close,
- mpd_jack_delay,
+ &Wrapper::Finish,
+ &Wrapper::Enable,
+ &Wrapper::Disable,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- mpd_jack_play,
+ &Wrapper::Play,
nullptr,
nullptr,
- mpd_jack_pause,
+ &Wrapper::Pause,
nullptr,
};
diff --git a/src/output/plugins/JackOutputPlugin.hxx b/src/output/plugins/JackOutputPlugin.hxx
index 6f1f7ecb9..f76431690 100644
--- a/src/output/plugins/JackOutputPlugin.hxx
+++ b/src/output/plugins/JackOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/NullOutputPlugin.cxx b/src/output/plugins/NullOutputPlugin.cxx
index 098f58926..e1731f0fe 100644
--- a/src/output/plugins/NullOutputPlugin.cxx
+++ b/src/output/plugins/NullOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,119 +20,94 @@
#include "config.h"
#include "NullOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "../Timer.hxx"
-struct NullOutput {
+class NullOutput {
+ friend struct AudioOutputWrapper<NullOutput>;
+
AudioOutput base;
bool sync;
Timer *timer;
+public:
NullOutput()
:base(null_output_plugin) {}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
- }
-};
-
-static AudioOutput *
-null_init(const config_param &param, Error &error)
-{
- NullOutput *nd = new NullOutput();
-
- if (!nd->Initialize(param, error)) {
- delete nd;
- return nullptr;
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
- nd->sync = param.GetBlockValue("sync", true);
+ static NullOutput *Create(const ConfigBlock &block, Error &error);
- return &nd->base;
-}
+ bool Open(AudioFormat &audio_format, gcc_unused Error &error) {
+ if (sync)
+ timer = new Timer(audio_format);
-static void
-null_finish(AudioOutput *ao)
-{
- NullOutput *nd = (NullOutput *)ao;
-
- delete nd;
-}
-
-static bool
-null_open(AudioOutput *ao, AudioFormat &audio_format,
- gcc_unused Error &error)
-{
- NullOutput *nd = (NullOutput *)ao;
-
- if (nd->sync)
- nd->timer = new Timer(audio_format);
+ return true;
+ }
- return true;
-}
+ void Close() {
+ if (sync)
+ delete timer;
+ }
-static void
-null_close(AudioOutput *ao)
-{
- NullOutput *nd = (NullOutput *)ao;
+ unsigned Delay() const {
+ return sync && timer->IsStarted()
+ ? timer->GetDelay()
+ : 0;
+ }
- if (nd->sync)
- delete nd->timer;
-}
+ size_t Play(gcc_unused const void *chunk, size_t size,
+ gcc_unused Error &error) {
+ if (sync) {
+ if (!timer->IsStarted())
+ timer->Start();
+ timer->Add(size);
+ }
-static unsigned
-null_delay(AudioOutput *ao)
-{
- NullOutput *nd = (NullOutput *)ao;
+ return size;
+ }
- return nd->sync && nd->timer->IsStarted()
- ? nd->timer->GetDelay()
- : 0;
-}
+ void Cancel() {
+ if (sync)
+ timer->Reset();
+ }
+};
-static size_t
-null_play(AudioOutput *ao, gcc_unused const void *chunk, size_t size,
- gcc_unused Error &error)
+inline NullOutput *
+NullOutput::Create(const ConfigBlock &block, Error &error)
{
- NullOutput *nd = (NullOutput *)ao;
- Timer *timer = nd->timer;
+ NullOutput *nd = new NullOutput();
- if (!nd->sync)
- return size;
+ if (!nd->Initialize(block, error)) {
+ delete nd;
+ return nullptr;
+ }
- if (!timer->IsStarted())
- timer->Start();
- timer->Add(size);
+ nd->sync = block.GetBlockValue("sync", true);
- return size;
+ return nd;
}
-static void
-null_cancel(AudioOutput *ao)
-{
- NullOutput *nd = (NullOutput *)ao;
-
- if (!nd->sync)
- return;
-
- nd->timer->Reset();
-}
+typedef AudioOutputWrapper<NullOutput> Wrapper;
const struct AudioOutputPlugin null_output_plugin = {
"null",
nullptr,
- null_init,
- null_finish,
+ &Wrapper::Init,
+ &Wrapper::Finish,
nullptr,
nullptr,
- null_open,
- null_close,
- null_delay,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- null_play,
+ &Wrapper::Play,
nullptr,
- null_cancel,
+ &Wrapper::Cancel,
nullptr,
nullptr,
};
diff --git a/src/output/plugins/NullOutputPlugin.hxx b/src/output/plugins/NullOutputPlugin.hxx
index f25f5b9f3..9a1d1558b 100644
--- a/src/output/plugins/NullOutputPlugin.hxx
+++ b/src/output/plugins/NullOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index 13ac7b35e..16c042ba3 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -61,17 +61,17 @@ osx_output_test_default_device(void)
}
static void
-osx_output_configure(OSXOutput *oo, const config_param &param)
+osx_output_configure(OSXOutput *oo, const ConfigBlock &block)
{
- const char *device = param.GetBlockValue("device");
+ const char *device = block.GetBlockValue("device");
- if (device == NULL || 0 == strcmp(device, "default")) {
+ if (device == nullptr || 0 == strcmp(device, "default")) {
oo->component_subtype = kAudioUnitSubType_DefaultOutput;
- oo->device_name = NULL;
+ oo->device_name = nullptr;
}
else if (0 == strcmp(device, "system")) {
oo->component_subtype = kAudioUnitSubType_SystemOutput;
- oo->device_name = NULL;
+ oo->device_name = nullptr;
}
else {
oo->component_subtype = kAudioUnitSubType_HALOutput;
@@ -81,15 +81,15 @@ osx_output_configure(OSXOutput *oo, const config_param &param)
}
static AudioOutput *
-osx_output_init(const config_param &param, Error &error)
+osx_output_init(const ConfigBlock &block, Error &error)
{
OSXOutput *oo = new OSXOutput();
- if (!oo->base.Configure(param, error)) {
+ if (!oo->base.Configure(block, error)) {
delete oo;
- return NULL;
+ return nullptr;
}
- osx_output_configure(oo, param);
+ osx_output_configure(oo, block);
return &oo->base;
}
@@ -108,7 +108,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
bool ret = true;
OSStatus status;
UInt32 size, numdevices;
- AudioDeviceID *deviceids = NULL;
+ AudioDeviceID *deviceids = nullptr;
char name[256];
unsigned int i;
@@ -118,7 +118,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
/* how many audio devices are there? */
status = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
&size,
- NULL);
+ nullptr);
if (status != noErr) {
error.Format(osx_output_domain, status,
"Unable to determine number of OS X audio devices: %s",
@@ -206,7 +206,7 @@ osx_render(void *vdata,
AudioBuffer *buffer = &buffer_list->mBuffers[0];
size_t buffer_size = buffer->mDataByteSize;
- assert(od->buffer != NULL);
+ assert(od->buffer != nullptr);
od->mutex.lock();
@@ -245,7 +245,7 @@ osx_output_enable(AudioOutput *ao, Error &error)
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
- Component comp = FindNextComponent(NULL, &desc);
+ Component comp = FindNextComponent(nullptr, &desc);
if (comp == 0) {
error.Set(osx_output_domain,
"Error finding OS X component");
diff --git a/src/output/plugins/OSXOutputPlugin.hxx b/src/output/plugins/OSXOutputPlugin.hxx
index d7aed40b6..89cd3fe91 100644
--- a/src/output/plugins/OSXOutputPlugin.hxx
+++ b/src/output/plugins/OSXOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx
index 2f095c0a4..eb55c6e9b 100644
--- a/src/output/plugins/OpenALOutputPlugin.cxx
+++ b/src/output/plugins/OpenALOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "OpenALOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -33,10 +34,12 @@
#include <OpenAL/alc.h>
#endif
-/* should be enough for buffer size = 2048 */
-#define NUM_BUFFERS 16
+class OpenALOutput {
+ friend struct AudioOutputWrapper<OpenALOutput>;
+
+ /* should be enough for buffer size = 2048 */
+ static constexpr unsigned NUM_BUFFERS = 16;
-struct OpenALOutput {
AudioOutput base;
const char *device_name;
@@ -51,9 +54,47 @@ struct OpenALOutput {
OpenALOutput()
:base(openal_output_plugin) {}
- bool Initialize(const config_param &param, Error &error_r) {
- return base.Configure(param, error_r);
+ bool Configure(const ConfigBlock &block, Error &error);
+
+ static OpenALOutput *Create(const ConfigBlock &block, Error &error);
+
+ bool Open(AudioFormat &audio_format, Error &error);
+
+ void Close();
+
+ gcc_pure
+ unsigned Delay() const {
+ return filled < NUM_BUFFERS || HasProcessed()
+ ? 0
+ /* we don't know exactly how long we must wait
+ for the next buffer to finish, so this is a
+ random guess: */
+ : 50;
+ }
+
+ size_t Play(const void *chunk, size_t size, Error &error);
+
+ void Cancel();
+
+private:
+ gcc_pure
+ ALint GetSourceI(ALenum param) const {
+ ALint value;
+ alGetSourcei(source, param, &value);
+ return value;
+ }
+
+ gcc_pure
+ bool HasProcessed() const {
+ return GetSourceI(AL_BUFFERS_PROCESSED) > 0;
}
+
+ gcc_pure
+ bool IsPlaying() const {
+ return GetSourceI(AL_SOURCE_STATE) == AL_PLAYING;
+ }
+
+ bool SetupContext(Error &error);
};
static constexpr Domain openal_output_domain("openal_output");
@@ -83,200 +124,154 @@ openal_audio_format(AudioFormat &audio_format)
}
}
-gcc_pure
-static inline ALint
-openal_get_source_i(const OpenALOutput *od, ALenum param)
-{
- ALint value;
- alGetSourcei(od->source, param, &value);
- return value;
-}
-
-gcc_pure
-static inline bool
-openal_has_processed(const OpenALOutput *od)
-{
- return openal_get_source_i(od, AL_BUFFERS_PROCESSED) > 0;
-}
-
-gcc_pure
-static inline ALint
-openal_is_playing(const OpenALOutput *od)
-{
- return openal_get_source_i(od, AL_SOURCE_STATE) == AL_PLAYING;
-}
-
-static bool
-openal_setup_context(OpenALOutput *od, Error &error)
+inline bool
+OpenALOutput::SetupContext(Error &error)
{
- od->device = alcOpenDevice(od->device_name);
+ device = alcOpenDevice(device_name);
- if (od->device == nullptr) {
+ if (device == nullptr) {
error.Format(openal_output_domain,
"Error opening OpenAL device \"%s\"",
- od->device_name);
+ device_name);
return false;
}
- od->context = alcCreateContext(od->device, nullptr);
+ context = alcCreateContext(device, nullptr);
- if (od->context == nullptr) {
+ if (context == nullptr) {
error.Format(openal_output_domain,
"Error creating context for \"%s\"",
- od->device_name);
- alcCloseDevice(od->device);
+ device_name);
+ alcCloseDevice(device);
return false;
}
return true;
}
-static AudioOutput *
-openal_init(const config_param &param, Error &error)
+inline bool
+OpenALOutput::Configure(const ConfigBlock &block, Error &error)
{
- const char *device_name = param.GetBlockValue("device");
- if (device_name == nullptr) {
- device_name = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
- }
-
- OpenALOutput *od = new OpenALOutput();
- if (!od->Initialize(param, error)) {
- delete od;
- return nullptr;
- }
+ if (!base.Configure(block, error))
+ return false;
- od->device_name = device_name;
+ device_name = block.GetBlockValue("device");
+ if (device_name == nullptr)
+ device_name = alcGetString(nullptr,
+ ALC_DEFAULT_DEVICE_SPECIFIER);
- return &od->base;
+ return true;
}
-static void
-openal_finish(AudioOutput *ao)
+inline OpenALOutput *
+OpenALOutput::Create(const ConfigBlock &block, Error &error)
{
- OpenALOutput *od = (OpenALOutput *)ao;
+ OpenALOutput *oo = new OpenALOutput();
+
+ if (!oo->Configure(block, error)) {
+ delete oo;
+ return nullptr;
+ }
- delete od;
+ return oo;
}
-static bool
-openal_open(AudioOutput *ao, AudioFormat &audio_format,
- Error &error)
+inline bool
+OpenALOutput::Open(AudioFormat &audio_format, Error &error)
{
- OpenALOutput *od = (OpenALOutput *)ao;
+ format = openal_audio_format(audio_format);
- od->format = openal_audio_format(audio_format);
-
- if (!openal_setup_context(od, error)) {
+ if (!SetupContext(error))
return false;
- }
- alcMakeContextCurrent(od->context);
- alGenBuffers(NUM_BUFFERS, od->buffers);
+ alcMakeContextCurrent(context);
+ alGenBuffers(NUM_BUFFERS, buffers);
if (alGetError() != AL_NO_ERROR) {
error.Set(openal_output_domain, "Failed to generate buffers");
return false;
}
- alGenSources(1, &od->source);
+ alGenSources(1, &source);
if (alGetError() != AL_NO_ERROR) {
error.Set(openal_output_domain, "Failed to generate source");
- alDeleteBuffers(NUM_BUFFERS, od->buffers);
+ alDeleteBuffers(NUM_BUFFERS, buffers);
return false;
}
- od->filled = 0;
- od->frequency = audio_format.sample_rate;
+ filled = 0;
+ frequency = audio_format.sample_rate;
return true;
}
-static void
-openal_close(AudioOutput *ao)
+inline void
+OpenALOutput::Close()
{
- OpenALOutput *od = (OpenALOutput *)ao;
-
- alcMakeContextCurrent(od->context);
- alDeleteSources(1, &od->source);
- alDeleteBuffers(NUM_BUFFERS, od->buffers);
- alcDestroyContext(od->context);
- alcCloseDevice(od->device);
+ alcMakeContextCurrent(context);
+ alDeleteSources(1, &source);
+ alDeleteBuffers(NUM_BUFFERS, buffers);
+ alcDestroyContext(context);
+ alcCloseDevice(device);
}
-static unsigned
-openal_delay(AudioOutput *ao)
+inline size_t
+OpenALOutput::Play(const void *chunk, size_t size, gcc_unused Error &error)
{
- OpenALOutput *od = (OpenALOutput *)ao;
-
- return od->filled < NUM_BUFFERS || openal_has_processed(od)
- ? 0
- /* we don't know exactly how long we must wait for the
- next buffer to finish, so this is a random
- guess: */
- : 50;
-}
+ if (alcGetCurrentContext() != context)
+ alcMakeContextCurrent(context);
-static size_t
-openal_play(AudioOutput *ao, const void *chunk, size_t size,
- gcc_unused Error &error)
-{
- OpenALOutput *od = (OpenALOutput *)ao;
ALuint buffer;
-
- if (alcGetCurrentContext() != od->context) {
- alcMakeContextCurrent(od->context);
- }
-
- if (od->filled < NUM_BUFFERS) {
+ if (filled < NUM_BUFFERS) {
/* fill all buffers */
- buffer = od->buffers[od->filled];
- od->filled++;
+ buffer = buffers[filled];
+ filled++;
} else {
/* wait for processed buffer */
- while (!openal_has_processed(od))
+ while (!HasProcessed())
usleep(10);
- alSourceUnqueueBuffers(od->source, 1, &buffer);
+ alSourceUnqueueBuffers(source, 1, &buffer);
}
- alBufferData(buffer, od->format, chunk, size, od->frequency);
- alSourceQueueBuffers(od->source, 1, &buffer);
+ alBufferData(buffer, format, chunk, size, frequency);
+ alSourceQueueBuffers(source, 1, &buffer);
- if (!openal_is_playing(od))
- alSourcePlay(od->source);
+ if (!IsPlaying())
+ alSourcePlay(source);
return size;
}
-static void
-openal_cancel(AudioOutput *ao)
+inline void
+OpenALOutput::Cancel()
{
- OpenALOutput *od = (OpenALOutput *)ao;
-
- od->filled = 0;
- alcMakeContextCurrent(od->context);
- alSourceStop(od->source);
+ filled = 0;
+ alcMakeContextCurrent(context);
+ alSourceStop(source);
/* force-unqueue all buffers */
- alSourcei(od->source, AL_BUFFER, 0);
- od->filled = 0;
+ alSourcei(source, AL_BUFFER, 0);
+ filled = 0;
}
+typedef AudioOutputWrapper<OpenALOutput> Wrapper;
+
const struct AudioOutputPlugin openal_output_plugin = {
"openal",
nullptr,
- openal_init,
- openal_finish,
+ &Wrapper::Init,
+ &Wrapper::Finish,
nullptr,
nullptr,
- openal_open,
- openal_close,
- openal_delay,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- openal_play,
+ &Wrapper::Play,
nullptr,
- openal_cancel,
+ &Wrapper::Cancel,
nullptr,
nullptr,
};
diff --git a/src/output/plugins/OpenALOutputPlugin.hxx b/src/output/plugins/OpenALOutputPlugin.hxx
index a27e6b53c..abf4ffdb1 100644
--- a/src/output/plugins/OpenALOutputPlugin.hxx
+++ b/src/output/plugins/OpenALOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/OssOutputPlugin.cxx b/src/output/plugins/OssOutputPlugin.cxx
index 39d87fc35..7f75f4e31 100644
--- a/src/output/plugins/OssOutputPlugin.cxx
+++ b/src/output/plugins/OssOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "OssOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "mixer/MixerList.hxx"
#include "system/fd_util.h"
#include "util/ConstBuffer.hxx"
@@ -57,7 +58,9 @@
#include "util/Manual.hxx"
#endif
-struct OssOutput {
+class OssOutput {
+ friend struct AudioOutputWrapper<OssOutput>;
+
AudioOutput base;
#ifdef AFMT_S24_PACKED
@@ -79,13 +82,49 @@ struct OssOutput {
*/
int oss_format;
- OssOutput()
+public:
+ OssOutput(const char *_device=nullptr)
:base(oss_output_plugin),
- fd(-1), device(nullptr) {}
+ fd(-1), device(_device) {}
- bool Initialize(const config_param &param, Error &error_r) {
- return base.Configure(param, error_r);
+ bool Initialize(const ConfigBlock &block, Error &error_r) {
+ return base.Configure(block, error_r);
}
+
+ static OssOutput *Create(const ConfigBlock &block, Error &error);
+
+#ifdef AFMT_S24_PACKED
+ bool Enable(gcc_unused Error &error) {
+ pcm_export.Construct();
+ return true;
+ }
+
+ void Disable() {
+ pcm_export.Destruct();
+ }
+#endif
+
+ bool Open(AudioFormat &audio_format, Error &error);
+
+ void Close() {
+ DoClose();
+ }
+
+ size_t Play(const void *chunk, size_t size, Error &error);
+ void Cancel();
+
+private:
+ /**
+ * Sets up the OSS device which was opened before.
+ */
+ bool Setup(AudioFormat &audio_format, Error &error);
+
+ /**
+ * Reopen the device with the saved audio_format, without any probing.
+ */
+ bool Reopen(Error &error);
+
+ void DoClose();
};
static constexpr Domain oss_output_domain("oss_output");
@@ -124,7 +163,7 @@ oss_stat_device(const char *device, int *errno_r)
return OSS_STAT_NO_ERROR;
}
-static const char *default_devices[] = { "/dev/sound/dsp", "/dev/dsp" };
+static const char *const default_devices[] = { "/dev/sound/dsp", "/dev/dsp" };
static bool
oss_output_test_default_device(void)
@@ -147,24 +186,23 @@ oss_output_test_default_device(void)
return false;
}
-static AudioOutput *
+static OssOutput *
oss_open_default(Error &error)
{
int err[ARRAY_SIZE(default_devices)];
enum oss_stat ret[ARRAY_SIZE(default_devices)];
- const config_param empty;
+ const ConfigBlock empty;
for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) {
ret[i] = oss_stat_device(default_devices[i], &err[i]);
if (ret[i] == OSS_STAT_NO_ERROR) {
- OssOutput *od = new OssOutput();
+ OssOutput *od = new OssOutput(default_devices[i]);
if (!od->Initialize(empty, error)) {
delete od;
- return NULL;
+ return nullptr;
}
- od->device = default_devices[i];
- return &od->base;
+ return od;
}
}
@@ -194,62 +232,33 @@ oss_open_default(Error &error)
error.Set(oss_output_domain,
"error trying to open default OSS device");
- return NULL;
+ return nullptr;
}
-static AudioOutput *
-oss_output_init(const config_param &param, Error &error)
+inline OssOutput *
+OssOutput::Create(const ConfigBlock &block, Error &error)
{
- const char *device = param.GetBlockValue("device");
- if (device != NULL) {
+ const char *device = block.GetBlockValue("device");
+ if (device != nullptr) {
OssOutput *od = new OssOutput();
- if (!od->Initialize(param, error)) {
+ if (!od->Initialize(block, error)) {
delete od;
- return NULL;
+ return nullptr;
}
od->device = device;
- return &od->base;
+ return od;
}
return oss_open_default(error);
}
-static void
-oss_output_finish(AudioOutput *ao)
+void
+OssOutput::DoClose()
{
- OssOutput *od = (OssOutput *)ao;
-
- delete od;
-}
-
-#ifdef AFMT_S24_PACKED
-
-static bool
-oss_output_enable(AudioOutput *ao, gcc_unused Error &error)
-{
- OssOutput *od = (OssOutput *)ao;
-
- od->pcm_export.Construct();
- return true;
-}
-
-static void
-oss_output_disable(AudioOutput *ao)
-{
- OssOutput *od = (OssOutput *)ao;
-
- od->pcm_export.Destruct();
-}
-
-#endif
-
-static void
-oss_close(OssOutput *od)
-{
- if (od->fd >= 0)
- close(od->fd);
- od->fd = -1;
+ if (fd >= 0)
+ close(fd);
+ fd = -1;
}
/**
@@ -271,8 +280,8 @@ oss_try_ioctl_r(int fd, unsigned long request, int *value_r,
const char *msg, Error &error)
{
assert(fd >= 0);
- assert(value_r != NULL);
- assert(msg != NULL);
+ assert(value_r != nullptr);
+ assert(msg != nullptr);
assert(!error.IsDefined());
int ret = ioctl(fd, request, value_r);
@@ -380,7 +389,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
break;
}
- static const int sample_rates[] = { 48000, 44100, 0 };
+ static constexpr int sample_rates[] = { 48000, 44100, 0 };
for (unsigned i = 0; sample_rates[i] != 0; ++i) {
sample_rate = sample_rates[i];
if (sample_rate == (int)audio_format.sample_rate)
@@ -412,6 +421,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
* Convert a MPD sample format to its OSS counterpart. Returns
* AFMT_QUERY if there is no direct counterpart.
*/
+gcc_const
static int
sample_format_to_oss(SampleFormat format)
{
@@ -442,13 +452,15 @@ sample_format_to_oss(SampleFormat format)
#endif
}
- return AFMT_QUERY;
+ assert(false);
+ gcc_unreachable();
}
/**
* Convert an OSS sample format to its MPD counterpart. Returns
* SampleFormat::UNDEFINED if there is no direct counterpart.
*/
+gcc_const
static SampleFormat
sample_format_from_oss(int format)
{
@@ -572,7 +584,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
/* the requested sample format is not available - probe for
other formats supported by MPD */
- static const SampleFormat sample_formats[] = {
+ static constexpr SampleFormat sample_formats[] = {
SampleFormat::S24_P32,
SampleFormat::S32,
SampleFormat::S16,
@@ -609,18 +621,14 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
return false;
}
-/**
- * Sets up the OSS device which was opened before.
- */
-static bool
-oss_setup(OssOutput *od, AudioFormat &audio_format,
- Error &error)
+inline bool
+OssOutput::Setup(AudioFormat &_audio_format, Error &error)
{
- return oss_setup_channels(od->fd, audio_format, error) &&
- oss_setup_sample_rate(od->fd, audio_format, error) &&
- oss_setup_sample_format(od->fd, audio_format, &od->oss_format,
+ return oss_setup_channels(fd, _audio_format, error) &&
+ oss_setup_sample_rate(fd, _audio_format, error) &&
+ oss_setup_sample_format(fd, _audio_format, &oss_format,
#ifdef AFMT_S24_PACKED
- od->pcm_export,
+ pcm_export,
#endif
error);
}
@@ -628,46 +636,46 @@ oss_setup(OssOutput *od, AudioFormat &audio_format,
/**
* Reopen the device with the saved audio_format, without any probing.
*/
-static bool
-oss_reopen(OssOutput *od, Error &error)
+inline bool
+OssOutput::Reopen(Error &error)
{
- assert(od->fd < 0);
+ assert(fd < 0);
- od->fd = open_cloexec(od->device, O_WRONLY, 0);
- if (od->fd < 0) {
+ fd = open_cloexec(device, O_WRONLY, 0);
+ if (fd < 0) {
error.FormatErrno("Error opening OSS device \"%s\"",
- od->device);
+ device);
return false;
}
enum oss_setup_result result;
const char *const msg1 = "Failed to set channel count";
- result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS,
- od->audio_format.channels, msg1, error);
+ result = oss_try_ioctl(fd, SNDCTL_DSP_CHANNELS,
+ audio_format.channels, msg1, error);
if (result != SUCCESS) {
- oss_close(od);
+ DoClose();
if (result == UNSUPPORTED)
error.Set(oss_output_domain, msg1);
return false;
}
const char *const msg2 = "Failed to set sample rate";
- result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED,
- od->audio_format.sample_rate, msg2, error);
+ result = oss_try_ioctl(fd, SNDCTL_DSP_SPEED,
+ audio_format.sample_rate, msg2, error);
if (result != SUCCESS) {
- oss_close(od);
+ DoClose();
if (result == UNSUPPORTED)
error.Set(oss_output_domain, msg2);
return false;
}
const char *const msg3 = "Failed to set sample format";
- result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE,
- od->oss_format,
+ result = oss_try_ioctl(fd, SNDCTL_DSP_SAMPLESIZE,
+ oss_format,
msg3, error);
if (result != SUCCESS) {
- oss_close(od);
+ DoClose();
if (result == UNSUPPORTED)
error.Set(oss_output_domain, msg3);
return false;
@@ -676,62 +684,47 @@ oss_reopen(OssOutput *od, Error &error)
return true;
}
-static bool
-oss_output_open(AudioOutput *ao, AudioFormat &audio_format,
- Error &error)
+inline bool
+OssOutput::Open(AudioFormat &_audio_format, Error &error)
{
- OssOutput *od = (OssOutput *)ao;
-
- od->fd = open_cloexec(od->device, O_WRONLY, 0);
- if (od->fd < 0) {
+ fd = open_cloexec(device, O_WRONLY, 0);
+ if (fd < 0) {
error.FormatErrno("Error opening OSS device \"%s\"",
- od->device);
+ device);
return false;
}
- if (!oss_setup(od, audio_format, error)) {
- oss_close(od);
+ if (!Setup(_audio_format, error)) {
+ DoClose();
return false;
}
- od->audio_format = audio_format;
+ audio_format = _audio_format;
return true;
}
-static void
-oss_output_close(AudioOutput *ao)
+inline void
+OssOutput::Cancel()
{
- OssOutput *od = (OssOutput *)ao;
-
- oss_close(od);
-}
-
-static void
-oss_output_cancel(AudioOutput *ao)
-{
- OssOutput *od = (OssOutput *)ao;
-
- if (od->fd >= 0) {
- ioctl(od->fd, SNDCTL_DSP_RESET, 0);
- oss_close(od);
+ if (fd >= 0) {
+ ioctl(fd, SNDCTL_DSP_RESET, 0);
+ DoClose();
}
}
-static size_t
-oss_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+OssOutput::Play(const void *chunk, size_t size, Error &error)
{
- 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))
+ if (fd < 0 && !Reopen(error))
return 0;
#ifdef AFMT_S24_PACKED
- const auto e = od->pcm_export->Export({chunk, size});
+ const auto e = pcm_export->Export({chunk, size});
chunk = e.data;
size = e.size;
#endif
@@ -739,40 +732,42 @@ oss_output_play(AudioOutput *ao, const void *chunk, size_t size,
assert(size > 0);
while (true) {
- ret = write(od->fd, chunk, size);
+ ret = write(fd, chunk, size);
if (ret > 0) {
#ifdef AFMT_S24_PACKED
- ret = od->pcm_export->CalcSourceSize(ret);
+ ret = pcm_export->CalcSourceSize(ret);
#endif
return ret;
}
if (ret < 0 && errno != EINTR) {
- error.FormatErrno("Write error on %s", od->device);
+ error.FormatErrno("Write error on %s", device);
return 0;
}
}
}
+typedef AudioOutputWrapper<OssOutput> Wrapper;
+
const struct AudioOutputPlugin oss_output_plugin = {
"oss",
oss_output_test_default_device,
- oss_output_init,
- oss_output_finish,
+ &Wrapper::Init,
+ &Wrapper::Finish,
#ifdef AFMT_S24_PACKED
- oss_output_enable,
- oss_output_disable,
+ &Wrapper::Enable,
+ &Wrapper::Disable,
#else
nullptr,
nullptr,
#endif
- oss_output_open,
- oss_output_close,
+ &Wrapper::Open,
+ &Wrapper::Close,
nullptr,
nullptr,
- oss_output_play,
+ &Wrapper::Play,
nullptr,
- oss_output_cancel,
+ &Wrapper::Cancel,
nullptr,
&oss_mixer_plugin,
diff --git a/src/output/plugins/OssOutputPlugin.hxx b/src/output/plugins/OssOutputPlugin.hxx
index f9970c8f0..8f9b3d424 100644
--- a/src/output/plugins/OssOutputPlugin.hxx
+++ b/src/output/plugins/OssOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx
index 7a1f32258..1e34ea98d 100644
--- a/src/output/plugins/PipeOutputPlugin.cxx
+++ b/src/output/plugins/PipeOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "PipeOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "config/ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -28,7 +29,9 @@
#include <stdio.h>
-struct PipeOutput {
+class PipeOutput {
+ friend struct AudioOutputWrapper<PipeOutput>;
+
AudioOutput base;
std::string cmd;
@@ -37,19 +40,30 @@ struct PipeOutput {
PipeOutput()
:base(pipe_output_plugin) {}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Configure(const ConfigBlock &block, Error &error);
+
+public:
+ static PipeOutput *Create(const ConfigBlock &block, Error &error);
+
+ bool Open(AudioFormat &audio_format, Error &error);
+
+ void Close() {
+ pclose(fh);
}
- bool Configure(const config_param &param, Error &error);
+ size_t Play(const void *chunk, size_t size, Error &error);
+
};
static constexpr Domain pipe_output_domain("pipe_output");
inline bool
-PipeOutput::Configure(const config_param &param, Error &error)
+PipeOutput::Configure(const ConfigBlock &block, Error &error)
{
- cmd = param.GetBlockValue("command", "");
+ if (!base.Configure(block, error))
+ return false;
+
+ cmd = block.GetBlockValue("command", "");
if (cmd.empty()) {
error.Set(config_domain,
"No \"command\" parameter specified");
@@ -59,83 +73,56 @@ PipeOutput::Configure(const config_param &param, Error &error)
return true;
}
-static AudioOutput *
-pipe_output_init(const config_param &param, Error &error)
+inline PipeOutput *
+PipeOutput::Create(const ConfigBlock &block, Error &error)
{
- PipeOutput *pd = new PipeOutput();
+ PipeOutput *po = new PipeOutput();
- if (!pd->Initialize(param, error)) {
- delete pd;
+ if (!po->Configure(block, error)) {
+ delete po;
return nullptr;
}
- if (!pd->Configure(param, error)) {
- delete pd;
- return nullptr;
- }
-
- return &pd->base;
-}
-
-static void
-pipe_output_finish(AudioOutput *ao)
-{
- PipeOutput *pd = (PipeOutput *)ao;
-
- delete pd;
+ return po;
}
-static bool
-pipe_output_open(AudioOutput *ao,
- gcc_unused AudioFormat &audio_format,
- Error &error)
+inline bool
+PipeOutput::Open(gcc_unused AudioFormat &audio_format, Error &error)
{
- PipeOutput *pd = (PipeOutput *)ao;
-
- pd->fh = popen(pd->cmd.c_str(), "w");
- if (pd->fh == nullptr) {
+ fh = popen(cmd.c_str(), "w");
+ if (fh == nullptr) {
error.FormatErrno("Error opening pipe \"%s\"",
- pd->cmd.c_str());
+ cmd.c_str());
return false;
}
return true;
}
-static void
-pipe_output_close(AudioOutput *ao)
+inline size_t
+PipeOutput::Play(const void *chunk, size_t size, Error &error)
{
- PipeOutput *pd = (PipeOutput *)ao;
-
- pclose(pd->fh);
-}
-
-static size_t
-pipe_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
-{
- PipeOutput *pd = (PipeOutput *)ao;
- size_t ret;
-
- ret = fwrite(chunk, 1, size, pd->fh);
- if (ret == 0)
+ size_t nbytes = fwrite(chunk, 1, size, fh);
+ if (nbytes == 0)
error.SetErrno("Write error on pipe");
- return ret;
+ return nbytes;
}
+typedef AudioOutputWrapper<PipeOutput> Wrapper;
+
const struct AudioOutputPlugin pipe_output_plugin = {
"pipe",
nullptr,
- pipe_output_init,
- pipe_output_finish,
+ &Wrapper::Init,
+ &Wrapper::Finish,
nullptr,
nullptr,
- pipe_output_open,
- pipe_output_close,
+ &Wrapper::Open,
+ &Wrapper::Close,
nullptr,
nullptr,
- pipe_output_play,
+ &Wrapper::Play,
nullptr,
nullptr,
nullptr,
diff --git a/src/output/plugins/PipeOutputPlugin.hxx b/src/output/plugins/PipeOutputPlugin.hxx
index bdaf2ecfd..5d92848c2 100644
--- a/src/output/plugins/PipeOutputPlugin.hxx
+++ b/src/output/plugins/PipeOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx
index 120bad090..8b5225584 100644
--- a/src/output/plugins/PulseOutputPlugin.cxx
+++ b/src/output/plugins/PulseOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,11 +19,14 @@
#include "config.h"
#include "PulseOutputPlugin.hxx"
+#include "lib/pulse/Domain.hxx"
+#include "lib/pulse/Error.hxx"
+#include "lib/pulse/LogError.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "mixer/MixerList.hxx"
#include "mixer/plugins/PulseMixerPlugin.hxx"
#include "util/Error.hxx"
-#include "util/Domain.hxx"
#include "Log.hxx"
#include <pulse/thread-mainloop.h>
@@ -31,7 +34,6 @@
#include <pulse/stream.h>
#include <pulse/introspect.h>
#include <pulse/subscribe.h>
-#include <pulse/error.h>
#include <pulse/version.h>
#include <assert.h>
@@ -40,7 +42,9 @@
#define MPD_PULSE_NAME "Music Player Daemon"
-struct PulseOutput {
+class PulseOutput {
+ friend struct AudioOutputWrapper<PulseOutput>;
+
AudioOutput base;
const char *name;
@@ -56,80 +60,190 @@ struct PulseOutput {
size_t writable;
PulseOutput()
- :base(pulse_output_plugin) {}
-};
+ :base(pulse_output_plugin),
+ mixer(nullptr),
+ mainloop(nullptr), stream(nullptr) {}
-static constexpr Domain pulse_output_domain("pulse_output");
+public:
+ void SetMixer(PulseMixer &_mixer);
-static void
-SetError(Error &error, pa_context *context, const char *msg)
-{
- const int e = pa_context_errno(context);
- error.Format(pulse_output_domain, e, "%s: %s", msg, pa_strerror(e));
-}
+ void ClearMixer(gcc_unused PulseMixer &old_mixer) {
+ assert(mixer == &old_mixer);
+
+ mixer = nullptr;
+ }
+
+ bool SetVolume(const pa_cvolume &volume, Error &error);
+
+ void Lock() {
+ pa_threaded_mainloop_lock(mainloop);
+ }
+
+ void Unlock() {
+ pa_threaded_mainloop_unlock(mainloop);
+ }
+
+ void OnContextStateChanged(pa_context_state_t new_state);
+ void OnServerLayoutChanged(pa_subscription_event_type_t t,
+ uint32_t idx);
+ void OnStreamSuspended(pa_stream *_stream);
+ void OnStreamStateChanged(pa_stream *_stream,
+ pa_stream_state_t new_state);
+ void OnStreamWrite(size_t nbytes);
+
+ void OnStreamSuccess() {
+ Signal();
+ }
+
+ gcc_const
+ static bool TestDefaultDevice();
+
+ bool Configure(const ConfigBlock &block, Error &error);
+ static PulseOutput *Create(const ConfigBlock &block, Error &error);
+
+ bool Enable(Error &error);
+ void Disable();
+
+ bool Open(AudioFormat &audio_format, Error &error);
+ void Close();
+
+ unsigned Delay();
+ size_t Play(const void *chunk, size_t size, Error &error);
+ void Cancel();
+ bool Pause();
+
+private:
+ /**
+ * Attempt to connect asynchronously to the PulseAudio server.
+ *
+ * @return true on success, false on error
+ */
+ bool Connect(Error &error);
+
+ /**
+ * Create, set up and connect a context.
+ *
+ * Caller must lock the main loop.
+ *
+ * @return true on success, false on error
+ */
+ bool SetupContext(Error &error);
+
+ /**
+ * Frees and clears the context.
+ *
+ * Caller must lock the main loop.
+ */
+ void DeleteContext();
+
+ void Signal() {
+ pa_threaded_mainloop_signal(mainloop, 0);
+ }
+
+ /**
+ * Check if the context is (already) connected, and waits if
+ * not. If the context has been disconnected, retry to
+ * connect.
+ *
+ * Caller must lock the main loop.
+ *
+ * @return true on success, false on error
+ */
+ bool WaitConnection(Error &error);
+
+ /**
+ * Create, set up and connect a context.
+ *
+ * Caller must lock the main loop.
+ *
+ * @return true on success, false on error
+ */
+ bool SetupStream(const pa_sample_spec &ss, Error &error);
+
+ /**
+ * Frees and clears the stream.
+ */
+ void DeleteStream();
+
+ /**
+ * Check if the stream is (already) connected, and waits if
+ * not. The mainloop must be locked before calling this
+ * function.
+ *
+ * @return true on success, false on error
+ */
+ bool WaitStream(Error &error);
+
+ /**
+ * Sets cork mode on the stream.
+ */
+ bool StreamPause(bool pause, Error &error);
+};
void
pulse_output_lock(PulseOutput &po)
{
- pa_threaded_mainloop_lock(po.mainloop);
+ po.Lock();
}
void
pulse_output_unlock(PulseOutput &po)
{
- pa_threaded_mainloop_unlock(po.mainloop);
+ po.Unlock();
}
-void
-pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm)
+inline void
+PulseOutput::SetMixer(PulseMixer &_mixer)
{
- assert(po.mixer == nullptr);
+ assert(mixer == nullptr);
- po.mixer = &pm;
+ mixer = &_mixer;
- if (po.mainloop == nullptr)
+ if (mainloop == nullptr)
return;
- pa_threaded_mainloop_lock(po.mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (po.context != nullptr &&
- pa_context_get_state(po.context) == PA_CONTEXT_READY) {
- pulse_mixer_on_connect(pm, po.context);
+ if (context != nullptr &&
+ pa_context_get_state(context) == PA_CONTEXT_READY) {
+ pulse_mixer_on_connect(_mixer, context);
- if (po.stream != nullptr &&
- pa_stream_get_state(po.stream) == PA_STREAM_READY)
- pulse_mixer_on_change(pm, po.context, po.stream);
+ if (stream != nullptr &&
+ pa_stream_get_state(stream) == PA_STREAM_READY)
+ pulse_mixer_on_change(_mixer, context, stream);
}
- pa_threaded_mainloop_unlock(po.mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
}
void
-pulse_output_clear_mixer(PulseOutput &po, gcc_unused PulseMixer &pm)
+pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm)
{
- assert(po.mixer == &pm);
-
- po.mixer = nullptr;
+ po.SetMixer(pm);
}
-bool
-pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume,
- Error &error)
+void
+pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm)
{
- pa_operation *o;
+ po.ClearMixer(pm);
+}
- if (po.context == nullptr || po.stream == nullptr ||
- pa_stream_get_state(po.stream) != PA_STREAM_READY) {
- error.Set(pulse_output_domain, "disconnected");
+inline bool
+PulseOutput::SetVolume(const pa_cvolume &volume, Error &error)
+{
+ if (context == nullptr || stream == nullptr ||
+ pa_stream_get_state(stream) != PA_STREAM_READY) {
+ error.Set(pulse_domain, "disconnected");
return false;
}
- o = pa_context_set_sink_input_volume(po.context,
- pa_stream_get_index(po.stream),
- volume, nullptr, nullptr);
+ pa_operation *o =
+ pa_context_set_sink_input_volume(context,
+ pa_stream_get_index(stream),
+ &volume, nullptr, nullptr);
if (o == nullptr) {
- SetError(error, po.context,
- "failed to set PulseAudio volume");
+ SetPulseError(error, context,
+ "failed to set PulseAudio volume");
return false;
}
@@ -137,6 +251,13 @@ pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume,
return true;
}
+bool
+pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume,
+ Error &error)
+{
+ return po.SetVolume(*volume, error);
+}
+
/**
* \brief waits for a pulseaudio operation to finish, frees it and
* unlocks the mainloop
@@ -169,32 +290,30 @@ static void
pulse_output_stream_success_cb(gcc_unused pa_stream *s,
gcc_unused int success, void *userdata)
{
- PulseOutput *po = (PulseOutput *)userdata;
+ PulseOutput &po = *(PulseOutput *)userdata;
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ po.OnStreamSuccess();
}
-static void
-pulse_output_context_state_cb(struct pa_context *context, void *userdata)
+inline void
+PulseOutput::OnContextStateChanged(pa_context_state_t new_state)
{
- PulseOutput *po = (PulseOutput *)userdata;
-
- switch (pa_context_get_state(context)) {
+ switch (new_state) {
case PA_CONTEXT_READY:
- if (po->mixer != nullptr)
- pulse_mixer_on_connect(*po->mixer, context);
+ if (mixer != nullptr)
+ pulse_mixer_on_connect(*mixer, context);
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ Signal();
break;
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
- if (po->mixer != nullptr)
- pulse_mixer_on_disconnect(*po->mixer);
+ if (mixer != nullptr)
+ pulse_mixer_on_disconnect(*mixer);
/* the caller thread might be waiting for these
states */
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ Signal();
break;
case PA_CONTEXT_UNCONNECTED:
@@ -206,230 +325,203 @@ pulse_output_context_state_cb(struct pa_context *context, void *userdata)
}
static void
-pulse_output_subscribe_cb(pa_context *context,
- pa_subscription_event_type_t t,
- uint32_t idx, void *userdata)
+pulse_output_context_state_cb(struct pa_context *context, void *userdata)
+{
+ PulseOutput &po = *(PulseOutput *)userdata;
+
+ po.OnContextStateChanged(pa_context_get_state(context));
+}
+
+inline void
+PulseOutput::OnServerLayoutChanged(pa_subscription_event_type_t t,
+ uint32_t idx)
{
- PulseOutput *po = (PulseOutput *)userdata;
pa_subscription_event_type_t facility =
pa_subscription_event_type_t(t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK);
pa_subscription_event_type_t type =
pa_subscription_event_type_t(t & PA_SUBSCRIPTION_EVENT_TYPE_MASK);
- if (po->mixer != nullptr &&
+ if (mixer != nullptr &&
facility == PA_SUBSCRIPTION_EVENT_SINK_INPUT &&
- po->stream != nullptr &&
- pa_stream_get_state(po->stream) == PA_STREAM_READY &&
- idx == pa_stream_get_index(po->stream) &&
+ stream != nullptr &&
+ pa_stream_get_state(stream) == PA_STREAM_READY &&
+ idx == pa_stream_get_index(stream) &&
(type == PA_SUBSCRIPTION_EVENT_NEW ||
type == PA_SUBSCRIPTION_EVENT_CHANGE))
- pulse_mixer_on_change(*po->mixer, context, po->stream);
+ pulse_mixer_on_change(*mixer, context, stream);
}
-/**
- * Attempt to connect asynchronously to the PulseAudio server.
- *
- * @return true on success, false on error
- */
-static bool
-pulse_output_connect(PulseOutput *po, Error &error)
+static void
+pulse_output_subscribe_cb(gcc_unused pa_context *context,
+ pa_subscription_event_type_t t,
+ uint32_t idx, void *userdata)
{
- assert(po != nullptr);
- assert(po->context != nullptr);
+ PulseOutput &po = *(PulseOutput *)userdata;
- if (pa_context_connect(po->context, po->server,
+ po.OnServerLayoutChanged(t, idx);
+}
+
+inline bool
+PulseOutput::Connect(Error &error)
+{
+ assert(context != nullptr);
+
+ if (pa_context_connect(context, server,
(pa_context_flags_t)0, nullptr) < 0) {
- SetError(error, po->context,
- "pa_context_connect() has failed");
+ SetPulseError(error, context,
+ "pa_context_connect() has failed");
return false;
}
return true;
}
-/**
- * Frees and clears the stream.
- */
-static void
-pulse_output_delete_stream(PulseOutput *po)
+void
+PulseOutput::DeleteStream()
{
- assert(po != nullptr);
- assert(po->stream != nullptr);
+ assert(stream != nullptr);
- pa_stream_set_suspended_callback(po->stream, nullptr, nullptr);
+ pa_stream_set_suspended_callback(stream, nullptr, nullptr);
- pa_stream_set_state_callback(po->stream, nullptr, nullptr);
- pa_stream_set_write_callback(po->stream, nullptr, nullptr);
+ pa_stream_set_state_callback(stream, nullptr, nullptr);
+ pa_stream_set_write_callback(stream, nullptr, nullptr);
- pa_stream_disconnect(po->stream);
- pa_stream_unref(po->stream);
- po->stream = nullptr;
+ pa_stream_disconnect(stream);
+ pa_stream_unref(stream);
+ stream = nullptr;
}
-/**
- * Frees and clears the context.
- *
- * Caller must lock the main loop.
- */
-static void
-pulse_output_delete_context(PulseOutput *po)
+void
+PulseOutput::DeleteContext()
{
- assert(po != nullptr);
- assert(po->context != nullptr);
+ assert(context != nullptr);
- pa_context_set_state_callback(po->context, nullptr, nullptr);
- pa_context_set_subscribe_callback(po->context, nullptr, nullptr);
+ pa_context_set_state_callback(context, nullptr, nullptr);
+ pa_context_set_subscribe_callback(context, nullptr, nullptr);
- pa_context_disconnect(po->context);
- pa_context_unref(po->context);
- po->context = nullptr;
+ pa_context_disconnect(context);
+ pa_context_unref(context);
+ context = nullptr;
}
-/**
- * Create, set up and connect a context.
- *
- * Caller must lock the main loop.
- *
- * @return true on success, false on error
- */
-static bool
-pulse_output_setup_context(PulseOutput *po, Error &error)
+bool
+PulseOutput::SetupContext(Error &error)
{
- assert(po != nullptr);
- assert(po->mainloop != nullptr);
+ assert(mainloop != nullptr);
- po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop),
- MPD_PULSE_NAME);
- if (po->context == nullptr) {
- error.Set(pulse_output_domain, "pa_context_new() has failed");
+ context = pa_context_new(pa_threaded_mainloop_get_api(mainloop),
+ MPD_PULSE_NAME);
+ if (context == nullptr) {
+ error.Set(pulse_domain, "pa_context_new() has failed");
return false;
}
- pa_context_set_state_callback(po->context,
- pulse_output_context_state_cb, po);
- pa_context_set_subscribe_callback(po->context,
- pulse_output_subscribe_cb, po);
+ pa_context_set_state_callback(context,
+ pulse_output_context_state_cb, this);
+ pa_context_set_subscribe_callback(context,
+ pulse_output_subscribe_cb, this);
- if (!pulse_output_connect(po, error)) {
- pulse_output_delete_context(po);
+ if (!Connect(error)) {
+ DeleteContext();
return false;
}
return true;
}
-static AudioOutput *
-pulse_output_init(const config_param &param, Error &error)
+inline bool
+PulseOutput::Configure(const ConfigBlock &block, Error &error)
{
- PulseOutput *po;
+ if (!base.Configure(block, error))
+ return false;
+
+ name = block.GetBlockValue("name", "mpd_pulse");
+ server = block.GetBlockValue("server");
+ sink = block.GetBlockValue("sink");
+ return true;
+}
+
+PulseOutput *
+PulseOutput::Create(const ConfigBlock &block, Error &error)
+{
setenv("PULSE_PROP_media.role", "music", true);
setenv("PULSE_PROP_application.icon_name", "mpd", true);
- po = new PulseOutput();
- if (!po->base.Configure(param, error)) {
+ auto *po = new PulseOutput();
+ if (!po->Configure(block, error)) {
delete po;
return nullptr;
}
- po->name = param.GetBlockValue("name", "mpd_pulse");
- po->server = param.GetBlockValue("server");
- po->sink = param.GetBlockValue("sink");
-
- po->mixer = nullptr;
- po->mainloop = nullptr;
- po->context = nullptr;
- po->stream = nullptr;
-
- return &po->base;
+ return po;
}
-static void
-pulse_output_finish(AudioOutput *ao)
+inline bool
+PulseOutput::Enable(Error &error)
{
- PulseOutput *po = (PulseOutput *)ao;
-
- delete po;
-}
-
-static bool
-pulse_output_enable(AudioOutput *ao, Error &error)
-{
- PulseOutput *po = (PulseOutput *)ao;
-
- assert(po->mainloop == nullptr);
- assert(po->context == nullptr);
+ assert(mainloop == nullptr);
/* create the libpulse mainloop and start the thread */
- po->mainloop = pa_threaded_mainloop_new();
- if (po->mainloop == nullptr) {
- error.Set(pulse_output_domain,
+ mainloop = pa_threaded_mainloop_new();
+ if (mainloop == nullptr) {
+ error.Set(pulse_domain,
"pa_threaded_mainloop_new() has failed");
return false;
}
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (pa_threaded_mainloop_start(po->mainloop) < 0) {
- pa_threaded_mainloop_unlock(po->mainloop);
- pa_threaded_mainloop_free(po->mainloop);
- po->mainloop = nullptr;
+ if (pa_threaded_mainloop_start(mainloop) < 0) {
+ pa_threaded_mainloop_unlock(mainloop);
+ pa_threaded_mainloop_free(mainloop);
+ mainloop = nullptr;
- error.Set(pulse_output_domain,
+ error.Set(pulse_domain,
"pa_threaded_mainloop_start() has failed");
return false;
}
/* create the libpulse context and connect it */
- if (!pulse_output_setup_context(po, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
- pa_threaded_mainloop_stop(po->mainloop);
- pa_threaded_mainloop_free(po->mainloop);
- po->mainloop = nullptr;
+ if (!SetupContext(error)) {
+ pa_threaded_mainloop_unlock(mainloop);
+ pa_threaded_mainloop_stop(mainloop);
+ pa_threaded_mainloop_free(mainloop);
+ mainloop = nullptr;
return false;
}
- pa_threaded_mainloop_unlock(po->mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
return true;
}
-static void
-pulse_output_disable(AudioOutput *ao)
+inline void
+PulseOutput::Disable()
{
- PulseOutput *po = (PulseOutput *)ao;
-
- assert(po->mainloop != nullptr);
+ assert(mainloop != nullptr);
- pa_threaded_mainloop_stop(po->mainloop);
- if (po->context != nullptr)
- pulse_output_delete_context(po);
- pa_threaded_mainloop_free(po->mainloop);
- po->mainloop = nullptr;
+ pa_threaded_mainloop_stop(mainloop);
+ if (context != nullptr)
+ DeleteContext();
+ pa_threaded_mainloop_free(mainloop);
+ mainloop = nullptr;
}
-/**
- * Check if the context is (already) connected, and waits if not. If
- * the context has been disconnected, retry to connect.
- *
- * Caller must lock the main loop.
- *
- * @return true on success, false on error
- */
-static bool
-pulse_output_wait_connection(PulseOutput *po, Error &error)
+bool
+PulseOutput::WaitConnection(Error &error)
{
- assert(po->mainloop != nullptr);
+ assert(mainloop != nullptr);
pa_context_state_t state;
- if (po->context == nullptr && !pulse_output_setup_context(po, error))
+ if (context == nullptr && !SetupContext(error))
return false;
while (true) {
- state = pa_context_get_state(po->context);
+ state = pa_context_get_state(context);
switch (state) {
case PA_CONTEXT_READY:
/* nothing to do */
@@ -439,56 +531,61 @@ pulse_output_wait_connection(PulseOutput *po, Error &error)
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
/* failure */
- SetError(error, po->context, "failed to connect");
- pulse_output_delete_context(po);
+ SetPulseError(error, context, "failed to connect");
+ DeleteContext();
return false;
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
/* wait some more */
- pa_threaded_mainloop_wait(po->mainloop);
+ pa_threaded_mainloop_wait(mainloop);
break;
}
}
}
-static void
-pulse_output_stream_suspended_cb(gcc_unused pa_stream *stream, void *userdata)
+inline void
+PulseOutput::OnStreamSuspended(gcc_unused pa_stream *_stream)
{
- PulseOutput *po = (PulseOutput *)userdata;
-
- assert(stream == po->stream || po->stream == nullptr);
- assert(po->mainloop != nullptr);
+ assert(_stream == stream || stream == nullptr);
+ assert(mainloop != nullptr);
/* wake up the main loop to break out of the loop in
pulse_output_play() */
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ Signal();
}
static void
-pulse_output_stream_state_cb(pa_stream *stream, void *userdata)
+pulse_output_stream_suspended_cb(pa_stream *stream, void *userdata)
{
- PulseOutput *po = (PulseOutput *)userdata;
+ PulseOutput &po = *(PulseOutput *)userdata;
- assert(stream == po->stream || po->stream == nullptr);
- assert(po->mainloop != nullptr);
- assert(po->context != nullptr);
+ po.OnStreamSuspended(stream);
+}
+
+inline void
+PulseOutput::OnStreamStateChanged(pa_stream *_stream,
+ pa_stream_state_t new_state)
+{
+ assert(_stream == stream || stream == nullptr);
+ assert(mainloop != nullptr);
+ assert(context != nullptr);
- switch (pa_stream_get_state(stream)) {
+ switch (new_state) {
case PA_STREAM_READY:
- if (po->mixer != nullptr)
- pulse_mixer_on_change(*po->mixer, po->context, stream);
+ if (mixer != nullptr)
+ pulse_mixer_on_change(*mixer, context, _stream);
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ Signal();
break;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
- if (po->mixer != nullptr)
- pulse_mixer_on_disconnect(*po->mixer);
+ if (mixer != nullptr)
+ pulse_mixer_on_disconnect(*mixer);
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ Signal();
break;
case PA_STREAM_UNCONNECTED:
@@ -498,68 +595,75 @@ pulse_output_stream_state_cb(pa_stream *stream, void *userdata)
}
static void
+pulse_output_stream_state_cb(pa_stream *stream, void *userdata)
+{
+ PulseOutput &po = *(PulseOutput *)userdata;
+
+ return po.OnStreamStateChanged(stream, pa_stream_get_state(stream));
+}
+
+inline void
+PulseOutput::OnStreamWrite(size_t nbytes)
+{
+ assert(mainloop != nullptr);
+
+ writable = nbytes;
+ Signal();
+}
+
+static void
pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes,
void *userdata)
{
- PulseOutput *po = (PulseOutput *)userdata;
-
- assert(po->mainloop != nullptr);
+ PulseOutput &po = *(PulseOutput *)userdata;
- po->writable = nbytes;
- pa_threaded_mainloop_signal(po->mainloop, 0);
+ return po.OnStreamWrite(nbytes);
}
-/**
- * Create, set up and connect a context.
- *
- * Caller must lock the main loop.
- *
- * @return true on success, false on error
- */
-static bool
-pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
- Error &error)
+inline bool
+PulseOutput::SetupStream(const pa_sample_spec &ss, Error &error)
{
- assert(po != nullptr);
- assert(po->context != nullptr);
+ assert(context != nullptr);
- po->stream = pa_stream_new(po->context, po->name, ss, nullptr);
- if (po->stream == nullptr) {
- SetError(error, po->context, "pa_stream_new() has failed");
+ /* WAVE-EX is been adopted as the speaker map for most media files */
+ pa_channel_map chan_map;
+ pa_channel_map_init_auto(&chan_map, ss.channels,
+ PA_CHANNEL_MAP_WAVEEX);
+ stream = pa_stream_new(context, name, &ss, &chan_map);
+ if (stream == nullptr) {
+ SetPulseError(error, context,
+ "pa_stream_new() has failed");
return false;
}
- pa_stream_set_suspended_callback(po->stream,
- pulse_output_stream_suspended_cb, po);
+ pa_stream_set_suspended_callback(stream,
+ pulse_output_stream_suspended_cb,
+ this);
- pa_stream_set_state_callback(po->stream,
- pulse_output_stream_state_cb, po);
- pa_stream_set_write_callback(po->stream,
- pulse_output_stream_write_cb, po);
+ pa_stream_set_state_callback(stream,
+ pulse_output_stream_state_cb, this);
+ pa_stream_set_write_callback(stream,
+ pulse_output_stream_write_cb, this);
return true;
}
-static bool
-pulse_output_open(AudioOutput *ao, AudioFormat &audio_format,
- Error &error)
+inline bool
+PulseOutput::Open(AudioFormat &audio_format, Error &error)
{
- PulseOutput *po = (PulseOutput *)ao;
- pa_sample_spec ss;
-
- assert(po->mainloop != nullptr);
+ assert(mainloop != nullptr);
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (po->context != nullptr) {
- switch (pa_context_get_state(po->context)) {
+ if (context != nullptr) {
+ switch (pa_context_get_state(context)) {
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
/* the connection was closed meanwhile; delete
it, and pulse_output_wait_connection() will
reopen it */
- pulse_output_delete_context(po);
+ DeleteContext();
break;
case PA_CONTEXT_READY:
@@ -570,8 +674,8 @@ pulse_output_open(AudioOutput *ao, AudioFormat &audio_format,
}
}
- if (!pulse_output_wait_connection(po, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (!WaitConnection(error)) {
+ pa_threaded_mainloop_unlock(mainloop);
return false;
}
@@ -579,304 +683,282 @@ pulse_output_open(AudioOutput *ao, AudioFormat &audio_format,
we just force MPD to send us everything as 16 bit */
audio_format.format = SampleFormat::S16;
+ pa_sample_spec ss;
ss.format = PA_SAMPLE_S16NE;
ss.rate = audio_format.sample_rate;
ss.channels = audio_format.channels;
/* create a stream .. */
- if (!pulse_output_setup_stream(po, &ss, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (!SetupStream(ss, error)) {
+ pa_threaded_mainloop_unlock(mainloop);
return false;
}
/* .. and connect it (asynchronously) */
- if (pa_stream_connect_playback(po->stream, po->sink,
+ if (pa_stream_connect_playback(stream, sink,
nullptr, pa_stream_flags_t(0),
nullptr, nullptr) < 0) {
- pulse_output_delete_stream(po);
+ DeleteStream();
- SetError(error, po->context,
- "pa_stream_connect_playback() has failed");
- pa_threaded_mainloop_unlock(po->mainloop);
+ SetPulseError(error, context,
+ "pa_stream_connect_playback() has failed");
+ pa_threaded_mainloop_unlock(mainloop);
return false;
}
- pa_threaded_mainloop_unlock(po->mainloop);
-
+ pa_threaded_mainloop_unlock(mainloop);
return true;
}
-static void
-pulse_output_close(AudioOutput *ao)
+inline void
+PulseOutput::Close()
{
- PulseOutput *po = (PulseOutput *)ao;
- pa_operation *o;
-
- assert(po->mainloop != nullptr);
+ assert(mainloop != nullptr);
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (pa_stream_get_state(po->stream) == PA_STREAM_READY) {
- o = pa_stream_drain(po->stream,
- pulse_output_stream_success_cb, po);
+ if (pa_stream_get_state(stream) == PA_STREAM_READY) {
+ pa_operation *o =
+ pa_stream_drain(stream,
+ pulse_output_stream_success_cb, this);
if (o == nullptr) {
- FormatWarning(pulse_output_domain,
- "pa_stream_drain() has failed: %s",
- pa_strerror(pa_context_errno(po->context)));
+ LogPulseError(context,
+ "pa_stream_drain() has failed");
} else
- pulse_wait_for_operation(po->mainloop, o);
+ pulse_wait_for_operation(mainloop, o);
}
- pulse_output_delete_stream(po);
+ DeleteStream();
- if (po->context != nullptr &&
- pa_context_get_state(po->context) != PA_CONTEXT_READY)
- pulse_output_delete_context(po);
+ if (context != nullptr &&
+ pa_context_get_state(context) != PA_CONTEXT_READY)
+ DeleteContext();
- pa_threaded_mainloop_unlock(po->mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
}
-/**
- * Check if the stream is (already) connected, and waits if not. The
- * mainloop must be locked before calling this function.
- *
- * @return true on success, false on error
- */
-static bool
-pulse_output_wait_stream(PulseOutput *po, Error &error)
+bool
+PulseOutput::WaitStream(Error &error)
{
while (true) {
- switch (pa_stream_get_state(po->stream)) {
+ switch (pa_stream_get_state(stream)) {
case PA_STREAM_READY:
return true;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED:
- SetError(error, po->context,
- "failed to connect the stream");
+ SetPulseError(error, context,
+ "failed to connect the stream");
return false;
case PA_STREAM_CREATING:
- pa_threaded_mainloop_wait(po->mainloop);
+ pa_threaded_mainloop_wait(mainloop);
break;
}
}
}
-/**
- * Sets cork mode on the stream.
- */
-static bool
-pulse_output_stream_pause(PulseOutput *po, bool pause,
- Error &error)
+bool
+PulseOutput::StreamPause(bool pause, Error &error)
{
- pa_operation *o;
-
- assert(po->mainloop != nullptr);
- assert(po->context != nullptr);
- assert(po->stream != nullptr);
+ assert(mainloop != nullptr);
+ assert(context != nullptr);
+ assert(stream != nullptr);
- o = pa_stream_cork(po->stream, pause,
- pulse_output_stream_success_cb, po);
+ pa_operation *o = pa_stream_cork(stream, pause,
+ pulse_output_stream_success_cb, this);
if (o == nullptr) {
- SetError(error, po->context, "pa_stream_cork() has failed");
+ SetPulseError(error, context,
+ "pa_stream_cork() has failed");
return false;
}
- if (!pulse_wait_for_operation(po->mainloop, o)) {
- SetError(error, po->context, "pa_stream_cork() has failed");
+ if (!pulse_wait_for_operation(mainloop, o)) {
+ SetPulseError(error, context,
+ "pa_stream_cork() has failed");
return false;
}
return true;
}
-static unsigned
-pulse_output_delay(AudioOutput *ao)
+inline unsigned
+PulseOutput::Delay()
{
- PulseOutput *po = (PulseOutput *)ao;
- unsigned result = 0;
-
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (po->base.pause && pa_stream_is_corked(po->stream) &&
- pa_stream_get_state(po->stream) == PA_STREAM_READY)
+ unsigned result = 0;
+ if (base.pause && pa_stream_is_corked(stream) &&
+ pa_stream_get_state(stream) == PA_STREAM_READY)
/* idle while paused */
result = 1000;
- pa_threaded_mainloop_unlock(po->mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
return result;
}
-static size_t
-pulse_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+PulseOutput::Play(const void *chunk, size_t size, Error &error)
{
- PulseOutput *po = (PulseOutput *)ao;
-
- assert(po->mainloop != nullptr);
- assert(po->stream != nullptr);
+ assert(mainloop != nullptr);
+ assert(stream != nullptr);
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
/* check if the stream is (already) connected */
- if (!pulse_output_wait_stream(po, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (!WaitStream(error)) {
+ pa_threaded_mainloop_unlock(mainloop);
return 0;
}
- assert(po->context != nullptr);
+ assert(context != nullptr);
/* unpause if previously paused */
- if (pa_stream_is_corked(po->stream) &&
- !pulse_output_stream_pause(po, false, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (pa_stream_is_corked(stream) && !StreamPause(false, error)) {
+ pa_threaded_mainloop_unlock(mainloop);
return 0;
}
/* wait until the server allows us to write */
- while (po->writable == 0) {
- if (pa_stream_is_suspended(po->stream)) {
- pa_threaded_mainloop_unlock(po->mainloop);
- error.Set(pulse_output_domain, "suspended");
+ while (writable == 0) {
+ if (pa_stream_is_suspended(stream)) {
+ pa_threaded_mainloop_unlock(mainloop);
+ error.Set(pulse_domain, "suspended");
return 0;
}
- pa_threaded_mainloop_wait(po->mainloop);
+ pa_threaded_mainloop_wait(mainloop);
- if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
- pa_threaded_mainloop_unlock(po->mainloop);
- error.Set(pulse_output_domain, "disconnected");
+ if (pa_stream_get_state(stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(mainloop);
+ error.Set(pulse_domain, "disconnected");
return 0;
}
}
/* now write */
- if (size > po->writable)
+ if (size > writable)
/* don't send more than possible */
- size = po->writable;
+ size = writable;
- po->writable -= size;
+ writable -= size;
- int result = pa_stream_write(po->stream, chunk, size, nullptr,
+ int result = pa_stream_write(stream, chunk, size, nullptr,
0, PA_SEEK_RELATIVE);
- pa_threaded_mainloop_unlock(po->mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
if (result < 0) {
- SetError(error, po->context, "pa_stream_write() failed");
+ SetPulseError(error, context, "pa_stream_write() failed");
return 0;
}
return size;
}
-static void
-pulse_output_cancel(AudioOutput *ao)
+inline void
+PulseOutput::Cancel()
{
- PulseOutput *po = (PulseOutput *)ao;
- pa_operation *o;
-
- assert(po->mainloop != nullptr);
- assert(po->stream != nullptr);
+ assert(mainloop != nullptr);
+ assert(stream != nullptr);
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
- if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
+ if (pa_stream_get_state(stream) != PA_STREAM_READY) {
/* no need to flush when the stream isn't connected
yet */
- pa_threaded_mainloop_unlock(po->mainloop);
+ pa_threaded_mainloop_unlock(mainloop);
return;
}
- assert(po->context != nullptr);
+ assert(context != nullptr);
- o = pa_stream_flush(po->stream, pulse_output_stream_success_cb, po);
+ pa_operation *o = pa_stream_flush(stream,
+ pulse_output_stream_success_cb,
+ this);
if (o == nullptr) {
- FormatWarning(pulse_output_domain,
- "pa_stream_flush() has failed: %s",
- pa_strerror(pa_context_errno(po->context)));
- pa_threaded_mainloop_unlock(po->mainloop);
+ LogPulseError(context, "pa_stream_flush() has failed");
+ pa_threaded_mainloop_unlock(mainloop);
return;
}
- pulse_wait_for_operation(po->mainloop, o);
- pa_threaded_mainloop_unlock(po->mainloop);
+ pulse_wait_for_operation(mainloop, o);
+ pa_threaded_mainloop_unlock(mainloop);
}
-static bool
-pulse_output_pause(AudioOutput *ao)
+inline bool
+PulseOutput::Pause()
{
- PulseOutput *po = (PulseOutput *)ao;
-
- assert(po->mainloop != nullptr);
- assert(po->stream != nullptr);
+ assert(mainloop != nullptr);
+ assert(stream != nullptr);
- pa_threaded_mainloop_lock(po->mainloop);
+ pa_threaded_mainloop_lock(mainloop);
/* check if the stream is (already/still) connected */
Error error;
- if (!pulse_output_wait_stream(po, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (!WaitStream(error)) {
+ pa_threaded_mainloop_unlock(mainloop);
LogError(error);
return false;
}
- assert(po->context != nullptr);
+ assert(context != nullptr);
/* cork the stream */
- if (!pa_stream_is_corked(po->stream) &&
- !pulse_output_stream_pause(po, true, error)) {
- pa_threaded_mainloop_unlock(po->mainloop);
+ if (!pa_stream_is_corked(stream) && !StreamPause(true, error)) {
+ pa_threaded_mainloop_unlock(mainloop);
LogError(error);
return false;
}
- pa_threaded_mainloop_unlock(po->mainloop);
-
+ pa_threaded_mainloop_unlock(mainloop);
return true;
}
-static bool
-pulse_output_test_default_device(void)
+inline bool
+PulseOutput::TestDefaultDevice()
{
- bool success;
-
- const config_param empty;
- PulseOutput *po = (PulseOutput *)
- pulse_output_init(empty, IgnoreError());
+ const ConfigBlock empty;
+ PulseOutput *po = PulseOutput::Create(empty, IgnoreError());
if (po == nullptr)
return false;
- success = pulse_output_wait_connection(po, IgnoreError());
- pulse_output_finish(&po->base);
-
+ bool success = po->WaitConnection(IgnoreError());
+ delete po;
return success;
}
+static bool
+pulse_output_test_default_device(void)
+{
+ return PulseOutput::TestDefaultDevice();
+}
+
+typedef AudioOutputWrapper<PulseOutput> Wrapper;
+
const struct AudioOutputPlugin pulse_output_plugin = {
"pulse",
pulse_output_test_default_device,
- pulse_output_init,
- pulse_output_finish,
- pulse_output_enable,
- pulse_output_disable,
- pulse_output_open,
- pulse_output_close,
- pulse_output_delay,
+ &Wrapper::Init,
+ &Wrapper::Finish,
+ &Wrapper::Enable,
+ &Wrapper::Disable,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- pulse_output_play,
+ &Wrapper::Play,
nullptr,
- pulse_output_cancel,
- pulse_output_pause,
+ &Wrapper::Cancel,
+ &Wrapper::Pause,
&pulse_mixer_plugin,
};
diff --git a/src/output/plugins/PulseOutputPlugin.hxx b/src/output/plugins/PulseOutputPlugin.hxx
index 9219780a5..f193db1d8 100644
--- a/src/output/plugins/PulseOutputPlugin.hxx
+++ b/src/output/plugins/PulseOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX
#define MPD_PULSE_OUTPUT_PLUGIN_HXX
-struct PulseOutput;
+class PulseOutput;
class PulseMixer;
struct pa_cvolume;
class Error;
diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx
index 87e23f55a..115ee534d 100644
--- a/src/output/plugins/RecorderOutputPlugin.cxx
+++ b/src/output/plugins/RecorderOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,21 +20,28 @@
#include "config.h"
#include "RecorderOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
+#include "tag/Format.hxx"
+#include "encoder/ToOutputStream.hxx"
+#include "encoder/EncoderInterface.hxx"
#include "encoder/EncoderPlugin.hxx"
#include "encoder/EncoderList.hxx"
#include "config/ConfigError.hxx"
+#include "config/ConfigPath.hxx"
+#include "Log.hxx"
+#include "fs/AllocatedPath.hxx"
+#include "fs/io/FileOutputStream.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#include "system/fd_util.h"
-#include "open.h"
#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
+#include <stdlib.h>
+
+static constexpr Domain recorder_domain("recorder");
+
+class RecorderOutput {
+ friend struct AudioOutputWrapper<RecorderOutput>;
-struct RecorderOutput {
AudioOutput base;
/**
@@ -45,44 +52,77 @@ struct RecorderOutput {
/**
* The destination file name.
*/
- const char *path;
+ AllocatedPath path;
+
+ /**
+ * A string that will be used with FormatTag() to build the
+ * destination path.
+ */
+ std::string format_path;
/**
- * The destination file descriptor.
+ * The #AudioFormat that is currently active. This is used
+ * for switching to another file.
*/
- int fd;
+ AudioFormat effective_audio_format;
/**
- * The buffer for encoder_read().
+ * The destination file.
*/
- char buffer[32768];
+ FileOutputStream *file;
RecorderOutput()
- :base(recorder_output_plugin) {}
+ :base(recorder_output_plugin),
+ encoder(nullptr),
+ path(AllocatedPath::Null()) {}
- bool Initialize(const config_param &param, Error &error_r) {
- return base.Configure(param, error_r);
+ ~RecorderOutput() {
+ if (encoder != nullptr)
+ encoder->Dispose();
}
- bool Configure(const config_param &param, Error &error);
+ bool Initialize(const ConfigBlock &block, Error &error_r) {
+ return base.Configure(block, error_r);
+ }
+
+ static RecorderOutput *Create(const ConfigBlock &block, Error &error);
+
+ bool Configure(const ConfigBlock &block, Error &error);
- bool WriteToFile(const void *data, size_t length, Error &error);
+ bool Open(AudioFormat &audio_format, Error &error);
+ void Close();
/**
* Writes pending data from the encoder to the output file.
*/
bool EncoderToFile(Error &error);
-};
-static constexpr Domain recorder_output_domain("recorder_output");
+ void SendTag(const Tag &tag);
+
+ size_t Play(const void *chunk, size_t size, Error &error);
+
+private:
+ gcc_pure
+ bool HasDynamicPath() const {
+ return !format_path.empty();
+ }
+
+ /**
+ * Finish the encoder and commit the file.
+ */
+ bool Commit(Error &error);
+
+ void FinishFormat();
+ bool ReopenFormat(AllocatedPath &&new_path, Error &error);
+};
inline bool
-RecorderOutput::Configure(const config_param &param, Error &error)
+RecorderOutput::Configure(const ConfigBlock &block, Error &error)
{
/* read configuration */
const char *encoder_name =
- param.GetBlockValue("encoder", "vorbis");
+ block.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == nullptr) {
error.Format(config_domain,
@@ -90,167 +130,268 @@ RecorderOutput::Configure(const config_param &param, Error &error)
return false;
}
- path = param.GetBlockValue("path");
- if (path == nullptr) {
+ path = block.GetBlockPath("path", error);
+ if (error.IsDefined())
+ return false;
+
+ const char *fmt = block.GetBlockValue("format_path", nullptr);
+ if (fmt != nullptr)
+ format_path = fmt;
+
+ if (path.IsNull() && fmt == nullptr) {
error.Set(config_domain, "'path' not configured");
return false;
}
+ if (!path.IsNull() && fmt != nullptr) {
+ error.Set(config_domain, "Cannot have both 'path' and 'format_path'");
+ return false;
+ }
+
/* initialize encoder */
- encoder = encoder_init(*encoder_plugin, param, error);
+ encoder = encoder_init(*encoder_plugin, block, error);
if (encoder == nullptr)
return false;
return true;
}
-static AudioOutput *
-recorder_output_init(const config_param &param, Error &error)
+RecorderOutput *
+RecorderOutput::Create(const ConfigBlock &block, Error &error)
{
RecorderOutput *recorder = new RecorderOutput();
- if (!recorder->Initialize(param, error)) {
+ if (!recorder->Initialize(block, error)) {
delete recorder;
return nullptr;
}
- if (!recorder->Configure(param, error)) {
+ if (!recorder->Configure(block, error)) {
delete recorder;
return nullptr;
}
- return &recorder->base;
+ return recorder;
}
-static void
-recorder_output_finish(AudioOutput *ao)
+inline bool
+RecorderOutput::EncoderToFile(Error &error)
{
- RecorderOutput *recorder = (RecorderOutput *)ao;
+ assert(file != nullptr);
+ assert(file->IsDefined());
- encoder_finish(recorder->encoder);
- delete recorder;
+ return EncoderToOutputStream(*file, *encoder, error);
}
inline bool
-RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error)
+RecorderOutput::Open(AudioFormat &audio_format, Error &error)
{
- assert(length > 0);
-
- const uint8_t *data = (const uint8_t *)_data, *end = data + length;
-
- while (true) {
- ssize_t nbytes = write(fd, data, end - data);
- if (nbytes > 0) {
- data += nbytes;
- if (data == end)
- return true;
- } else if (nbytes == 0) {
- /* shouldn't happen for files */
- error.Set(recorder_output_domain,
- "write() returned 0");
+ /* create the output file */
+
+ if (!HasDynamicPath()) {
+ assert(!path.IsNull());
+
+ file = FileOutputStream::Create(path, error);
+ if (file == nullptr)
return false;
- } else if (errno != EINTR) {
- error.FormatErrno("Failed to write to '%s'", path);
+ } else {
+ /* don't open the file just yet; wait until we have
+ a tag that we can use to build the path */
+ assert(path.IsNull());
+
+ file = nullptr;
+ }
+
+ /* open the encoder */
+
+ if (!encoder->Open(audio_format, error)) {
+ delete file;
+ return false;
+ }
+
+ if (!HasDynamicPath()) {
+ if (!EncoderToFile(error)) {
+ encoder->Close();
+ delete file;
return false;
}
+ } else {
+ /* remember the AudioFormat for ReopenFormat() */
+ effective_audio_format = audio_format;
+
+ /* close the encoder for now; it will be opened as
+ soon as we have received a tag */
+ encoder->Close();
}
+
+ return true;
}
inline bool
-RecorderOutput::EncoderToFile(Error &error)
+RecorderOutput::Commit(Error &error)
{
- assert(fd >= 0);
+ assert(!path.IsNull());
- while (true) {
- /* read from the encoder */
+ /* flush the encoder and write the rest to the file */
- size_t size = encoder_read(encoder, buffer, sizeof(buffer));
- if (size == 0)
- return true;
+ bool success = encoder_end(encoder, error) &&
+ EncoderToFile(error);
- /* write everything into the file */
+ /* now really close everything */
- if (!WriteToFile(buffer, size, error))
- return false;
- }
+ encoder->Close();
+
+ if (success && !file->Commit(error))
+ success = false;
+
+ delete file;
+
+ return success;
}
-static bool
-recorder_output_open(AudioOutput *ao,
- AudioFormat &audio_format,
- Error &error)
+inline void
+RecorderOutput::Close()
{
- RecorderOutput *recorder = (RecorderOutput *)ao;
+ if (file == nullptr) {
+ /* not currently encoding to a file; nothing needs to
+ be done now */
+ assert(HasDynamicPath());
+ assert(path.IsNull());
+ return;
+ }
- /* create the output file */
+ Error error;
+ if (!Commit(error))
+ LogError(error);
- recorder->fd = open_cloexec(recorder->path,
- O_CREAT|O_WRONLY|O_TRUNC|O_BINARY,
- 0666);
- if (recorder->fd < 0) {
- error.FormatErrno("Failed to create '%s'", recorder->path);
- return false;
+ if (HasDynamicPath()) {
+ assert(!path.IsNull());
+ path.SetNull();
}
+}
- /* open the encoder */
+void
+RecorderOutput::FinishFormat()
+{
+ assert(HasDynamicPath());
+
+ if (file == nullptr)
+ return;
+
+ Error error;
+ if (!Commit(error))
+ LogError(error);
+
+ file = nullptr;
+ path.SetNull();
+}
- if (!encoder_open(recorder->encoder, audio_format, error)) {
- close(recorder->fd);
- unlink(recorder->path);
+inline bool
+RecorderOutput::ReopenFormat(AllocatedPath &&new_path, Error &error)
+{
+ assert(HasDynamicPath());
+ assert(path.IsNull());
+ assert(file == nullptr);
+
+ FileOutputStream *new_file =
+ FileOutputStream::Create(new_path, error);
+ if (new_file == nullptr)
+ return false;
+
+ AudioFormat new_audio_format = effective_audio_format;
+ if (!encoder->Open(new_audio_format, error)) {
+ delete new_file;
return false;
}
- if (!recorder->EncoderToFile(error)) {
- encoder_close(recorder->encoder);
- close(recorder->fd);
- unlink(recorder->path);
+ /* reopening the encoder must always result in the same
+ AudioFormat as before */
+ assert(new_audio_format == effective_audio_format);
+
+ if (!EncoderToOutputStream(*new_file, *encoder, error)) {
+ encoder->Close();
+ delete new_file;
return false;
}
+ path = std::move(new_path);
+ file = new_file;
+
+ FormatDebug(recorder_domain, "Recording to \"%s\"", path.c_str());
+
return true;
}
-static void
-recorder_output_close(AudioOutput *ao)
+inline void
+RecorderOutput::SendTag(const Tag &tag)
{
- RecorderOutput *recorder = (RecorderOutput *)ao;
-
- /* flush the encoder and write the rest to the file */
+ if (HasDynamicPath()) {
+ char *p = FormatTag(tag, format_path.c_str());
+ if (p == nullptr || *p == 0) {
+ /* no path could be composed with this tag:
+ don't write a file */
+ free(p);
+ FinishFormat();
+ return;
+ }
- if (encoder_end(recorder->encoder, IgnoreError()))
- recorder->EncoderToFile(IgnoreError());
+ Error error;
+ AllocatedPath new_path = ParsePath(p, error);
+ free(p);
+ if (new_path.IsNull()) {
+ LogError(error);
+ FinishFormat();
+ return;
+ }
- /* now really close everything */
+ if (new_path != path) {
+ FinishFormat();
- encoder_close(recorder->encoder);
+ if (!ReopenFormat(std::move(new_path), error)) {
+ LogError(error);
+ return;
+ }
+ }
+ }
- close(recorder->fd);
+ Error error;
+ if (!encoder_pre_tag(encoder, error) ||
+ !EncoderToFile(error) ||
+ !encoder_tag(encoder, tag, error))
+ LogError(error);
}
-static size_t
-recorder_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+RecorderOutput::Play(const void *chunk, size_t size, Error &error)
{
- RecorderOutput *recorder = (RecorderOutput *)ao;
+ if (file == nullptr) {
+ /* not currently encoding to a file; discard incoming
+ data */
+ assert(HasDynamicPath());
+ assert(path.IsNull());
+ return size;
+ }
- return encoder_write(recorder->encoder, chunk, size, error) &&
- recorder->EncoderToFile(error)
+ return encoder_write(encoder, chunk, size, error) &&
+ EncoderToFile(error)
? size : 0;
}
+typedef AudioOutputWrapper<RecorderOutput> Wrapper;
+
const struct AudioOutputPlugin recorder_output_plugin = {
"recorder",
nullptr,
- recorder_output_init,
- recorder_output_finish,
- nullptr,
+ &Wrapper::Init,
+ &Wrapper::Finish,
nullptr,
- recorder_output_open,
- recorder_output_close,
nullptr,
+ &Wrapper::Open,
+ &Wrapper::Close,
nullptr,
- recorder_output_play,
+ &Wrapper::SendTag,
+ &Wrapper::Play,
nullptr,
nullptr,
nullptr,
diff --git a/src/output/plugins/RecorderOutputPlugin.hxx b/src/output/plugins/RecorderOutputPlugin.hxx
index ea1044e0f..061279fba 100644
--- a/src/output/plugins/RecorderOutputPlugin.hxx
+++ b/src/output/plugins/RecorderOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx
index aa37c91b7..11b0f1671 100644
--- a/src/output/plugins/RoarOutputPlugin.cxx
+++ b/src/output/plugins/RoarOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* Copyright (C) 2010-2011 Philipp 'ph3-der-loewe' Schafft
* Copyright (C) 2010-2011 Hans-Kristian 'maister' Arntzen
*
@@ -21,6 +21,7 @@
#include "config.h"
#include "RoarOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "mixer/MixerList.hxx"
#include "thread/Mutex.hxx"
#include "util/Error.hxx"
@@ -36,6 +37,8 @@
#undef new
class RoarOutput {
+ friend struct AudioOutputWrapper<RoarOutput>;
+
AudioOutput base;
std::string host, name;
@@ -57,11 +60,11 @@ public:
return &base;
}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
- void Configure(const config_param &param);
+ void Configure(const ConfigBlock &block);
bool Open(AudioFormat &audio_format, Error &error);
void Close();
@@ -121,40 +124,32 @@ roar_output_set_volume(RoarOutput &roar, unsigned volume)
}
inline void
-RoarOutput::Configure(const config_param &param)
+RoarOutput::Configure(const ConfigBlock &block)
{
- host = param.GetBlockValue("server", "");
- name = param.GetBlockValue("name", "MPD");
+ host = block.GetBlockValue("server", "");
+ name = block.GetBlockValue("name", "MPD");
- const char *_role = param.GetBlockValue("role", "music");
+ const char *_role = block.GetBlockValue("role", "music");
role = _role != nullptr
? roar_str2role(_role)
: ROAR_ROLE_MUSIC;
}
static AudioOutput *
-roar_init(const config_param &param, Error &error)
+roar_init(const ConfigBlock &block, Error &error)
{
RoarOutput *self = new RoarOutput();
- if (!self->Initialize(param, error)) {
+ if (!self->Initialize(block, error)) {
delete self;
return nullptr;
}
- self->Configure(param);
+ self->Configure(block);
return *self;
}
static void
-roar_finish(AudioOutput *ao)
-{
- RoarOutput *self = (RoarOutput *)ao;
-
- delete self;
-}
-
-static void
roar_use_audio_format(struct roar_audio_info *info,
AudioFormat &audio_format)
{
@@ -221,14 +216,6 @@ RoarOutput::Open(AudioFormat &audio_format, Error &error)
return true;
}
-static bool
-roar_open(AudioOutput *ao, AudioFormat &audio_format, Error &error)
-{
- RoarOutput *self = (RoarOutput *)ao;
-
- return self->Open(audio_format, error);
-}
-
inline void
RoarOutput::Close()
{
@@ -242,13 +229,6 @@ RoarOutput::Close()
roar_disconnect(&con);
}
-static void
-roar_close(AudioOutput *ao)
-{
- RoarOutput *self = (RoarOutput *)ao;
- self->Close();
-}
-
inline void
RoarOutput::Cancel()
{
@@ -277,14 +257,6 @@ RoarOutput::Cancel()
alive = true;
}
-static void
-roar_cancel(AudioOutput *ao)
-{
- RoarOutput *self = (RoarOutput *)ao;
-
- self->Cancel();
-}
-
inline size_t
RoarOutput::Play(const void *chunk, size_t size, Error &error)
{
@@ -302,14 +274,6 @@ RoarOutput::Play(const void *chunk, size_t size, Error &error)
return nbytes;
}
-static size_t
-roar_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
-{
- RoarOutput *self = (RoarOutput *)ao;
- return self->Play(chunk, size, error);
-}
-
static const char*
roar_tag_convert(TagType type, bool *is_uuid)
{
@@ -407,26 +371,28 @@ RoarOutput::SendTag(const Tag &tag)
}
static void
-roar_send_tag(AudioOutput *ao, const Tag *meta)
+roar_send_tag(AudioOutput *ao, const Tag &meta)
{
RoarOutput *self = (RoarOutput *)ao;
- self->SendTag(*meta);
+ self->SendTag(meta);
}
+typedef AudioOutputWrapper<RoarOutput> Wrapper;
+
const struct AudioOutputPlugin roar_output_plugin = {
"roar",
nullptr,
roar_init,
- roar_finish,
+ &Wrapper::Finish,
nullptr,
nullptr,
- roar_open,
- roar_close,
+ &Wrapper::Open,
+ &Wrapper::Close,
nullptr,
roar_send_tag,
- roar_play,
+ &Wrapper::Play,
nullptr,
- roar_cancel,
+ &Wrapper::Cancel,
nullptr,
&roar_mixer_plugin,
};
diff --git a/src/output/plugins/RoarOutputPlugin.hxx b/src/output/plugins/RoarOutputPlugin.hxx
index 5f5a9246e..a9726d5c8 100644
--- a/src/output/plugins/RoarOutputPlugin.hxx
+++ b/src/output/plugins/RoarOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index b51f7ed82..339c4e491 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "ShoutOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "encoder/EncoderInterface.hxx"
#include "encoder/EncoderPlugin.hxx"
#include "encoder/EncoderList.hxx"
#include "config/ConfigError.hxx"
@@ -67,11 +68,11 @@ struct ShoutOutput final {
shout_free(shout_conn);
}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
};
static int shout_init_count;
@@ -91,18 +92,18 @@ shout_encoder_plugin_get(const char *name)
gcc_pure
static const char *
-require_block_string(const config_param &param, const char *name)
+require_block_string(const ConfigBlock &block, const char *name)
{
- const char *value = param.GetBlockValue(name);
+ const char *value = block.GetBlockValue(name);
if (value == nullptr)
FormatFatalError("no \"%s\" defined for shout device defined "
- "at line %u\n", name, param.line);
+ "at line %d\n", name, block.line);
return value;
}
inline bool
-ShoutOutput::Configure(const config_param &param, Error &error)
+ShoutOutput::Configure(const ConfigBlock &block, Error &error)
{
const AudioFormat audio_format = base.config_audio_format;
@@ -112,22 +113,22 @@ ShoutOutput::Configure(const config_param &param, Error &error)
return false;
}
- const char *host = require_block_string(param, "host");
- const char *mount = require_block_string(param, "mount");
- unsigned port = param.GetBlockValue("port", 0u);
+ const char *host = require_block_string(block, "host");
+ const char *mount = require_block_string(block, "mount");
+ unsigned port = block.GetBlockValue("port", 0u);
if (port == 0) {
error.Set(config_domain, "shout port must be configured");
return false;
}
- const char *passwd = require_block_string(param, "password");
- const char *name = require_block_string(param, "name");
+ const char *passwd = require_block_string(block, "password");
+ const char *name = require_block_string(block, "name");
- bool is_public = param.GetBlockValue("public", false);
+ bool is_public = block.GetBlockValue("public", false);
- const char *user = param.GetBlockValue("user", "source");
+ const char *user = block.GetBlockValue("user", "source");
- const char *value = param.GetBlockValue("quality");
+ const char *value = block.GetBlockValue("quality");
if (value != nullptr) {
char *test;
quality = strtod(value, &test);
@@ -140,14 +141,14 @@ ShoutOutput::Configure(const config_param &param, Error &error)
return false;
}
- if (param.GetBlockValue("bitrate") != nullptr) {
+ if (block.GetBlockValue("bitrate") != nullptr) {
error.Set(config_domain,
"quality and bitrate are "
"both defined");
return false;
}
} else {
- value = param.GetBlockValue("bitrate");
+ value = block.GetBlockValue("bitrate");
if (value == nullptr) {
error.Set(config_domain,
"neither bitrate nor quality defined");
@@ -164,7 +165,7 @@ ShoutOutput::Configure(const config_param &param, Error &error)
}
}
- const char *encoding = param.GetBlockValue("encoding", "ogg");
+ const char *encoding = block.GetBlockValue("encoding", "ogg");
const auto encoder_plugin = shout_encoder_plugin_get(encoding);
if (encoder_plugin == nullptr) {
error.Format(config_domain,
@@ -173,7 +174,7 @@ ShoutOutput::Configure(const config_param &param, Error &error)
return false;
}
- encoder = encoder_init(*encoder_plugin, param, error);
+ encoder = encoder_init(*encoder_plugin, block, error);
if (encoder == nullptr)
return false;
@@ -184,7 +185,7 @@ ShoutOutput::Configure(const config_param &param, Error &error)
shout_format = SHOUT_FORMAT_OGG;
unsigned protocol;
- value = param.GetBlockValue("protocol");
+ value = block.GetBlockValue("protocol");
if (value != nullptr) {
if (0 == strcmp(value, "shoutcast") &&
0 != strcmp(encoding, "mp3")) {
@@ -225,21 +226,21 @@ ShoutOutput::Configure(const config_param &param, Error &error)
}
/* optional paramters */
- timeout = param.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT);
+ timeout = block.GetBlockValue("timeout", DEFAULT_CONN_TIMEOUT);
- value = param.GetBlockValue("genre");
+ value = block.GetBlockValue("genre");
if (value != nullptr && shout_set_genre(shout_conn, value)) {
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
- value = param.GetBlockValue("description");
+ value = block.GetBlockValue("description");
if (value != nullptr && shout_set_description(shout_conn, value)) {
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
- value = param.GetBlockValue("url");
+ value = block.GetBlockValue("url");
if (value != nullptr && shout_set_url(shout_conn, value)) {
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
@@ -271,15 +272,15 @@ ShoutOutput::Configure(const config_param &param, Error &error)
}
static AudioOutput *
-my_shout_init_driver(const config_param &param, Error &error)
+my_shout_init_driver(const ConfigBlock &block, Error &error)
{
ShoutOutput *sd = new ShoutOutput();
- if (!sd->Initialize(param, error)) {
+ if (!sd->Initialize(block, error)) {
delete sd;
return nullptr;
}
- if (!sd->Configure(param, error)) {
+ if (!sd->Configure(block, error)) {
delete sd;
return nullptr;
}
@@ -345,7 +346,7 @@ static void close_shout_conn(ShoutOutput * sd)
if (encoder_end(sd->encoder, IgnoreError()))
write_page(sd, IgnoreError());
- encoder_close(sd->encoder);
+ sd->encoder->Close();
}
if (shout_get_connected(sd->shout_conn) != SHOUTERR_UNCONNECTED &&
@@ -361,7 +362,7 @@ my_shout_finish_driver(AudioOutput *ao)
{
ShoutOutput *sd = (ShoutOutput *)ao;
- encoder_finish(sd->encoder);
+ sd->encoder->Dispose();
delete sd;
@@ -415,13 +416,13 @@ my_shout_open_device(AudioOutput *ao, AudioFormat &audio_format,
if (!shout_connect(sd, error))
return false;
- if (!encoder_open(sd->encoder, audio_format, error)) {
+ if (!sd->encoder->Open(audio_format, error)) {
shout_close(sd->shout_conn);
return false;
}
if (!write_page(sd, error)) {
- encoder_close(sd->encoder);
+ sd->encoder->Close();
shout_close(sd->shout_conn);
return false;
}
@@ -462,7 +463,7 @@ my_shout_pause(AudioOutput *ao)
}
static void
-shout_tag_to_metadata(const Tag *tag, char *dest, size_t size)
+shout_tag_to_metadata(const Tag &tag, char *dest, size_t size)
{
char artist[size];
char title[size];
@@ -470,7 +471,7 @@ shout_tag_to_metadata(const Tag *tag, char *dest, size_t size)
artist[0] = 0;
title[0] = 0;
- for (const auto &item : *tag) {
+ for (const auto &item : tag) {
switch (item.type) {
case TAG_ARTIST:
strncpy(artist, item.value, size);
@@ -488,7 +489,7 @@ shout_tag_to_metadata(const Tag *tag, char *dest, size_t size)
}
static void my_shout_set_tag(AudioOutput *ao,
- const Tag *tag)
+ const Tag &tag)
{
ShoutOutput *sd = (ShoutOutput *)ao;
diff --git a/src/output/plugins/ShoutOutputPlugin.hxx b/src/output/plugins/ShoutOutputPlugin.hxx
index 9f706fc3b..b103b3bf0 100644
--- a/src/output/plugins/ShoutOutputPlugin.hxx
+++ b/src/output/plugins/ShoutOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/SolarisOutputPlugin.cxx b/src/output/plugins/SolarisOutputPlugin.cxx
index 30745f97c..18c92d361 100644
--- a/src/output/plugins/SolarisOutputPlugin.cxx
+++ b/src/output/plugins/SolarisOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -60,8 +60,8 @@ struct SolarisOutput {
SolarisOutput()
:base(solaris_output_plugin) {}
- bool Initialize(const config_param &param, Error &error_r) {
- return base.Configure(param, error_r);
+ bool Initialize(const ConfigBlock &block, Error &error_r) {
+ return base.Configure(block, error_r);
}
};
@@ -75,15 +75,15 @@ solaris_output_test_default_device(void)
}
static AudioOutput *
-solaris_output_init(const config_param &param, Error &error_r)
+solaris_output_init(const ConfigBlock &block, Error &error_r)
{
SolarisOutput *so = new SolarisOutput();
- if (!so->Initialize(param, error_r)) {
+ if (!so->Initialize(block, error_r)) {
delete so;
return nullptr;
}
- so->device = param.GetBlockValue("device", "/dev/audio");
+ so->device = block.GetBlockValue("device", "/dev/audio");
return &so->base;
}
diff --git a/src/output/plugins/SolarisOutputPlugin.hxx b/src/output/plugins/SolarisOutputPlugin.hxx
index 3f9ede7a6..f6f32504a 100644
--- a/src/output/plugins/SolarisOutputPlugin.hxx
+++ b/src/output/plugins/SolarisOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx
index e5c5a6f0c..95f359828 100644
--- a/src/output/plugins/WinmmOutputPlugin.cxx
+++ b/src/output/plugins/WinmmOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -56,6 +56,18 @@ struct WinmmOutput {
static constexpr Domain winmm_output_domain("winmm_output");
+static void
+SetWaveOutError(Error &error, MMRESULT result, const char *prefix)
+{
+ char buffer[256];
+ if (waveOutGetErrorTextA(result, buffer,
+ ARRAY_SIZE(buffer)) == MMSYSERR_NOERROR)
+ error.Format(winmm_output_domain, int(result),
+ "%s: %s", prefix, buffer);
+ else
+ error.Set(winmm_output_domain, int(result), prefix);
+}
+
HWAVEOUT
winmm_output_get_handle(WinmmOutput &output)
{
@@ -110,15 +122,15 @@ fail:
}
static AudioOutput *
-winmm_output_init(const config_param &param, Error &error)
+winmm_output_init(const ConfigBlock &block, Error &error)
{
WinmmOutput *wo = new WinmmOutput();
- if (!wo->base.Configure(param, error)) {
+ if (!wo->base.Configure(block, error)) {
delete wo;
return nullptr;
}
- const char *device = param.GetBlockValue("device");
+ const char *device = block.GetBlockValue("device");
if (!get_device_id(device, &wo->device_id, error)) {
delete wo;
return nullptr;
@@ -179,7 +191,7 @@ winmm_output_open(AudioOutput *ao, AudioFormat &audio_format,
(DWORD_PTR)wo->event, 0, CALLBACK_EVENT);
if (result != MMSYSERR_NOERROR) {
CloseHandle(wo->event);
- error.Set(winmm_output_domain, "waveOutOpen() failed");
+ SetWaveOutError(error, result, "waveOutOpen() failed");
return false;
}
@@ -225,8 +237,8 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr));
if (result != MMSYSERR_NOERROR) {
- error.Set(winmm_output_domain, result,
- "waveOutPrepareHeader() failed");
+ SetWaveOutError(error, result,
+ "waveOutPrepareHeader() failed");
return false;
}
@@ -251,8 +263,8 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
if (result == MMSYSERR_NOERROR)
return true;
else if (result != WAVERR_STILLPLAYING) {
- error.Set(winmm_output_domain, result,
- "waveOutUnprepareHeader() failed");
+ SetWaveOutError(error, result,
+ "waveOutUnprepareHeader() failed");
return false;
}
@@ -278,8 +290,7 @@ winmm_output_play(AudioOutput *ao, const void *chunk, size_t size, Error &error)
if (result != MMSYSERR_NOERROR) {
waveOutUnprepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr));
- error.Set(winmm_output_domain, result,
- "waveOutWrite() failed");
+ SetWaveOutError(error, result, "waveOutWrite() failed");
return 0;
}
diff --git a/src/output/plugins/WinmmOutputPlugin.hxx b/src/output/plugins/WinmmOutputPlugin.hxx
index 50fae4f2f..6c8fcc627 100644
--- a/src/output/plugins/WinmmOutputPlugin.hxx
+++ b/src/output/plugins/WinmmOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/HttpdClient.cxx b/src/output/plugins/httpd/HttpdClient.cxx
index 3797c3d26..b372eedbc 100644
--- a/src/output/plugins/httpd/HttpdClient.cxx
+++ b/src/output/plugins/httpd/HttpdClient.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/HttpdClient.hxx b/src/output/plugins/httpd/HttpdClient.hxx
index f94f05769..af83f0d52 100644
--- a/src/output/plugins/httpd/HttpdClient.hxx
+++ b/src/output/plugins/httpd/HttpdClient.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/HttpdInternal.hxx b/src/output/plugins/httpd/HttpdInternal.hxx
index 20ff15e42..d3ea49cd4 100644
--- a/src/output/plugins/httpd/HttpdInternal.hxx
+++ b/src/output/plugins/httpd/HttpdInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@
#include <queue>
#include <list>
-struct config_param;
+struct ConfigBlock;
class Error;
class EventLoop;
class ServerSocket;
@@ -153,7 +153,7 @@ public:
HttpdOutput(EventLoop &_loop);
~HttpdOutput();
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
constexpr
#endif
static HttpdOutput *Cast(AudioOutput *ao) {
@@ -162,16 +162,16 @@ public:
using DeferredMonitor::GetEventLoop;
- bool Init(const config_param &param, Error &error);
+ bool Init(const ConfigBlock &block, Error &error);
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
- AudioOutput *InitAndConfigure(const config_param &param,
+ AudioOutput *InitAndConfigure(const ConfigBlock &block,
Error &error) {
- if (!Init(param, error))
+ if (!Init(block, error))
return nullptr;
- if (!Configure(param, error))
+ if (!Configure(block, error))
return nullptr;
return &base;
@@ -250,7 +250,7 @@ public:
bool EncodeAndPlay(const void *chunk, size_t size, Error &error);
- void SendTag(const Tag *tag);
+ void SendTag(const Tag &tag);
size_t Play(const void *chunk, size_t size, Error &error);
diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
index e3ba7727d..a99f9b412 100644
--- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx
+++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include "HttpdInternal.hxx"
#include "HttpdClient.hxx"
#include "output/OutputAPI.hxx"
+#include "encoder/EncoderInterface.hxx"
#include "encoder/EncoderPlugin.hxx"
#include "encoder/EncoderList.hxx"
#include "system/Resolver.hxx"
@@ -63,7 +64,7 @@ HttpdOutput::~HttpdOutput()
metadata->Unref();
if (encoder != nullptr)
- encoder_finish(encoder);
+ encoder->Dispose();
}
@@ -90,17 +91,17 @@ HttpdOutput::Unbind()
}
inline bool
-HttpdOutput::Configure(const config_param &param, Error &error)
+HttpdOutput::Configure(const ConfigBlock &block, Error &error)
{
/* read configuration */
- name = param.GetBlockValue("name", "Set name in config");
- genre = param.GetBlockValue("genre", "Set genre in config");
- website = param.GetBlockValue("website", "Set website in config");
+ name = block.GetBlockValue("name", "Set name in config");
+ genre = block.GetBlockValue("genre", "Set genre in config");
+ website = block.GetBlockValue("website", "Set website in config");
- unsigned port = param.GetBlockValue("port", 8000u);
+ unsigned port = block.GetBlockValue("port", 8000u);
const char *encoder_name =
- param.GetBlockValue("encoder", "vorbis");
+ block.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == nullptr) {
error.Format(httpd_output_domain,
@@ -108,11 +109,11 @@ HttpdOutput::Configure(const config_param &param, Error &error)
return false;
}
- clients_max = param.GetBlockValue("max_clients", 0u);
+ clients_max = block.GetBlockValue("max_clients", 0u);
/* set up bind_to_address */
- const char *bind_to_address = param.GetBlockValue("bind_to_address");
+ const char *bind_to_address = block.GetBlockValue("bind_to_address");
bool success = bind_to_address != nullptr &&
strcmp(bind_to_address, "any") != 0
? AddHost(bind_to_address, port, error)
@@ -122,7 +123,7 @@ HttpdOutput::Configure(const config_param &param, Error &error)
/* initialize encoder */
- encoder = encoder_init(*encoder_plugin, param, error);
+ encoder = encoder_init(*encoder_plugin, block, error);
if (encoder == nullptr)
return false;
@@ -135,17 +136,17 @@ HttpdOutput::Configure(const config_param &param, Error &error)
}
inline bool
-HttpdOutput::Init(const config_param &param, Error &error)
+HttpdOutput::Init(const ConfigBlock &block, Error &error)
{
- return base.Configure(param, error);
+ return base.Configure(block, error);
}
static AudioOutput *
-httpd_output_init(const config_param &param, Error &error)
+httpd_output_init(const ConfigBlock &block, Error &error)
{
HttpdOutput *httpd = new HttpdOutput(io_thread_get());
- AudioOutput *result = httpd->InitAndConfigure(param, error);
+ AudioOutput *result = httpd->InitAndConfigure(block, error);
if (result == nullptr)
delete httpd;
@@ -294,7 +295,7 @@ httpd_output_disable(AudioOutput *ao)
inline bool
HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
{
- if (!encoder_open(encoder, audio_format, error))
+ if (!encoder->Open(audio_format, error))
return false;
/* we have to remember the encoder header, i.e. the first
@@ -354,7 +355,7 @@ HttpdOutput::Close()
if (header != nullptr)
header->Unref();
- encoder_close(encoder);
+ encoder->Close();
}
static void
@@ -499,10 +500,8 @@ httpd_output_pause(AudioOutput *ao)
}
inline void
-HttpdOutput::SendTag(const Tag *tag)
+HttpdOutput::SendTag(const Tag &tag)
{
- assert(tag != nullptr);
-
if (encoder->plugin.tag != nullptr) {
/* embed encoder tags */
@@ -538,7 +537,7 @@ HttpdOutput::SendTag(const Tag *tag)
TAG_NUM_OF_ITEM_TYPES
};
- metadata = icy_server_metadata_page(*tag, &types[0]);
+ metadata = icy_server_metadata_page(tag, &types[0]);
if (metadata != nullptr) {
const ScopeLock protect(mutex);
for (auto &client : clients)
@@ -548,7 +547,7 @@ HttpdOutput::SendTag(const Tag *tag)
}
static void
-httpd_output_tag(AudioOutput *ao, const Tag *tag)
+httpd_output_tag(AudioOutput *ao, const Tag &tag)
{
HttpdOutput *httpd = HttpdOutput::Cast(ao);
diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.hxx b/src/output/plugins/httpd/HttpdOutputPlugin.hxx
index df99e2b43..8280d9fb2 100644
--- a/src/output/plugins/httpd/HttpdOutputPlugin.hxx
+++ b/src/output/plugins/httpd/HttpdOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/IcyMetaDataServer.cxx b/src/output/plugins/httpd/IcyMetaDataServer.cxx
index 146df23d1..fe841ac11 100644
--- a/src/output/plugins/httpd/IcyMetaDataServer.cxx
+++ b/src/output/plugins/httpd/IcyMetaDataServer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,8 +22,8 @@
#include "Page.hxx"
#include "tag/Tag.hxx"
#include "util/FormatString.hxx"
-
-#include <glib.h>
+#include "util/StringUtil.hxx"
+#include "util/Macros.hxx"
#include <string.h>
@@ -57,16 +57,13 @@ icy_server_metadata_header(const char *name,
static char *
icy_server_metadata_string(const char *stream_title, const char* stream_url)
{
- gchar *icy_metadata;
- guint meta_length;
-
// The leading n is a placeholder for the length information
- icy_metadata = FormatNew("nStreamTitle='%s';"
- "StreamUrl='%s';",
- stream_title,
- stream_url);
+ char *icy_metadata = FormatNew("nStreamTitle='%s';"
+ "StreamUrl='%s';",
+ stream_title,
+ stream_url);
- meta_length = strlen(icy_metadata);
+ size_t meta_length = strlen(icy_metadata);
meta_length--; // subtract placeholder
@@ -85,43 +82,30 @@ icy_server_metadata_string(const char *stream_title, const char* stream_url)
Page *
icy_server_metadata_page(const Tag &tag, const TagType *types)
{
- const gchar *tag_items[TAG_NUM_OF_ITEM_TYPES];
- gint last_item, item;
- guint position;
- gchar *icy_string;
- gchar stream_title[(1 + 255 - 28) * 16]; // Length + Metadata -
- // "StreamTitle='';StreamUrl='';"
- // = 4081 - 28
- stream_title[0] = '\0';
-
- last_item = -1;
+ const char *tag_items[TAG_NUM_OF_ITEM_TYPES];
+ int last_item = -1;
while (*types != TAG_NUM_OF_ITEM_TYPES) {
- const gchar *tag_item = tag.GetValue(*types++);
+ const char *tag_item = tag.GetValue(*types++);
if (tag_item)
tag_items[++last_item] = tag_item;
}
- position = item = 0;
- while (position < sizeof(stream_title) && item <= last_item) {
- gint length = 0;
-
- length = g_strlcpy(stream_title + position,
- tag_items[item++],
- sizeof(stream_title) - position);
+ int item = 0;
- position += length;
+ // Length + Metadata - "StreamTitle='';StreamUrl='';" = 4081 - 28
+ char stream_title[(1 + 255 - 28) * 16];
+ char *p = stream_title, *const end = stream_title + ARRAY_SIZE(stream_title);
+ stream_title[0] = '\0';
- if (item <= last_item) {
- length = g_strlcpy(stream_title + position,
- " - ",
- sizeof(stream_title) - position);
+ while (p < end && item <= last_item) {
+ p = CopyString(p, tag_items[item++], end - p);
- position += length;
- }
+ if (item <= last_item)
+ p = CopyString(p, " - ", end - p);
}
- icy_string = icy_server_metadata_string(stream_title, "");
+ char *icy_string = icy_server_metadata_string(stream_title, "");
if (icy_string == nullptr)
return nullptr;
diff --git a/src/output/plugins/httpd/IcyMetaDataServer.hxx b/src/output/plugins/httpd/IcyMetaDataServer.hxx
index 773b46641..38415e5bd 100644
--- a/src/output/plugins/httpd/IcyMetaDataServer.hxx
+++ b/src/output/plugins/httpd/IcyMetaDataServer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/Page.cxx b/src/output/plugins/httpd/Page.cxx
index e22134bbc..ff7036645 100644
--- a/src/output/plugins/httpd/Page.cxx
+++ b/src/output/plugins/httpd/Page.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/httpd/Page.hxx b/src/output/plugins/httpd/Page.hxx
index 95f35d06a..88b7c2d85 100644
--- a/src/output/plugins/httpd/Page.hxx
+++ b/src/output/plugins/httpd/Page.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/output/plugins/sles/SlesOutputPlugin.cxx b/src/output/plugins/sles/SlesOutputPlugin.cxx
index 85fd9f2f2..94084e1b8 100644
--- a/src/output/plugins/sles/SlesOutputPlugin.cxx
+++ b/src/output/plugins/sles/SlesOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
#include "Play.hxx"
#include "AndroidSimpleBufferQueue.hxx"
#include "../../OutputAPI.hxx"
+#include "../../Wrapper.hxx"
#include "util/Macros.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -34,6 +35,8 @@
#include <SLES/OpenSLES_Android.h>
class SlesOutput {
+ friend struct AudioOutputWrapper<SlesOutput>;
+
static constexpr unsigned N_BUFFERS = 3;
static constexpr size_t BUFFER_SIZE = 65536;
@@ -88,11 +91,11 @@ public:
return &base;
}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
}
- bool Configure(const config_param &param, Error &error);
+ bool Configure(const ConfigBlock &block, Error &error);
bool Open(AudioFormat &audio_format, Error &error);
void Close();
@@ -126,7 +129,7 @@ private:
static constexpr Domain sles_domain("sles");
inline bool
-SlesOutput::Configure(const config_param &, Error &)
+SlesOutput::Configure(const ConfigBlock &, Error &)
{
return true;
}
@@ -442,12 +445,12 @@ sles_test_default_device()
}
static AudioOutput *
-sles_output_init(const config_param &param, Error &error)
+sles_output_init(const ConfigBlock &block, Error &error)
{
SlesOutput *sles = new SlesOutput();
- if (!sles->Initialize(param, error) ||
- !sles->Configure(param, error)) {
+ if (!sles->Initialize(block, error) ||
+ !sles->Configure(block, error)) {
delete sles;
return nullptr;
}
@@ -455,85 +458,22 @@ sles_output_init(const config_param &param, Error &error)
return *sles;
}
-static void
-sles_output_finish(AudioOutput *ao)
-{
- SlesOutput *sles = (SlesOutput *)ao;
-
- delete sles;
-}
-
-static bool
-sles_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- return sles.Open(audio_format, error);
-}
-
-static void
-sles_output_close(AudioOutput *ao)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- sles.Close();
-}
-
-static unsigned
-sles_output_delay(AudioOutput *ao)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- return sles.Delay();
-}
-
-static size_t
-sles_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- return sles.Play(chunk, size, error);
-}
-
-static void
-sles_output_drain(AudioOutput *ao)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- sles.Drain();
-}
-
-static void
-sles_output_cancel(AudioOutput *ao)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- sles.Cancel();
-}
-
-static bool
-sles_output_pause(AudioOutput *ao)
-{
- SlesOutput &sles = *(SlesOutput *)ao;
-
- return sles.Pause();
-}
+typedef AudioOutputWrapper<SlesOutput> Wrapper;
const struct AudioOutputPlugin sles_output_plugin = {
"sles",
sles_test_default_device,
sles_output_init,
- sles_output_finish,
+ &Wrapper::Finish,
nullptr,
nullptr,
- sles_output_open,
- sles_output_close,
- sles_output_delay,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- sles_output_play,
- sles_output_drain,
- sles_output_cancel,
- sles_output_pause,
+ &Wrapper::Play,
+ &Wrapper::Drain,
+ &Wrapper::Cancel,
+ &Wrapper::Pause,
nullptr,
};
diff --git a/src/output/plugins/sles/SlesOutputPlugin.hxx b/src/output/plugins/sles/SlesOutputPlugin.hxx
index 5424dec2e..5a7595c24 100644
--- a/src/output/plugins/sles/SlesOutputPlugin.hxx
+++ b/src/output/plugins/sles/SlesOutputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/ChannelsConverter.cxx b/src/pcm/ChannelsConverter.cxx
index 714613788..261af77ca 100644
--- a/src/pcm/ChannelsConverter.cxx
+++ b/src/pcm/ChannelsConverter.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/ChannelsConverter.hxx b/src/pcm/ChannelsConverter.hxx
index 1374f9f5d..aba230a86 100644
--- a/src/pcm/ChannelsConverter.hxx
+++ b/src/pcm/ChannelsConverter.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx
index f6aec3f95..30cb801c7 100644
--- a/src/pcm/ConfiguredResampler.cxx
+++ b/src/pcm/ConfiguredResampler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,13 +23,15 @@
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
#include "config/ConfigError.hxx"
+#include "config/Block.hxx"
+#include "config/Param.hxx"
#include "util/Error.hxx"
-#ifdef HAVE_LIBSAMPLERATE
+#ifdef ENABLE_LIBSAMPLERATE
#include "LibsamplerateResampler.hxx"
#endif
-#ifdef HAVE_SOXR
+#ifdef ENABLE_SOXR
#include "SoxrResampler.hxx"
#endif
@@ -38,45 +40,130 @@
enum class SelectedResampler {
FALLBACK,
-#ifdef HAVE_LIBSAMPLERATE
+#ifdef ENABLE_LIBSAMPLERATE
LIBSAMPLERATE,
#endif
-#ifdef HAVE_SOXR
+#ifdef ENABLE_SOXR
SOXR,
#endif
};
static SelectedResampler selected_resampler = SelectedResampler::FALLBACK;
-bool
-pcm_resampler_global_init(Error &error)
+static const ConfigBlock *
+MakeResamplerDefaultConfig(ConfigBlock &block)
{
- const char *converter =
- config_get_string(CONF_SAMPLERATE_CONVERTER, "");
+ assert(block.IsEmpty());
+
+#ifdef ENABLE_LIBSAMPLERATE
+ block.AddBlockParam("plugin", "libsamplerate");
+#elif defined(ENABLE_SOXR)
+ block.AddBlockParam("plugin", "soxr");
+#else
+ block.AddBlockParam("plugin", "internal");
+#endif
+ return &block;
+}
- if (strcmp(converter, "internal") == 0)
- return true;
+/**
+ * Convert the old "samplerate_converter" setting to a new-style
+ * "resampler" block.
+ */
+static const ConfigBlock *
+MigrateResamplerConfig(const config_param &param, ConfigBlock &block)
+{
+ assert(block.IsEmpty());
-#ifdef HAVE_SOXR
- if (memcmp(converter, "soxr", 4) == 0) {
- selected_resampler = SelectedResampler::SOXR;
- return pcm_resample_soxr_global_init(converter, error);
+ block.line = param.line;
+
+ const char *converter = param.value.c_str();
+ if (*converter == 0 || strcmp(converter, "internal") == 0) {
+ block.AddBlockParam("plugin", "internal");
+ return &block;
+ }
+
+#ifdef ENABLE_SOXR
+ if (strcmp(converter, "soxr") == 0) {
+ block.AddBlockParam("plugin", "soxr");
+ return &block;
}
-#endif
-#ifdef HAVE_LIBSAMPLERATE
- selected_resampler = SelectedResampler::LIBSAMPLERATE;
- return pcm_resample_lsr_global_init(converter, error);
+ if (memcmp(converter, "soxr ", 5) == 0) {
+ block.AddBlockParam("plugin", "soxr");
+ block.AddBlockParam("quality", converter + 5);
+ return &block;
+ }
#endif
- if (*converter == 0)
- return true;
+ block.AddBlockParam("plugin", "libsamplerate");
+ block.AddBlockParam("type", converter);
+ return &block;
+}
+
+static const ConfigBlock *
+MigrateResamplerConfig(const config_param *param, ConfigBlock &buffer)
+{
+ assert(buffer.IsEmpty());
- error.Format(config_domain,
- "The samplerate_converter '%s' is not available",
- converter);
- return false;
+ return param == nullptr
+ ? MakeResamplerDefaultConfig(buffer)
+ : MigrateResamplerConfig(*param, buffer);
+}
+
+static const ConfigBlock *
+GetResamplerConfig(ConfigBlock &buffer, Error &error)
+{
+ const auto *old_param =
+ config_get_param(ConfigOption::SAMPLERATE_CONVERTER);
+ const auto *block = config_get_block(ConfigBlockOption::RESAMPLER);
+ if (block == nullptr)
+ return MigrateResamplerConfig(old_param, buffer);
+
+ if (old_param != nullptr) {
+ error.Format(config_domain,
+ "Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)",
+ block->line, old_param->line);
+ return nullptr;
+ }
+
+ return block;
+}
+
+bool
+pcm_resampler_global_init(Error &error)
+{
+ ConfigBlock buffer;
+ const auto *block = GetResamplerConfig(buffer, error);
+ if (block == nullptr)
+ return false;
+
+ const char *plugin_name = block->GetBlockValue("plugin");
+ if (plugin_name == nullptr) {
+ error.Format(config_domain,
+ "'plugin' missing in line %d", block->line);
+ return false;
+ }
+
+ if (strcmp(plugin_name, "internal") == 0) {
+ selected_resampler = SelectedResampler::FALLBACK;
+ return true;
+#ifdef ENABLE_SOXR
+ } else if (strcmp(plugin_name, "soxr") == 0) {
+ selected_resampler = SelectedResampler::SOXR;
+ return pcm_resample_soxr_global_init(*block, error);
+#endif
+#ifdef ENABLE_LIBSAMPLERATE
+ } else if (strcmp(plugin_name, "libsamplerate") == 0) {
+ selected_resampler = SelectedResampler::LIBSAMPLERATE;
+ return pcm_resample_lsr_global_init(*block, error);
+#endif
+ } else {
+ error.Format(config_domain,
+ "No such resampler plugin: %s",
+ plugin_name);
+ return false;
+ }
}
PcmResampler *
@@ -86,12 +173,12 @@ pcm_resampler_create()
case SelectedResampler::FALLBACK:
return new FallbackPcmResampler();
-#ifdef HAVE_LIBSAMPLERATE
+#ifdef ENABLE_LIBSAMPLERATE
case SelectedResampler::LIBSAMPLERATE:
return new LibsampleratePcmResampler();
#endif
-#ifdef HAVE_SOXR
+#ifdef ENABLE_SOXR
case SelectedResampler::SOXR:
return new SoxrPcmResampler();
#endif
diff --git a/src/pcm/ConfiguredResampler.hxx b/src/pcm/ConfiguredResampler.hxx
index 2b14b381e..090f2ae0a 100644
--- a/src/pcm/ConfiguredResampler.hxx
+++ b/src/pcm/ConfiguredResampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/Domain.cxx b/src/pcm/Domain.cxx
index ecd5c22a4..8673e5a10 100644
--- a/src/pcm/Domain.cxx
+++ b/src/pcm/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/Domain.hxx b/src/pcm/Domain.hxx
index 781d5c71b..47d5ef8b9 100644
--- a/src/pcm/Domain.hxx
+++ b/src/pcm/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/FallbackResampler.cxx b/src/pcm/FallbackResampler.cxx
index bd3f20d86..74fbc29bd 100644
--- a/src/pcm/FallbackResampler.cxx
+++ b/src/pcm/FallbackResampler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/FallbackResampler.hxx b/src/pcm/FallbackResampler.hxx
index 38273f53f..d96b89d4f 100644
--- a/src/pcm/FallbackResampler.hxx
+++ b/src/pcm/FallbackResampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/FloatConvert.hxx b/src/pcm/FloatConvert.hxx
index 93e867159..47fe8d65a 100644
--- a/src/pcm/FloatConvert.hxx
+++ b/src/pcm/FloatConvert.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/FormatConverter.cxx b/src/pcm/FormatConverter.cxx
index 8874e1b3c..28e585e70 100644
--- a/src/pcm/FormatConverter.cxx
+++ b/src/pcm/FormatConverter.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/FormatConverter.hxx b/src/pcm/FormatConverter.hxx
index 3d8b6fb75..a67fcd7d6 100644
--- a/src/pcm/FormatConverter.hxx
+++ b/src/pcm/FormatConverter.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/GlueResampler.cxx b/src/pcm/GlueResampler.cxx
index 0f5fe0271..3b1b61c3b 100644
--- a/src/pcm/GlueResampler.cxx
+++ b/src/pcm/GlueResampler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/GlueResampler.hxx b/src/pcm/GlueResampler.hxx
index aff07823e..7471d39b7 100644
--- a/src/pcm/GlueResampler.hxx
+++ b/src/pcm/GlueResampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/LibsamplerateResampler.cxx b/src/pcm/LibsamplerateResampler.cxx
index 8b22f1e32..cc6f3d43f 100644
--- a/src/pcm/LibsamplerateResampler.cxx
+++ b/src/pcm/LibsamplerateResampler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,7 @@
#include "config.h"
#include "LibsamplerateResampler.hxx"
+#include "config/Block.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -63,8 +64,9 @@ lsr_parse_converter(const char *s)
}
bool
-pcm_resample_lsr_global_init(const char *converter, Error &error)
+pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error)
{
+ const char *converter = block.GetBlockValue("type", "2");
if (!lsr_parse_converter(converter)) {
error.Format(libsamplerate_domain,
"unknown samplerate converter '%s'", converter);
diff --git a/src/pcm/LibsamplerateResampler.hxx b/src/pcm/LibsamplerateResampler.hxx
index 4f4e645e6..f19dc19eb 100644
--- a/src/pcm/LibsamplerateResampler.hxx
+++ b/src/pcm/LibsamplerateResampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +27,8 @@
#include <samplerate.h>
+struct ConfigBlock;
+
/**
* A resampler using libsamplerate.
*/
@@ -51,6 +53,6 @@ private:
};
bool
-pcm_resample_lsr_global_init(const char *converter, Error &error);
+pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error);
#endif
diff --git a/src/pcm/Neon.hxx b/src/pcm/Neon.hxx
index 7109778ab..a2a92eea6 100644
--- a/src/pcm/Neon.hxx
+++ b/src/pcm/Neon.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmBuffer.cxx b/src/pcm/PcmBuffer.cxx
index 7bba2de47..e767872bd 100644
--- a/src/pcm/PcmBuffer.cxx
+++ b/src/pcm/PcmBuffer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmBuffer.hxx b/src/pcm/PcmBuffer.hxx
index f56a85985..eafdc649e 100644
--- a/src/pcm/PcmBuffer.hxx
+++ b/src/pcm/PcmBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmChannels.cxx b/src/pcm/PcmChannels.cxx
index 276f31045..5cf730e6c 100644
--- a/src/pcm/PcmChannels.cxx
+++ b/src/pcm/PcmChannels.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmChannels.hxx b/src/pcm/PcmChannels.hxx
index 6ad093c3b..eb6aa4828 100644
--- a/src/pcm/PcmChannels.hxx
+++ b/src/pcm/PcmChannels.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmConvert.cxx b/src/pcm/PcmConvert.cxx
index 438566759..ccc45c246 100644
--- a/src/pcm/PcmConvert.cxx
+++ b/src/pcm/PcmConvert.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmConvert.hxx b/src/pcm/PcmConvert.hxx
index 26ab02923..716ac9e05 100644
--- a/src/pcm/PcmConvert.hxx
+++ b/src/pcm/PcmConvert.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDither.cxx b/src/pcm/PcmDither.cxx
index 7b2a9e900..25252458b 100644
--- a/src/pcm/PcmDither.cxx
+++ b/src/pcm/PcmDither.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDither.hxx b/src/pcm/PcmDither.hxx
index 54b0f7315..86d844eae 100644
--- a/src/pcm/PcmDither.hxx
+++ b/src/pcm/PcmDither.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDop.cxx b/src/pcm/PcmDop.cxx
index b2096d9e4..e60c6d14d 100644
--- a/src/pcm/PcmDop.cxx
+++ b/src/pcm/PcmDop.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDop.hxx b/src/pcm/PcmDop.hxx
index 03161c456..82c045911 100644
--- a/src/pcm/PcmDop.hxx
+++ b/src/pcm/PcmDop.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDsd.cxx b/src/pcm/PcmDsd.cxx
index 53d26d480..f27c63f33 100644
--- a/src/pcm/PcmDsd.cxx
+++ b/src/pcm/PcmDsd.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmDsd.hxx b/src/pcm/PcmDsd.hxx
index e3e3a3cb1..89654ebe6 100644
--- a/src/pcm/PcmDsd.hxx
+++ b/src/pcm/PcmDsd.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx
index ef099ba71..af2eb7d9f 100644
--- a/src/pcm/PcmExport.cxx
+++ b/src/pcm/PcmExport.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmExport.hxx b/src/pcm/PcmExport.hxx
index b99a35835..c174437cc 100644
--- a/src/pcm/PcmExport.hxx
+++ b/src/pcm/PcmExport.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmFormat.cxx b/src/pcm/PcmFormat.cxx
index 4cabc05a0..a70a38982 100644
--- a/src/pcm/PcmFormat.cxx
+++ b/src/pcm/PcmFormat.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmFormat.hxx b/src/pcm/PcmFormat.hxx
index da182e771..cc6db2c8d 100644
--- a/src/pcm/PcmFormat.hxx
+++ b/src/pcm/PcmFormat.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmMix.cxx b/src/pcm/PcmMix.cxx
index d21b5f04b..b67a4ec24 100644
--- a/src/pcm/PcmMix.cxx
+++ b/src/pcm/PcmMix.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmMix.hxx b/src/pcm/PcmMix.hxx
index 4e22a33f1..a906dc402 100644
--- a/src/pcm/PcmMix.hxx
+++ b/src/pcm/PcmMix.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmPack.cxx b/src/pcm/PcmPack.cxx
index 7a3379ad0..ef4406b82 100644
--- a/src/pcm/PcmPack.cxx
+++ b/src/pcm/PcmPack.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmPack.hxx b/src/pcm/PcmPack.hxx
index 271a3cd25..613298e2e 100644
--- a/src/pcm/PcmPack.hxx
+++ b/src/pcm/PcmPack.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmPrng.hxx b/src/pcm/PcmPrng.hxx
index 5233caba6..38b48de7f 100644
--- a/src/pcm/PcmPrng.hxx
+++ b/src/pcm/PcmPrng.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/PcmUtils.hxx b/src/pcm/PcmUtils.hxx
index 23870a729..9ea9cf3b3 100644
--- a/src/pcm/PcmUtils.hxx
+++ b/src/pcm/PcmUtils.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/Resampler.hxx b/src/pcm/Resampler.hxx
index 9b6ccbbc7..5525b6cda 100644
--- a/src/pcm/Resampler.hxx
+++ b/src/pcm/Resampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/ShiftConvert.hxx b/src/pcm/ShiftConvert.hxx
index 92f96b7ba..e678abc56 100644
--- a/src/pcm/ShiftConvert.hxx
+++ b/src/pcm/ShiftConvert.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx
index b9d6fc099..6f58a6092 100644
--- a/src/pcm/SoxrResampler.cxx
+++ b/src/pcm/SoxrResampler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "config.h"
#include "SoxrResampler.hxx"
#include "AudioFormat.hxx"
+#include "config/Block.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -32,68 +33,76 @@
static constexpr Domain soxr_domain("soxr");
-static unsigned long soxr_quality_recipe = SOXR_HQ;
+static constexpr unsigned long SOXR_DEFAULT_RECIPE = SOXR_HQ;
+/**
+ * Special value for "invalid argument".
+ */
+static constexpr unsigned long SOXR_INVALID_RECIPE = -1;
+
+static soxr_quality_spec_t soxr_quality;
+static soxr_runtime_spec_t soxr_runtime;
+
+static constexpr struct {
+ unsigned long recipe;
+ const char *name;
+} soxr_quality_table[] = {
+ { SOXR_VHQ, "very high" },
+ { SOXR_HQ, "high" },
+ { SOXR_MQ, "medium" },
+ { SOXR_LQ, "low" },
+ { SOXR_QQ, "quick" },
+ { SOXR_INVALID_RECIPE, nullptr }
+};
+
+gcc_const
static const char *
soxr_quality_name(unsigned long recipe)
{
- switch (recipe) {
- case SOXR_VHQ:
- return "Very High Quality";
- case SOXR_HQ:
- return "High Quality";
- case SOXR_MQ:
- return "Medium Quality";
- case SOXR_LQ:
- return "Low Quality";
- case SOXR_QQ:
- return "Quick";
- }
+ for (const auto *i = soxr_quality_table;; ++i) {
+ assert(i->name != nullptr);
- gcc_unreachable();
+ if (i->recipe == recipe)
+ return i->name;
+ }
}
-static bool
-soxr_parse_converter(const char *converter)
+gcc_pure
+static unsigned long
+soxr_parse_quality(const char *quality)
{
- assert(converter != nullptr);
-
- assert(memcmp(converter, "soxr", 4) == 0);
- if (converter[4] == '\0')
- return true;
- if (converter[4] != ' ')
- return false;
+ if (quality == nullptr)
+ return SOXR_DEFAULT_RECIPE;
- // converter example is "soxr very high", we want the "very high" part
- const char *quality = converter + 5;
- if (strcmp(quality, "very high") == 0)
- soxr_quality_recipe = SOXR_VHQ;
- else if (strcmp(quality, "high") == 0)
- soxr_quality_recipe = SOXR_HQ;
- else if (strcmp(quality, "medium") == 0)
- soxr_quality_recipe = SOXR_MQ;
- else if (strcmp(quality, "low") == 0)
- soxr_quality_recipe = SOXR_LQ;
- else if (strcmp(quality, "quick") == 0)
- soxr_quality_recipe = SOXR_QQ;
- else
- return false;
+ for (const auto *i = soxr_quality_table; i->name != nullptr; ++i)
+ if (strcmp(i->name, "very high") == 0)
+ return i->recipe;
- return true;
+ return SOXR_INVALID_RECIPE;
}
bool
-pcm_resample_soxr_global_init(const char *converter, Error &error)
+pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error)
{
- if (!soxr_parse_converter(converter)) {
+ const char *quality_string = block.GetBlockValue("quality");
+ unsigned long recipe = soxr_parse_quality(quality_string);
+ if (recipe == SOXR_INVALID_RECIPE) {
+ assert(quality_string != nullptr);
+
error.Format(soxr_domain,
- "unknown samplerate converter '%s'", converter);
+ "unknown quality setting '%s' in line %d",
+ quality_string, block.line);
return false;
}
+ soxr_quality = soxr_quality_spec(recipe, 0);
+
FormatDebug(soxr_domain,
"soxr converter '%s'",
- soxr_quality_name(soxr_quality_recipe));
+ soxr_quality_name(recipe));
+
+ const unsigned n_threads = block.GetBlockValue("threads", 1);
+ soxr_runtime = soxr_runtime_spec(n_threads);
return true;
}
@@ -106,10 +115,9 @@ SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
assert(audio_valid_sample_rate(new_sample_rate));
soxr_error_t e;
- soxr_quality_spec_t quality = soxr_quality_spec(soxr_quality_recipe, 0);
soxr = soxr_create(af.sample_rate, new_sample_rate,
af.channels, &e,
- nullptr, &quality, nullptr);
+ nullptr, &soxr_quality, &soxr_runtime);
if (soxr == nullptr) {
error.Format(soxr_domain,
"soxr initialization has failed: %s", e);
diff --git a/src/pcm/SoxrResampler.hxx b/src/pcm/SoxrResampler.hxx
index e4cba4a64..6c31ca45a 100644
--- a/src/pcm/SoxrResampler.hxx
+++ b/src/pcm/SoxrResampler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,7 @@
#include "Compiler.h"
struct AudioFormat;
+struct ConfigBlock;
/**
* A resampler using soxr.
@@ -46,6 +47,6 @@ public:
};
bool
-pcm_resample_soxr_global_init(const char *converter, Error &error);
+pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error);
#endif
diff --git a/src/pcm/Traits.hxx b/src/pcm/Traits.hxx
index 97259ac73..3d124ea2f 100644
--- a/src/pcm/Traits.hxx
+++ b/src/pcm/Traits.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/Volume.cxx b/src/pcm/Volume.cxx
index b12d8fd41..86dd8bd71 100644
--- a/src/pcm/Volume.cxx
+++ b/src/pcm/Volume.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/pcm/Volume.hxx b/src/pcm/Volume.hxx
index a156fc72e..5d51343b3 100644
--- a/src/pcm/Volume.hxx
+++ b/src/pcm/Volume.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/CloseSongEnumerator.cxx b/src/playlist/CloseSongEnumerator.cxx
index 2dddef823..6a95fd66e 100644
--- a/src/playlist/CloseSongEnumerator.cxx
+++ b/src/playlist/CloseSongEnumerator.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/CloseSongEnumerator.hxx b/src/playlist/CloseSongEnumerator.hxx
index 17f015394..f8e352f9b 100644
--- a/src/playlist/CloseSongEnumerator.hxx
+++ b/src/playlist/CloseSongEnumerator.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/MemorySongEnumerator.cxx b/src/playlist/MemorySongEnumerator.cxx
index c3127c2bf..e34a8d628 100644
--- a/src/playlist/MemorySongEnumerator.cxx
+++ b/src/playlist/MemorySongEnumerator.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/MemorySongEnumerator.hxx b/src/playlist/MemorySongEnumerator.hxx
index d1259f011..5a1493810 100644
--- a/src/playlist/MemorySongEnumerator.hxx
+++ b/src/playlist/MemorySongEnumerator.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistAny.cxx b/src/playlist/PlaylistAny.cxx
index 7093fb99a..be59d6b0c 100644
--- a/src/playlist/PlaylistAny.cxx
+++ b/src/playlist/PlaylistAny.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistAny.hxx b/src/playlist/PlaylistAny.hxx
index 23b0075b6..ca9bf662d 100644
--- a/src/playlist/PlaylistAny.hxx
+++ b/src/playlist/PlaylistAny.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistMapper.cxx b/src/playlist/PlaylistMapper.cxx
index 042a39d34..dbac3ccc7 100644
--- a/src/playlist/PlaylistMapper.cxx
+++ b/src/playlist/PlaylistMapper.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistMapper.hxx b/src/playlist/PlaylistMapper.hxx
index 29ce45083..e5309d649 100644
--- a/src/playlist/PlaylistMapper.hxx
+++ b/src/playlist/PlaylistMapper.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistPlugin.hxx b/src/playlist/PlaylistPlugin.hxx
index fd779ad8d..adbf4b35d 100644
--- a/src/playlist/PlaylistPlugin.hxx
+++ b/src/playlist/PlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
#ifndef MPD_PLAYLIST_PLUGIN_HXX
#define MPD_PLAYLIST_PLUGIN_HXX
-struct config_param;
+struct ConfigBlock;
class InputStream;
struct Tag;
class Mutex;
@@ -38,7 +38,7 @@ struct playlist_plugin {
* @return true if the plugin was initialized successfully,
* false if the plugin is not available
*/
- bool (*init)(const config_param &param);
+ bool (*init)(const ConfigBlock &block);
/**
* Deinitialize a plugin which was initialized successfully.
@@ -75,10 +75,10 @@ struct playlist_plugin {
*/
static inline bool
playlist_plugin_init(const struct playlist_plugin *plugin,
- const config_param &param)
+ const ConfigBlock &block)
{
return plugin->init != nullptr
- ? plugin->init(param)
+ ? plugin->init(block)
: true;
}
diff --git a/src/playlist/PlaylistQueue.cxx b/src/playlist/PlaylistQueue.cxx
index b10a26172..b6f85f586 100644
--- a/src/playlist/PlaylistQueue.cxx
+++ b/src/playlist/PlaylistQueue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistQueue.hxx b/src/playlist/PlaylistQueue.hxx
index 28eb86fcc..16bafaecf 100644
--- a/src/playlist/PlaylistQueue.hxx
+++ b/src/playlist/PlaylistQueue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistRegistry.cxx b/src/playlist/PlaylistRegistry.cxx
index 600f32b31..f8b1052bc 100644
--- a/src/playlist/PlaylistRegistry.cxx
+++ b/src/playlist/PlaylistRegistry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,7 +35,7 @@
#include "util/Error.hxx"
#include "util/Macros.hxx"
#include "config/ConfigGlobal.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "Log.hxx"
#include <assert.h>
@@ -44,11 +44,8 @@
const struct playlist_plugin *const playlist_plugins[] = {
&extm3u_playlist_plugin,
&m3u_playlist_plugin,
-#ifdef HAVE_GLIB
- // TODO: enable without GLib
&pls_playlist_plugin,
-#endif
-#ifdef HAVE_EXPAT
+#ifdef ENABLE_EXPAT
&xspf_playlist_plugin,
&asx_playlist_plugin,
&rss_playlist_plugin,
@@ -56,8 +53,10 @@ const struct playlist_plugin *const playlist_plugins[] = {
#ifdef ENABLE_SOUNDCLOUD
&soundcloud_playlist_plugin,
#endif
+#ifdef ENABLE_CUE
&cue_playlist_plugin,
&embcue_playlist_plugin,
+#endif
nullptr
};
@@ -74,13 +73,13 @@ static bool playlist_plugins_enabled[n_playlist_plugins];
void
playlist_list_global_init(void)
{
- const config_param empty;
+ const ConfigBlock empty;
for (unsigned i = 0; playlist_plugins[i] != nullptr; ++i) {
const struct playlist_plugin *plugin = playlist_plugins[i];
- const struct config_param *param =
- config_find_block(CONF_PLAYLIST_PLUGIN, "name",
- plugin->name);
+ const auto *param =
+ config_find_block(ConfigBlockOption::PLAYLIST_PLUGIN,
+ "name", plugin->name);
if (param == nullptr)
param = &empty;
else if (!param->GetBlockValue("enabled", true))
diff --git a/src/playlist/PlaylistRegistry.hxx b/src/playlist/PlaylistRegistry.hxx
index 7ce559baa..6b10b035f 100644
--- a/src/playlist/PlaylistRegistry.hxx
+++ b/src/playlist/PlaylistRegistry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistSong.cxx b/src/playlist/PlaylistSong.cxx
index 3603c1add..72f913418 100644
--- a/src/playlist/PlaylistSong.cxx
+++ b/src/playlist/PlaylistSong.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistSong.hxx b/src/playlist/PlaylistSong.hxx
index 278df46a8..0674c02c9 100644
--- a/src/playlist/PlaylistSong.hxx
+++ b/src/playlist/PlaylistSong.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistStream.cxx b/src/playlist/PlaylistStream.cxx
index 074f39d66..32e049c78 100644
--- a/src/playlist/PlaylistStream.cxx
+++ b/src/playlist/PlaylistStream.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/PlaylistStream.hxx b/src/playlist/PlaylistStream.hxx
index c07ae0b09..9f77cbea1 100644
--- a/src/playlist/PlaylistStream.hxx
+++ b/src/playlist/PlaylistStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/Print.cxx b/src/playlist/Print.cxx
index 8f743f56d..3de9807b7 100644
--- a/src/playlist/Print.cxx
+++ b/src/playlist/Print.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/Print.hxx b/src/playlist/Print.hxx
index c2fff5475..02096bdc2 100644
--- a/src/playlist/Print.hxx
+++ b/src/playlist/Print.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/SongEnumerator.hxx b/src/playlist/SongEnumerator.hxx
index 75295add1..0f6997785 100644
--- a/src/playlist/SongEnumerator.hxx
+++ b/src/playlist/SongEnumerator.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/cue/CueParser.cxx b/src/playlist/cue/CueParser.cxx
index 372c90b78..80bf79bf6 100644
--- a/src/playlist/cue/CueParser.cxx
+++ b/src/playlist/cue/CueParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/cue/CueParser.hxx b/src/playlist/cue/CueParser.hxx
index 7e040169b..07010f7c4 100644
--- a/src/playlist/cue/CueParser.hxx
+++ b/src/playlist/cue/CueParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/AsxPlaylistPlugin.cxx b/src/playlist/plugins/AsxPlaylistPlugin.cxx
index 3185a8144..c6226346b 100644
--- a/src/playlist/plugins/AsxPlaylistPlugin.cxx
+++ b/src/playlist/plugins/AsxPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include "Log.hxx"
/**
- * This is the state object for the GLib XML parser.
+ * This is the state object for our XML parser.
*/
struct AsxParser {
/**
diff --git a/src/playlist/plugins/AsxPlaylistPlugin.hxx b/src/playlist/plugins/AsxPlaylistPlugin.hxx
index 63371be0f..b14eeda87 100644
--- a/src/playlist/plugins/AsxPlaylistPlugin.hxx
+++ b/src/playlist/plugins/AsxPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/CuePlaylistPlugin.cxx b/src/playlist/plugins/CuePlaylistPlugin.cxx
index b907d34d0..df6946abc 100644
--- a/src/playlist/plugins/CuePlaylistPlugin.cxx
+++ b/src/playlist/plugins/CuePlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/CuePlaylistPlugin.hxx b/src/playlist/plugins/CuePlaylistPlugin.hxx
index 4d833bfc2..6daad4241 100644
--- a/src/playlist/plugins/CuePlaylistPlugin.hxx
+++ b/src/playlist/plugins/CuePlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
index 8baa11c03..29b15b1de 100644
--- a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
+++ b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx
index 5eedf3f13..9721481d5 100644
--- a/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx
+++ b/src/playlist/plugins/EmbeddedCuePlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx b/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx
index 93316ca6c..e60ef4aa6 100644
--- a/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx
+++ b/src/playlist/plugins/ExtM3uPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx b/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx
index 5743ded43..625afcd2d 100644
--- a/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx
+++ b/src/playlist/plugins/ExtM3uPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/M3uPlaylistPlugin.cxx b/src/playlist/plugins/M3uPlaylistPlugin.cxx
index 0428d291a..9e7647dd7 100644
--- a/src/playlist/plugins/M3uPlaylistPlugin.cxx
+++ b/src/playlist/plugins/M3uPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/M3uPlaylistPlugin.hxx b/src/playlist/plugins/M3uPlaylistPlugin.hxx
index f1ad14069..9df4482d9 100644
--- a/src/playlist/plugins/M3uPlaylistPlugin.hxx
+++ b/src/playlist/plugins/M3uPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/PlsPlaylistPlugin.cxx b/src/playlist/plugins/PlsPlaylistPlugin.cxx
index f7724f522..0a97c72b3 100644
--- a/src/playlist/plugins/PlsPlaylistPlugin.cxx
+++ b/src/playlist/plugins/PlsPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,121 +21,142 @@
#include "PlsPlaylistPlugin.hxx"
#include "../PlaylistPlugin.hxx"
#include "../MemorySongEnumerator.hxx"
-#include "input/InputStream.hxx"
+#include "input/TextInputStream.hxx"
#include "DetachedSong.hxx"
#include "tag/TagBuilder.hxx"
+#include "util/ASCII.hxx"
+#include "util/StringUtil.hxx"
+#include "util/DivideString.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#include "Log.hxx"
-
-#include <glib.h>
#include <string>
-#include <stdio.h>
-#include <stdio.h>
+#include <stdlib.h>
static constexpr Domain pls_domain("pls");
-static void
-pls_parser(GKeyFile *keyfile, std::forward_list<DetachedSong> &songs)
+static bool
+FindPlaylistSection(TextInputStream &is)
{
- gchar *value;
- GError *error = nullptr;
- int num_entries = g_key_file_get_integer(keyfile, "playlist",
- "NumberOfEntries", &error);
- if (error) {
- FormatError(pls_domain,
- "Invalid PLS file: '%s'", error->message);
- g_error_free(error);
- error = nullptr;
-
- /* Hack to work around shoutcast failure to comform to spec */
- num_entries = g_key_file_get_integer(keyfile, "playlist",
- "numberofentries", &error);
- if (error) {
- g_error_free(error);
- error = nullptr;
- }
+ char *line;
+ while ((line = is.ReadLine()) != nullptr) {
+ line = Strip(line);
+ if (StringEqualsCaseASCII(line, "[playlist]"))
+ return true;
}
- for (; num_entries > 0; --num_entries) {
- char key[64];
- sprintf(key, "File%u", num_entries);
- char *uri = g_key_file_get_string(keyfile, "playlist", key,
- &error);
- if(error) {
- FormatError(pls_domain, "Invalid PLS entry %s: '%s'",
- key, error->message);
- g_error_free(error);
- return;
- }
+ return false;
+}
- TagBuilder tag;
+static bool
+ParsePls(TextInputStream &is, std::forward_list<DetachedSong> &songs)
+{
+ assert(songs.empty());
- sprintf(key, "Title%u", num_entries);
- value = g_key_file_get_string(keyfile, "playlist", key,
- nullptr);
- if (value != nullptr)
- tag.AddItem(TAG_TITLE, value);
+ if (!FindPlaylistSection(is))
+ return false;
- g_free(value);
+ unsigned n_entries = 0;
- sprintf(key, "Length%u", num_entries);
- int length = g_key_file_get_integer(keyfile, "playlist", key,
- nullptr);
- if (length > 0)
- tag.SetDuration(SignedSongTime::FromS(length));
+ struct Entry {
+ std::string file, title;
+ int length;
- songs.emplace_front(uri, tag.Commit());
- g_free(uri);
- }
+ Entry():length(-1) {}
+ };
-}
+ static constexpr unsigned MAX_ENTRIES = 65536;
-static SongEnumerator *
-pls_open_stream(InputStream &is)
-{
- GError *error = nullptr;
- Error error2;
-
- std::string kf_data;
-
- do {
- char buffer[1024];
- size_t nbytes = is.LockRead(buffer, sizeof(buffer), error2);
- if (nbytes == 0) {
- if (error2.IsDefined()) {
- LogError(error2);
- return nullptr;
- }
+ std::vector<Entry> entries;
+
+ char *line;
+ while ((line = is.ReadLine()) != nullptr) {
+ line = Strip(line);
+ if (*line == 0 || *line == ';')
+ continue;
+
+ if (*line == '[')
+ /* another section starts; we only want
+ [Playlist], so stop here */
break;
+
+ const DivideString ds(line, '=', true);
+ if (!ds.IsDefined())
+ continue;
+
+ const char *const name = ds.GetFirst();
+ const char *const value = ds.GetSecond();
+
+ if (StringEqualsCaseASCII(name, "NumberOfEntries")) {
+ n_entries = strtoul(value, nullptr, 10);
+ if (n_entries == 0)
+ /* empty file - nothing remains to be
+ done */
+ return true;
+
+ if (n_entries > MAX_ENTRIES)
+ n_entries = MAX_ENTRIES;
+ entries.resize(n_entries);
+ } else if (StringEqualsCaseASCII(name, "File", 4)) {
+ unsigned i = strtoul(name + 4, nullptr, 10);
+ if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
+ if (entries.size() < i)
+ entries.resize(i);
+ entries[i - 1].file = value;
+ }
+ } else if (StringEqualsCaseASCII(name, "Title", 5)) {
+ unsigned i = strtoul(name + 5, nullptr, 10);
+ if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
+ if (entries.size() < i)
+ entries.resize(i);
+ entries[i - 1].title = value;
+ }
+ } else if (StringEqualsCaseASCII(name, "Length", 6)) {
+ unsigned i = strtoul(name + 6, nullptr, 10);
+ if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
+ if (entries.size() < i)
+ entries.resize(i);
+ entries[i - 1].length = atoi(value);
+ }
}
+ }
- kf_data.append(buffer, nbytes);
- /* Limit to 64k */
- } while (kf_data.length() < 65536);
+ if (n_entries == 0)
+ /* no "NumberOfEntries" found */
+ return false;
- if (kf_data.empty()) {
- LogWarning(pls_domain, "KeyFile parser failed: No Data");
- return nullptr;
- }
+ auto i = songs.before_begin();
+ for (const auto &entry : entries) {
+ const char *uri = entry.file.c_str();
- GKeyFile *keyfile = g_key_file_new();
- if (!g_key_file_load_from_data(keyfile,
- kf_data.data(), kf_data.length(),
- G_KEY_FILE_NONE, &error)) {
- FormatError(pls_domain,
- "KeyFile parser failed: %s", error->message);
- g_error_free(error);
- g_key_file_free(keyfile);
- return nullptr;
+ TagBuilder tag;
+ if (!entry.title.empty())
+ tag.AddItem(TAG_TITLE, entry.title.c_str());
+
+ if (entry.length > 0)
+ tag.SetDuration(SignedSongTime::FromS(entry.length));
+
+ i = songs.emplace_after(i, uri, tag.Commit());
}
+ return true;
+}
+
+static bool
+ParsePls(InputStream &is, std::forward_list<DetachedSong> &songs)
+{
+ TextInputStream tis(is);
+ return ParsePls(tis, songs);
+}
+
+static SongEnumerator *
+pls_open_stream(InputStream &is)
+{
std::forward_list<DetachedSong> songs;
- pls_parser(keyfile, songs);
- g_key_file_free(keyfile);
+ if (!ParsePls(is, songs))
+ return nullptr;
return new MemorySongEnumerator(std::move(songs));
}
diff --git a/src/playlist/plugins/PlsPlaylistPlugin.hxx b/src/playlist/plugins/PlsPlaylistPlugin.hxx
index 1a3f33873..c7a1e331c 100644
--- a/src/playlist/plugins/PlsPlaylistPlugin.hxx
+++ b/src/playlist/plugins/PlsPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/RssPlaylistPlugin.cxx b/src/playlist/plugins/RssPlaylistPlugin.cxx
index 6f9aad54b..27588cddf 100644
--- a/src/playlist/plugins/RssPlaylistPlugin.cxx
+++ b/src/playlist/plugins/RssPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include "Log.hxx"
/**
- * This is the state object for the GLib XML parser.
+ * This is the state object for the our XML parser.
*/
struct RssParser {
/**
diff --git a/src/playlist/plugins/RssPlaylistPlugin.hxx b/src/playlist/plugins/RssPlaylistPlugin.hxx
index a00a5a898..4928df904 100644
--- a/src/playlist/plugins/RssPlaylistPlugin.hxx
+++ b/src/playlist/plugins/RssPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx
index ec4d240a5..d6f25f48c 100644
--- a/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx
+++ b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,20 +21,21 @@
#include "SoundCloudPlaylistPlugin.hxx"
#include "../PlaylistPlugin.hxx"
#include "../MemorySongEnumerator.hxx"
-#include "config/ConfigData.hxx"
+#include "config/Block.hxx"
#include "input/InputStream.hxx"
#include "tag/TagBuilder.hxx"
#include "util/StringUtil.hxx"
+#include "util/Alloc.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
-#include <glib.h>
#include <yajl/yajl_parse.h>
#include <string>
#include <string.h>
+#include <stdlib.h>
static struct {
std::string apikey;
@@ -43,10 +44,10 @@ static struct {
static constexpr Domain soundcloud_domain("soundcloud");
static bool
-soundcloud_init(const config_param &param)
+soundcloud_init(const ConfigBlock &block)
{
// APIKEY for MPD application, registered under DarkFox' account.
- soundcloud_config.apikey = param.GetBlockValue("apikey", "a25e51780f7f86af0afa91f241d091f8");
+ soundcloud_config.apikey = block.GetBlockValue("apikey", "a25e51780f7f86af0afa91f241d091f8");
if (soundcloud_config.apikey.empty()) {
LogDebug(soundcloud_domain,
"disabling the soundcloud playlist plugin "
@@ -60,7 +61,7 @@ soundcloud_init(const config_param &param)
/**
* Construct a full soundcloud resolver URL from the given fragment.
* @param uri uri of a soundcloud page (or just the path)
- * @return Constructed URL. Must be freed with g_free.
+ * @return Constructed URL. Must be freed with free().
*/
static char *
soundcloud_resolve(const char* uri)
@@ -68,18 +69,18 @@ soundcloud_resolve(const char* uri)
char *u, *ru;
if (StringStartsWith(uri, "https://")) {
- u = g_strdup(uri);
+ u = xstrdup(uri);
} else if (StringStartsWith(uri, "soundcloud.com")) {
- u = g_strconcat("https://", uri, nullptr);
+ u = xstrcatdup("https://", uri);
} else {
/* assume it's just a path on soundcloud.com */
- u = g_strconcat("https://soundcloud.com/", uri, nullptr);
+ u = xstrcatdup("https://soundcloud.com/", uri);
}
- ru = g_strconcat("https://api.soundcloud.com/resolve.json?url=",
- u, "&client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
- g_free(u);
+ ru = xstrcatdup("https://api.soundcloud.com/resolve.json?url=",
+ u, "&client_id=",
+ soundcloud_config.apikey.c_str());
+ free(u);
return ru;
}
@@ -111,12 +112,7 @@ struct parse_data {
};
static int
-handle_integer(void *ctx,
- long
-#ifndef HAVE_YAJL1
- long
-#endif
- intval)
+handle_integer(void *ctx, long long intval)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -132,25 +128,19 @@ handle_integer(void *ctx,
}
static int
-handle_string(void *ctx, const unsigned char* stringval,
-#ifdef HAVE_YAJL1
- unsigned int
-#else
- size_t
-#endif
- stringlen)
+handle_string(void *ctx, const unsigned char *stringval, size_t stringlen)
{
struct parse_data *data = (struct parse_data *) ctx;
const char *s = (const char *) stringval;
switch (data->key) {
case Title:
- g_free(data->title);
- data->title = g_strndup(s, stringlen);
+ free(data->title);
+ data->title = xstrndup(s, stringlen);
break;
case Stream_URL:
- g_free(data->stream_url);
- data->stream_url = g_strndup(s, stringlen);
+ free(data->stream_url);
+ data->stream_url = xstrndup(s, stringlen);
data->got_url = 1;
break;
default:
@@ -161,13 +151,7 @@ handle_string(void *ctx, const unsigned char* stringval,
}
static int
-handle_mapkey(void *ctx, const unsigned char* stringval,
-#ifdef HAVE_YAJL1
- unsigned int
-#else
- size_t
-#endif
- stringlen)
+handle_mapkey(void *ctx, const unsigned char *stringval, size_t stringlen)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -211,8 +195,8 @@ handle_end_map(void *ctx)
/* got_url == 1, track finished, make it into a song */
data->got_url = 0;
- char *u = g_strconcat(data->stream_url, "?client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
+ char *u = xstrcatdup(data->stream_url, "?client_id=",
+ soundcloud_config.apikey.c_str());
TagBuilder tag;
tag.SetDuration(SignedSongTime::FromMS(data->duration));
@@ -220,7 +204,7 @@ handle_end_map(void *ctx)
tag.AddItem(TAG_NAME, data->title);
data->songs.emplace_front(u, tag.Commit());
- g_free(u);
+ free(u);
return 1;
}
@@ -282,20 +266,11 @@ soundcloud_parse_json(const char *url, yajl_handle hand,
}
if (done) {
-#ifdef HAVE_YAJL1
- stat = yajl_parse_complete(hand);
-#else
stat = yajl_complete_parse(hand);
-#endif
} else
stat = yajl_parse(hand, ubuffer, nbytes);
- if (stat != yajl_status_ok
-#ifdef HAVE_YAJL1
- && stat != yajl_status_insufficient_data
-#endif
- )
- {
+ if (stat != yajl_status_ok) {
unsigned char *str = yajl_get_error(hand, 1, ubuffer, nbytes);
LogError(soundcloud_domain, (const char *)str);
yajl_free_error(hand, str);
@@ -325,24 +300,24 @@ soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond)
char *u = nullptr;
if (memcmp(uri, "track/", 6) == 0) {
const char *rest = uri + 6;
- u = g_strconcat("https://api.soundcloud.com/tracks/",
- rest, ".json?client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
+ u = xstrcatdup("https://api.soundcloud.com/tracks/",
+ rest, ".json?client_id=",
+ soundcloud_config.apikey.c_str());
} else if (memcmp(uri, "playlist/", 9) == 0) {
const char *rest = uri + 9;
- u = g_strconcat("https://api.soundcloud.com/playlists/",
- rest, ".json?client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
+ u = xstrcatdup("https://api.soundcloud.com/playlists/",
+ rest, ".json?client_id=",
+ soundcloud_config.apikey.c_str());
} else if (memcmp(uri, "user/", 5) == 0) {
const char *rest = uri + 5;
- u = g_strconcat("https://api.soundcloud.com/users/",
- rest, "/tracks.json?client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
+ u = xstrcatdup("https://api.soundcloud.com/users/",
+ rest, "/tracks.json?client_id=",
+ soundcloud_config.apikey.c_str());
} else if (memcmp(uri, "search/", 7) == 0) {
const char *rest = uri + 7;
- u = g_strconcat("https://api.soundcloud.com/tracks.json?q=",
- rest, "&client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
+ u = xstrcatdup("https://api.soundcloud.com/tracks.json?q=",
+ rest, "&client_id=",
+ soundcloud_config.apikey.c_str());
} else if (memcmp(uri, "url/", 4) == 0) {
const char *rest = uri + 4;
/* Translate to soundcloud resolver call. libcurl will automatically
@@ -359,19 +334,14 @@ soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond)
data.got_url = 0;
data.title = nullptr;
data.stream_url = nullptr;
-#ifdef HAVE_YAJL1
- yajl_handle hand = yajl_alloc(&parse_callbacks, nullptr, nullptr,
- &data);
-#else
yajl_handle hand = yajl_alloc(&parse_callbacks, nullptr, &data);
-#endif
int ret = soundcloud_parse_json(u, hand, mutex, cond);
- g_free(u);
+ free(u);
yajl_free(hand);
- g_free(data.title);
- g_free(data.stream_url);
+ free(data.title);
+ free(data.stream_url);
if (ret == -1)
return nullptr;
diff --git a/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx b/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx
index b355b477a..199d21e56 100644
--- a/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx
+++ b/src/playlist/plugins/SoundCloudPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx
index 5b6010b53..41fe12013 100644
--- a/src/playlist/plugins/XspfPlaylistPlugin.cxx
+++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
static constexpr Domain xspf_domain("xspf");
/**
- * This is the state object for the GLib XML parser.
+ * This is the state object for our XML parser.
*/
struct XspfParser {
/**
diff --git a/src/playlist/plugins/XspfPlaylistPlugin.hxx b/src/playlist/plugins/XspfPlaylistPlugin.hxx
index 6b08a6be6..0e95a1445 100644
--- a/src/playlist/plugins/XspfPlaylistPlugin.hxx
+++ b/src/playlist/plugins/XspfPlaylistPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/poison.h b/src/poison.h
index c112f6e19..96972cd2e 100644
--- a/src/poison.h
+++ b/src/poison.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/Ack.cxx b/src/protocol/Ack.cxx
index 56f0f0b5d..9e0c06614 100644
--- a/src/protocol/Ack.cxx
+++ b/src/protocol/Ack.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/Ack.hxx b/src/protocol/Ack.hxx
index e2c4dd9d1..c8457c5b4 100644
--- a/src/protocol/Ack.hxx
+++ b/src/protocol/Ack.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/ArgParser.cxx b/src/protocol/ArgParser.cxx
index e373827b4..b8837eeb4 100644
--- a/src/protocol/ArgParser.cxx
+++ b/src/protocol/ArgParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/ArgParser.hxx b/src/protocol/ArgParser.hxx
index 0f79e7ab2..7df71d30b 100644
--- a/src/protocol/ArgParser.hxx
+++ b/src/protocol/ArgParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/Result.cxx b/src/protocol/Result.cxx
index 3cc5fc33e..66ea185cb 100644
--- a/src/protocol/Result.cxx
+++ b/src/protocol/Result.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/protocol/Result.hxx b/src/protocol/Result.hxx
index 0ac9d1e6b..2ec861468 100644
--- a/src/protocol/Result.hxx
+++ b/src/protocol/Result.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/IdTable.hxx b/src/queue/IdTable.hxx
index 8e445243d..d1a0008fb 100644
--- a/src/queue/IdTable.hxx
+++ b/src/queue/IdTable.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/Playlist.cxx b/src/queue/Playlist.cxx
index b2fd673b4..1da89469c 100644
--- a/src/queue/Playlist.cxx
+++ b/src/queue/Playlist.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -44,45 +44,52 @@ playlist::TagModified(DetachedSong &&song)
idle_add(IDLE_PLAYLIST);
}
-/**
- * Queue a song, addressed by its order number.
- */
-static void
-playlist_queue_song_order(playlist &playlist, PlayerControl &pc,
- unsigned order)
+inline void
+playlist::QueueSongOrder(PlayerControl &pc, unsigned order)
+
{
- assert(playlist.queue.IsValidOrder(order));
+ assert(queue.IsValidOrder(order));
- playlist.queued = order;
+ queued = order;
- const DetachedSong &song = playlist.queue.GetOrder(order);
+ const DetachedSong &song = queue.GetOrder(order);
FormatDebug(playlist_domain, "queue song %i:\"%s\"",
- playlist.queued, song.GetURI());
+ queued, song.GetURI());
pc.EnqueueSong(new DetachedSong(song));
}
-/**
- * Called if the player thread has started playing the "queued" song.
- */
-static void
-playlist_song_started(playlist &playlist, PlayerControl &pc)
+void
+playlist::SongStarted()
+{
+ assert(current >= 0);
+
+ /* reset a song's "priority" when playback starts */
+ if (queue.SetPriority(queue.OrderToPosition(current), 0, -1, false))
+ OnModified();
+}
+
+inline void
+playlist::QueuedSongStarted(PlayerControl &pc)
{
assert(pc.next_song == nullptr);
- assert(playlist.queued >= -1);
+ assert(queued >= -1);
+ assert(current >= 0);
/* queued song has started: copy queued to current,
and notify the clients */
- int current = playlist.current;
- playlist.current = playlist.queued;
- playlist.queued = -1;
+ const int old_current = current;
+ current = queued;
+ queued = -1;
- if(playlist.queue.consume)
- playlist.DeleteOrder(pc, current);
+ if (queue.consume)
+ DeleteOrder(pc, old_current);
idle_add(IDLE_PLAYER);
+
+ SongStarted();
}
const DetachedSong *
@@ -139,7 +146,7 @@ playlist::UpdateQueuedSong(PlayerControl &pc, const DetachedSong *prev)
if (next_order >= 0) {
if (next_song != prev)
- playlist_queue_song_order(*this, pc, next_order);
+ QueueSongOrder(pc, next_order);
else
queued = next_order;
}
@@ -157,10 +164,9 @@ playlist::PlayOrder(PlayerControl &pc, int order)
pc.Play(new DetachedSong(song));
current = order;
-}
-static void
-playlist_resume_playback(playlist &playlist, PlayerControl &pc);
+ SongStarted();
+}
void
playlist::SyncWithPlayer(PlayerControl &pc)
@@ -180,12 +186,12 @@ playlist::SyncWithPlayer(PlayerControl &pc)
should be restarted with the next song. That can
happen if the playlist isn't filling the queue fast
enough */
- playlist_resume_playback(*this, pc);
+ ResumePlayback(pc);
else {
/* check if the player thread has already started
playing the queued song */
if (pc_next_song == nullptr && queued != -1)
- playlist_song_started(*this, pc);
+ QueuedSongStarted(pc);
pc.Lock();
pc_next_song = pc.next_song;
@@ -198,31 +204,27 @@ playlist::SyncWithPlayer(PlayerControl &pc)
}
}
-/**
- * The player has stopped for some reason. Check the error, and
- * decide whether to re-start playback
- */
-static void
-playlist_resume_playback(playlist &playlist, PlayerControl &pc)
+inline void
+playlist::ResumePlayback(PlayerControl &pc)
{
- assert(playlist.playing);
+ assert(playing);
assert(pc.GetState() == PlayerState::STOP);
const auto error = pc.GetErrorType();
if (error == PlayerError::NONE)
- playlist.error_count = 0;
+ error_count = 0;
else
- ++playlist.error_count;
+ ++error_count;
- if ((playlist.stop_on_error && error != PlayerError::NONE) ||
+ if ((stop_on_error && error != PlayerError::NONE) ||
error == PlayerError::OUTPUT ||
- playlist.error_count >= playlist.queue.GetLength())
+ error_count >= queue.GetLength())
/* too many errors, or critical error: stop
playback */
- playlist.Stop(pc);
+ Stop(pc);
else
/* continue playback at the next song */
- playlist.PlayNext(pc);
+ PlayNext(pc);
}
void
diff --git a/src/queue/Playlist.hxx b/src/queue/Playlist.hxx
index ea19d9bba..8e367d870 100644
--- a/src/queue/Playlist.hxx
+++ b/src/queue/Playlist.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -135,6 +135,17 @@ protected:
void OnModified();
/**
+ * Called when playback of a new song starts. Unlike
+ * QueuedSongStarted(), this also gets called when the user
+ * manually switches to another song. It may be used for
+ * playlist fixups.
+ *
+ * The song being started is specified by the #current
+ * attribute.
+ */
+ void SongStarted();
+
+ /**
* Updates the "queued song". Calculates the next song
* according to the current one (if MPD isn't playing, it
* takes the first song), and queues this song. Clears the
@@ -145,6 +156,24 @@ protected:
*/
void UpdateQueuedSong(PlayerControl &pc, const DetachedSong *prev);
+ /**
+ * Queue a song, addressed by its order number.
+ */
+ void QueueSongOrder(PlayerControl &pc, unsigned order);
+
+ /**
+ * Called when the player thread has started playing the
+ * "queued" song, i.e. it has switched from one song to the
+ * next automatically.
+ */
+ void QueuedSongStarted(PlayerControl &pc);
+
+ /**
+ * The player has stopped for some reason. Check the error,
+ * and decide whether to re-start playback.
+ */
+ void ResumePlayback(PlayerControl &pc);
+
public:
void BeginBulk();
void CommitBulk(PlayerControl &pc);
diff --git a/src/queue/PlaylistControl.cxx b/src/queue/PlaylistControl.cxx
index f7e80dc46..ed4a77e36 100644
--- a/src/queue/PlaylistControl.cxx
+++ b/src/queue/PlaylistControl.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/PlaylistEdit.cxx b/src/queue/PlaylistEdit.cxx
index 22a88dc46..c5aad092f 100644
--- a/src/queue/PlaylistEdit.cxx
+++ b/src/queue/PlaylistEdit.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/PlaylistState.cxx b/src/queue/PlaylistState.cxx
index 6ea86166e..56687b6d6 100644
--- a/src/queue/PlaylistState.cxx
+++ b/src/queue/PlaylistState.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,6 @@
#include "PlayerControl.hxx"
#include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx"
-#include "fs/Limits.hxx"
#include "util/CharUtil.hxx"
#include "util/StringUtil.hxx"
#include "Log.hxx"
@@ -57,8 +56,6 @@
#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause"
#define PLAYLIST_STATE_FILE_STATE_STOP "stop"
-#define PLAYLIST_BUFFER_SIZE 2*MPD_PATH_MAX
-
void
playlist_state_save(BufferedOutputStream &os, const struct playlist &playlist,
PlayerControl &pc)
@@ -195,7 +192,7 @@ playlist_state_restore(const char *line, TextFile &file,
current = 0;
if (state == PlayerState::PLAY &&
- config_get_bool(CONF_RESTORE_PAUSED, false))
+ config_get_bool(ConfigOption::RESTORE_PAUSED, false))
/* the user doesn't want MPD to auto-start
playback after startup; fall back to
"pause" */
diff --git a/src/queue/PlaylistState.hxx b/src/queue/PlaylistState.hxx
index 3211b1178..9af9ff1f9 100644
--- a/src/queue/PlaylistState.hxx
+++ b/src/queue/PlaylistState.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/PlaylistTag.cxx b/src/queue/PlaylistTag.cxx
index 556e7f4e9..69b6abae8 100644
--- a/src/queue/PlaylistTag.cxx
+++ b/src/queue/PlaylistTag.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/PlaylistUpdate.cxx b/src/queue/PlaylistUpdate.cxx
index 8876711ef..9fcd2f911 100644
--- a/src/queue/PlaylistUpdate.cxx
+++ b/src/queue/PlaylistUpdate.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/Queue.cxx b/src/queue/Queue.cxx
index 99b545ab1..72837e3f4 100644
--- a/src/queue/Queue.cxx
+++ b/src/queue/Queue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -402,7 +402,8 @@ Queue::CountSamePriority(unsigned start_order, uint8_t priority) const
}
bool
-Queue::SetPriority(unsigned position, uint8_t priority, int after_order)
+Queue::SetPriority(unsigned position, uint8_t priority, int after_order,
+ bool reorder)
{
assert(position < length);
@@ -414,7 +415,7 @@ Queue::SetPriority(unsigned position, uint8_t priority, int after_order)
item->version = version;
item->priority = priority;
- if (!random)
+ if (!random || !reorder)
/* don't reorder if not in random mode */
return true;
diff --git a/src/queue/Queue.hxx b/src/queue/Queue.hxx
index 016619e65..5a71f7d4c 100644
--- a/src/queue/Queue.hxx
+++ b/src/queue/Queue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -340,10 +340,13 @@ struct Queue {
/**
* Shuffles a (position) range in the queue. The songs are physically
* shuffled, not by using the "order" mapping.
+ *
+ * @param reorder false to suppress updating the order list
*/
void ShuffleRange(unsigned start, unsigned end);
- bool SetPriority(unsigned position, uint8_t priority, int after_order);
+ bool SetPriority(unsigned position, uint8_t priority, int after_order,
+ bool reorder=true);
bool SetPriorityRange(unsigned start_position, unsigned end_position,
uint8_t priority, int after_order);
diff --git a/src/queue/QueuePrint.cxx b/src/queue/QueuePrint.cxx
index 831ecafb9..c5bda5607 100644
--- a/src/queue/QueuePrint.cxx
+++ b/src/queue/QueuePrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/QueuePrint.hxx b/src/queue/QueuePrint.hxx
index 1aa876219..6589ee93e 100644
--- a/src/queue/QueuePrint.hxx
+++ b/src/queue/QueuePrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/QueueSave.cxx b/src/queue/QueueSave.cxx
index bc2702572..f5c49549e 100644
--- a/src/queue/QueueSave.cxx
+++ b/src/queue/QueueSave.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/queue/QueueSave.hxx b/src/queue/QueueSave.hxx
index 3fb4dc1a6..3eeacb418 100644
--- a/src/queue/QueueSave.hxx
+++ b/src/queue/QueueSave.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/sticker/Match.hxx b/src/sticker/Match.hxx
new file mode 100644
index 000000000..4ac2ac383
--- /dev/null
+++ b/src/sticker/Match.hxx
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_STICKER_MATCH_HXX
+#define MPD_STICKER_MATCH_HXX
+
+enum class StickerOperator {
+ /**
+ * Matches if a sticker with the specified name exists. The
+ * "value" parameter is ignored (must be nullptr).
+ */
+ EXISTS,
+
+ /**
+ * Matches if a sticker with the specified name and value
+ * exists.
+ */
+ EQUALS,
+
+ /**
+ * Matches if a sticker with the specified name exists with a
+ * value smaller than the specified one.
+ */
+ LESS_THAN,
+
+ /**
+ * Matches if a sticker with the specified name exists with a
+ * value bigger than the specified one.
+ */
+ GREATER_THAN,
+};
+
+#endif
diff --git a/src/sticker/SongSticker.cxx b/src/sticker/SongSticker.cxx
index b6f46f167..d6ade9800 100644
--- a/src/sticker/SongSticker.cxx
+++ b/src/sticker/SongSticker.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,46 +23,48 @@
#include "db/LightSong.hxx"
#include "db/Interface.hxx"
#include "util/Error.hxx"
-
-#include <glib.h>
+#include "util/Alloc.hxx"
#include <assert.h>
#include <string.h>
+#include <stdlib.h>
std::string
-sticker_song_get_value(const LightSong &song, const char *name)
+sticker_song_get_value(const LightSong &song, const char *name, Error &error)
{
const auto uri = song.GetURI();
- return sticker_load_value("song", uri.c_str(), name);
+ return sticker_load_value("song", uri.c_str(), name, error);
}
bool
sticker_song_set_value(const LightSong &song,
- const char *name, const char *value)
+ const char *name, const char *value,
+ Error &error)
{
const auto uri = song.GetURI();
- return sticker_store_value("song", uri.c_str(), name, value);
+ return sticker_store_value("song", uri.c_str(), name, value, error);
}
bool
-sticker_song_delete(const LightSong &song)
+sticker_song_delete(const LightSong &song, Error &error)
{
const auto uri = song.GetURI();
- return sticker_delete("song", uri.c_str());
+ return sticker_delete("song", uri.c_str(), error);
}
bool
-sticker_song_delete_value(const LightSong &song, const char *name)
+sticker_song_delete_value(const LightSong &song, const char *name,
+ Error &error)
{
const auto uri = song.GetURI();
- return sticker_delete_value("song", uri.c_str(), name);
+ return sticker_delete_value("song", uri.c_str(), name, error);
}
struct sticker *
-sticker_song_get(const LightSong &song)
+sticker_song_get(const LightSong &song, Error &error)
{
const auto uri = song.GetURI();
- return sticker_load("song", uri.c_str());
+ return sticker_load("song", uri.c_str(), error);
}
struct sticker_song_find_data {
@@ -95,9 +97,11 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
bool
sticker_song_find(const Database &db, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
void (*func)(const LightSong &song, const char *value,
void *user_data),
- void *user_data)
+ void *user_data,
+ Error &error)
{
struct sticker_song_find_data data;
data.db = &db;
@@ -109,16 +113,17 @@ sticker_song_find(const Database &db, const char *base_uri, const char *name,
if (*data.base_uri != 0)
/* append slash to base_uri */
data.base_uri = allocated =
- g_strconcat(data.base_uri, "/", nullptr);
+ xstrcatdup(data.base_uri, "/");
else
/* searching in root directory - no trailing slash */
allocated = nullptr;
data.base_uri_length = strlen(data.base_uri);
- bool success = sticker_find("song", data.base_uri, name,
- sticker_song_find_cb, &data);
- g_free(allocated);
+ bool success = sticker_find("song", data.base_uri, name, op, value,
+ sticker_song_find_cb, &data,
+ error);
+ free(allocated);
return success;
}
diff --git a/src/sticker/SongSticker.hxx b/src/sticker/SongSticker.hxx
index 5956cd6f9..e175160ab 100644
--- a/src/sticker/SongSticker.hxx
+++ b/src/sticker/SongSticker.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#ifndef MPD_SONG_STICKER_HXX
#define MPD_SONG_STICKER_HXX
+#include "Match.hxx"
#include "Compiler.h"
#include <string>
@@ -27,6 +28,7 @@
struct LightSong;
struct sticker;
class Database;
+class Error;
/**
* Returns one value from a song's sticker record. The caller must
@@ -34,7 +36,7 @@ class Database;
*/
gcc_pure
std::string
-sticker_song_get_value(const LightSong &song, const char *name);
+sticker_song_get_value(const LightSong &song, const char *name, Error &error);
/**
* Sets a sticker value in the specified song. Overwrites existing
@@ -42,20 +44,22 @@ sticker_song_get_value(const LightSong &song, const char *name);
*/
bool
sticker_song_set_value(const LightSong &song,
- const char *name, const char *value);
+ const char *name, const char *value,
+ Error &error);
/**
* Deletes a sticker from the database. All values are deleted.
*/
bool
-sticker_song_delete(const LightSong &song);
+sticker_song_delete(const LightSong &song, Error &error);
/**
* Deletes a sticker value. Does nothing if the sticker did not
* exist.
*/
bool
-sticker_song_delete_value(const LightSong &song, const char *name);
+sticker_song_delete_value(const LightSong &song, const char *name,
+ Error &error);
/**
* Loads the sticker for the specified song.
@@ -64,7 +68,7 @@ sticker_song_delete_value(const LightSong &song, const char *name);
* @return a sticker object, or NULL on error or if there is no sticker
*/
sticker *
-sticker_song_get(const LightSong &song);
+sticker_song_get(const LightSong &song, Error &error);
/**
* Finds stickers with the specified name below the specified
@@ -79,8 +83,10 @@ sticker_song_get(const LightSong &song);
*/
bool
sticker_song_find(const Database &db, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
void (*func)(const LightSong &song, const char *value,
void *user_data),
- void *user_data);
+ void *user_data,
+ Error &error);
#endif
diff --git a/src/sticker/StickerDatabase.cxx b/src/sticker/StickerDatabase.cxx
index 93eaa900d..09feb71c9 100644
--- a/src/sticker/StickerDatabase.cxx
+++ b/src/sticker/StickerDatabase.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,23 +19,18 @@
#include "config.h"
#include "StickerDatabase.hxx"
+#include "lib/sqlite/Domain.hxx"
+#include "lib/sqlite/Util.hxx"
#include "fs/Path.hxx"
#include "Idle.hxx"
#include "util/Error.hxx"
-#include "util/Domain.hxx"
#include "util/Macros.hxx"
-#include "Log.hxx"
#include <string>
#include <map>
-#include <sqlite3.h>
#include <assert.h>
-#if SQLITE_VERSION_NUMBER < 3003009
-#define sqlite3_prepare_v2 sqlite3_prepare
-#endif
-
struct sticker {
std::map<std::string, std::string> table;
};
@@ -48,6 +43,9 @@ enum sticker_sql {
STICKER_SQL_DELETE,
STICKER_SQL_DELETE_VALUE,
STICKER_SQL_FIND,
+ STICKER_SQL_FIND_VALUE,
+ STICKER_SQL_FIND_LT,
+ STICKER_SQL_FIND_GT,
};
static const char *const sticker_sql[] = {
@@ -65,6 +63,15 @@ static const char *const sticker_sql[] = {
"DELETE FROM sticker WHERE type=? AND uri=? AND name=?",
//[STICKER_SQL_FIND] =
"SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=?",
+
+ //[STICKER_SQL_FIND_VALUE] =
+ "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value=?",
+
+ //[STICKER_SQL_FIND_LT] =
+ "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value<?",
+
+ //[STICKER_SQL_FIND_GT] =
+ "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value>?",
};
static const char sticker_sql_create[] =
@@ -81,23 +88,13 @@ static const char sticker_sql_create[] =
static sqlite3 *sticker_db;
static sqlite3_stmt *sticker_stmt[ARRAY_SIZE(sticker_sql)];
-static constexpr Domain sticker_domain("sticker");
-
-static void
-LogError(sqlite3 *db, const char *msg)
-{
- FormatError(sticker_domain, "%s: %s", msg, sqlite3_errmsg(db));
-}
-
static sqlite3_stmt *
sticker_prepare(const char *sql, Error &error)
{
- int ret;
sqlite3_stmt *stmt;
-
- ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, nullptr);
+ int ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, nullptr);
if (ret != SQLITE_OK) {
- error.Format(sticker_domain, ret,
+ error.Format(sqlite_domain, ret,
"sqlite3_prepare_v2() failed: %s",
sqlite3_errmsg(sticker_db));
return nullptr;
@@ -118,9 +115,9 @@ sticker_global_init(Path path, Error &error)
ret = sqlite3_open(path.c_str(), &sticker_db);
if (ret != SQLITE_OK) {
const std::string utf8 = path.ToUTF8();
- error.Format(sticker_domain, ret,
- "Failed to open sqlite database '%s': %s",
- utf8.c_str(), sqlite3_errmsg(sticker_db));
+ error.Format(sqlite_domain, ret,
+ "Failed to open sqlite database '%s': %s",
+ utf8.c_str(), sqlite3_errmsg(sticker_db));
return false;
}
@@ -129,7 +126,7 @@ sticker_global_init(Path path, Error &error)
ret = sqlite3_exec(sticker_db, sticker_sql_create,
nullptr, nullptr, nullptr);
if (ret != SQLITE_OK) {
- error.Format(sticker_domain, ret,
+ error.Format(sqlite_domain, ret,
"Failed to create sticker table: %s",
sqlite3_errmsg(sticker_db));
return false;
@@ -149,7 +146,7 @@ sticker_global_init(Path path, Error &error)
}
void
-sticker_global_finish(void)
+sticker_global_finish()
{
if (sticker_db == nullptr)
/* not configured */
@@ -165,16 +162,16 @@ sticker_global_finish(void)
}
bool
-sticker_enabled(void)
+sticker_enabled()
{
return sticker_db != nullptr;
}
std::string
-sticker_load_value(const char *type, const char *uri, const char *name)
+sticker_load_value(const char *type, const char *uri, const char *name,
+ Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_GET];
- int ret;
assert(sticker_enabled());
assert(type != nullptr);
@@ -184,40 +181,12 @@ sticker_load_value(const char *type, const char *uri, const char *name)
if (*name == 0)
return std::string();
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return std::string();
- }
-
- ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return std::string();
- }
-
- ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, type, uri, name))
return std::string();
- }
-
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
std::string value;
- if (ret == SQLITE_ROW) {
- /* record found */
+ if (ExecuteRow(stmt, error))
value = (const char*)sqlite3_column_text(stmt, 0);
- } else if (ret == SQLITE_DONE) {
- /* no record found */
- } else {
- /* error */
- LogError(sticker_db, "sqlite3_step() failed");
- }
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
@@ -227,63 +196,36 @@ sticker_load_value(const char *type, const char *uri, const char *name)
static bool
sticker_list_values(std::map<std::string, std::string> &table,
- const char *type, const char *uri)
+ const char *type, const char *uri,
+ Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_LIST];
- int ret;
assert(type != nullptr);
assert(uri != nullptr);
assert(sticker_enabled());
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, type, uri))
return false;
- }
-
- ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- do {
- ret = sqlite3_step(stmt);
- switch (ret) {
- const char *name, *value;
-
- case SQLITE_ROW:
- name = (const char*)sqlite3_column_text(stmt, 0);
- value = (const char*)sqlite3_column_text(stmt, 1);
+ const bool success = ExecuteForEach(stmt, error, [stmt, &table](){
+ const char *name = (const char *)sqlite3_column_text(stmt, 0);
+ const char *value = (const char *)sqlite3_column_text(stmt, 1);
table.insert(std::make_pair(name, value));
- break;
- case SQLITE_DONE:
- break;
- case SQLITE_BUSY:
- /* no op */
- break;
- default:
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
- } while (ret != SQLITE_DONE);
+ });
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- return true;
+ return success;
}
static bool
sticker_update_value(const char *type, const char *uri,
- const char *name, const char *value)
+ const char *name, const char *value,
+ Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_UPDATE];
- int ret;
assert(type != nullptr);
assert(uri != nullptr);
@@ -293,56 +235,25 @@ sticker_update_value(const char *type, const char *uri,
assert(sticker_enabled());
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, value, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 2, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, value, type, uri, name))
return false;
- }
- ret = sqlite3_bind_text(stmt, 3, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 4, name, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
-
- ret = sqlite3_changes(sticker_db);
+ bool modified = ExecuteModified(stmt, error);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- idle_add(IDLE_STICKER);
- return ret > 0;
+ if (modified)
+ idle_add(IDLE_STICKER);
+ return modified;
}
static bool
sticker_insert_value(const char *type, const char *uri,
- const char *name, const char *value)
+ const char *name, const char *value,
+ Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_INSERT];
- int ret;
assert(type != nullptr);
assert(uri != nullptr);
@@ -352,52 +263,23 @@ sticker_insert_value(const char *type, const char *uri,
assert(sticker_enabled());
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 4, value, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, type, uri, name, value))
return false;
- }
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
+ bool success = ExecuteCommand(stmt, error);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
-
- idle_add(IDLE_STICKER);
- return true;
+ if (success)
+ idle_add(IDLE_STICKER);
+ return success;
}
bool
sticker_store_value(const char *type, const char *uri,
- const char *name, const char *value)
+ const char *name, const char *value,
+ Error &error)
{
assert(sticker_enabled());
assert(type != nullptr);
@@ -408,96 +290,53 @@ sticker_store_value(const char *type, const char *uri,
if (*name == 0)
return false;
- return sticker_update_value(type, uri, name, value) ||
- sticker_insert_value(type, uri, name, value);
+ return sticker_update_value(type, uri, name, value, error) ||
+ sticker_insert_value(type, uri, name, value, error);
}
bool
-sticker_delete(const char *type, const char *uri)
+sticker_delete(const char *type, const char *uri, Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE];
- int ret;
assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, type, uri))
return false;
- }
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
+ bool modified = ExecuteModified(stmt, error);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- idle_add(IDLE_STICKER);
- return true;
+ if (modified)
+ idle_add(IDLE_STICKER);
+ return modified;
}
bool
-sticker_delete_value(const char *type, const char *uri, const char *name)
+sticker_delete_value(const char *type, const char *uri, const char *name,
+ Error &error)
{
sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE_VALUE];
- int ret;
assert(sticker_enabled());
assert(type != nullptr);
assert(uri != nullptr);
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
-
- ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ if (!BindAll(error, stmt, type, uri, name))
return false;
- }
-
- ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
- do {
- ret = sqlite3_step(stmt);
- } while (ret == SQLITE_BUSY);
-
- if (ret != SQLITE_DONE) {
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
-
- ret = sqlite3_changes(sticker_db);
+ bool modified = ExecuteModified(stmt, error);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- idle_add(IDLE_STICKER);
- return ret > 0;
+ if (modified)
+ idle_add(IDLE_STICKER);
+ return modified;
}
void
@@ -527,11 +366,11 @@ sticker_foreach(const sticker &sticker,
}
struct sticker *
-sticker_load(const char *type, const char *uri)
+sticker_load(const char *type, const char *uri, Error &error)
{
sticker s;
- if (!sticker_list_values(s.table, type, uri))
+ if (!sticker_list_values(s.table, type, uri, error))
return nullptr;
if (s.table.empty())
@@ -541,64 +380,67 @@ sticker_load(const char *type, const char *uri)
return new sticker(std::move(s));
}
-bool
-sticker_find(const char *type, const char *base_uri, const char *name,
- void (*func)(const char *uri, const char *value,
- void *user_data),
- void *user_data)
+static sqlite3_stmt *
+BindFind(const char *type, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
+ Error &error)
{
- sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_FIND];
- int ret;
-
assert(type != nullptr);
assert(name != nullptr);
- assert(func != nullptr);
- assert(sticker_enabled());
-
- sqlite3_reset(stmt);
-
- ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
- }
if (base_uri == nullptr)
base_uri = "";
- ret = sqlite3_bind_text(stmt, 2, base_uri, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
- return false;
+ switch (op) {
+ case StickerOperator::EXISTS:
+ return BindAllOrNull(error, sticker_stmt[STICKER_SQL_FIND],
+ type, base_uri, name);
+
+ case StickerOperator::EQUALS:
+ return BindAllOrNull(error,
+ sticker_stmt[STICKER_SQL_FIND_VALUE],
+ type, base_uri, name, value);
+
+ case StickerOperator::LESS_THAN:
+ return BindAllOrNull(error,
+ sticker_stmt[STICKER_SQL_FIND_LT],
+ type, base_uri, name, value);
+
+ case StickerOperator::GREATER_THAN:
+ return BindAllOrNull(error,
+ sticker_stmt[STICKER_SQL_FIND_GT],
+ type, base_uri, name, value);
}
- ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr);
- if (ret != SQLITE_OK) {
- LogError(sticker_db, "sqlite3_bind_text() failed");
+ assert(false);
+ gcc_unreachable();
+}
+
+bool
+sticker_find(const char *type, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
+ void (*func)(const char *uri, const char *value,
+ void *user_data),
+ void *user_data,
+ Error &error)
+{
+ assert(func != nullptr);
+ assert(sticker_enabled());
+
+ sqlite3_stmt *const stmt = BindFind(type, base_uri, name, op, value,
+ error);
+ if (stmt == nullptr)
return false;
- }
- do {
- ret = sqlite3_step(stmt);
- switch (ret) {
- case SQLITE_ROW:
+ const bool success = ExecuteForEach(stmt, error,
+ [stmt, func, user_data](){
func((const char*)sqlite3_column_text(stmt, 0),
(const char*)sqlite3_column_text(stmt, 1),
user_data);
- break;
- case SQLITE_DONE:
- break;
- case SQLITE_BUSY:
- /* no op */
- break;
- default:
- LogError(sticker_db, "sqlite3_step() failed");
- return false;
- }
- } while (ret != SQLITE_DONE);
+ });
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
- return true;
+ return success;
}
diff --git a/src/sticker/StickerDatabase.hxx b/src/sticker/StickerDatabase.hxx
index 8993489c4..29314d024 100644
--- a/src/sticker/StickerDatabase.hxx
+++ b/src/sticker/StickerDatabase.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -42,6 +42,7 @@
#ifndef MPD_STICKER_DATABASE_HXX
#define MPD_STICKER_DATABASE_HXX
+#include "Match.hxx"
#include "Compiler.h"
#include <string>
@@ -62,21 +63,22 @@ sticker_global_init(Path path, Error &error);
* Close the sticker database.
*/
void
-sticker_global_finish(void);
+sticker_global_finish();
/**
* Returns true if the sticker database is configured and available.
*/
gcc_const
bool
-sticker_enabled(void);
+sticker_enabled();
/**
* Returns one value from an object's sticker record. Returns an
* empty string if the value doesn't exist.
*/
std::string
-sticker_load_value(const char *type, const char *uri, const char *name);
+sticker_load_value(const char *type, const char *uri, const char *name,
+ Error &error);
/**
* Sets a sticker value in the specified object. Overwrites existing
@@ -84,21 +86,24 @@ sticker_load_value(const char *type, const char *uri, const char *name);
*/
bool
sticker_store_value(const char *type, const char *uri,
- const char *name, const char *value);
+ const char *name, const char *value,
+ Error &error);
/**
* Deletes a sticker from the database. All sticker values of the
* specified object are deleted.
*/
bool
-sticker_delete(const char *type, const char *uri);
+sticker_delete(const char *type, const char *uri,
+ Error &error);
/**
* Deletes a sticker value. Fails if no sticker with this name
* exists.
*/
bool
-sticker_delete_value(const char *type, const char *uri, const char *name);
+sticker_delete_value(const char *type, const char *uri, const char *name,
+ Error &error);
/**
* Frees resources held by the sticker object.
@@ -140,7 +145,8 @@ sticker_foreach(const sticker &sticker,
* @return a sticker object, or nullptr on error or if there is no sticker
*/
sticker *
-sticker_load(const char *type, const char *uri);
+sticker_load(const char *type, const char *uri,
+ Error &error);
/**
* Finds stickers with the specified name below the specified URI.
@@ -149,13 +155,17 @@ sticker_load(const char *type, const char *uri);
* @param base_uri the URI prefix of the resources, or nullptr if all
* resources should be searched
* @param name the name of the sticker
+ * @param op the comparison operator
+ * @param value the operand
* @return true on success (even if no sticker was found), false on
* failure
*/
bool
sticker_find(const char *type, const char *base_uri, const char *name,
+ StickerOperator op, const char *value,
void (*func)(const char *uri, const char *value,
void *user_data),
- void *user_data);
+ void *user_data,
+ Error &error);
#endif
diff --git a/src/sticker/StickerPrint.cxx b/src/sticker/StickerPrint.cxx
index a952ff203..b5dde512e 100644
--- a/src/sticker/StickerPrint.cxx
+++ b/src/sticker/StickerPrint.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/sticker/StickerPrint.hxx b/src/sticker/StickerPrint.hxx
index 39f3dc09e..c927567a7 100644
--- a/src/sticker/StickerPrint.hxx
+++ b/src/sticker/StickerPrint.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/CompositeStorage.cxx b/src/storage/CompositeStorage.cxx
index 89a2fc756..94bbb6901 100644
--- a/src/storage/CompositeStorage.cxx
+++ b/src/storage/CompositeStorage.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -137,7 +137,7 @@ CompositeStorage::Directory::Make(const char *uri)
Directory *directory = this;
while (*uri != 0) {
const std::string name = NextSegment(uri);
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
auto i = directory->children.emplace(std::move(name),
Directory());
#else
diff --git a/src/storage/CompositeStorage.hxx b/src/storage/CompositeStorage.hxx
index c3695c79d..cf27a292c 100644
--- a/src/storage/CompositeStorage.hxx
+++ b/src/storage/CompositeStorage.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/Configured.cxx b/src/storage/Configured.cxx
index 41541673b..adb5c7dc5 100644
--- a/src/storage/Configured.cxx
+++ b/src/storage/Configured.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@ CreateConfiguredStorageUri(EventLoop &event_loop, const char *uri,
static AllocatedPath
GetConfiguredMusicDirectory(Error &error)
{
- AllocatedPath path = config_get_path(CONF_MUSIC_DIR, error);
+ AllocatedPath path = config_get_path(ConfigOption::MUSIC_DIR, error);
if (path.IsNull() && !error.IsDefined())
path = GetUserMusicDir();
@@ -68,7 +68,7 @@ CreateConfiguredStorage(EventLoop &event_loop, Error &error)
{
assert(!error.IsDefined());
- auto uri = config_get_string(CONF_MUSIC_DIR, nullptr);
+ auto uri = config_get_string(ConfigOption::MUSIC_DIR, nullptr);
if (uri != nullptr && uri_has_scheme(uri))
return CreateConfiguredStorageUri(event_loop, uri, error);
@@ -78,5 +78,5 @@ CreateConfiguredStorage(EventLoop &event_loop, Error &error)
bool
IsStorageConfigured()
{
- return config_get_string(CONF_MUSIC_DIR, nullptr) != nullptr;
+ return config_get_string(ConfigOption::MUSIC_DIR, nullptr) != nullptr;
}
diff --git a/src/storage/Configured.hxx b/src/storage/Configured.hxx
index 828a192c3..6769da5ff 100644
--- a/src/storage/Configured.hxx
+++ b/src/storage/Configured.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/FileInfo.hxx b/src/storage/FileInfo.hxx
index 8dd152c0a..d194bd9f5 100644
--- a/src/storage/FileInfo.hxx
+++ b/src/storage/FileInfo.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/MemoryDirectoryReader.cxx b/src/storage/MemoryDirectoryReader.cxx
index 160836b1a..c9563ea84 100644
--- a/src/storage/MemoryDirectoryReader.cxx
+++ b/src/storage/MemoryDirectoryReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/MemoryDirectoryReader.hxx b/src/storage/MemoryDirectoryReader.hxx
index 1345082cb..a4d2c1f92 100644
--- a/src/storage/MemoryDirectoryReader.hxx
+++ b/src/storage/MemoryDirectoryReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/Registry.cxx b/src/storage/Registry.cxx
index d8e273fd5..a59ec01aa 100644
--- a/src/storage/Registry.cxx
+++ b/src/storage/Registry.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/Registry.hxx b/src/storage/Registry.hxx
index cb3a78f11..8d7828865 100644
--- a/src/storage/Registry.hxx
+++ b/src/storage/Registry.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/StorageInterface.cxx b/src/storage/StorageInterface.cxx
index 93c50a8ac..79f0815d7 100644
--- a/src/storage/StorageInterface.cxx
+++ b/src/storage/StorageInterface.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/StorageInterface.hxx b/src/storage/StorageInterface.hxx
index 4484815bc..7e73dd34b 100644
--- a/src/storage/StorageInterface.hxx
+++ b/src/storage/StorageInterface.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/StoragePlugin.hxx b/src/storage/StoragePlugin.hxx
index 15f431105..962963d2f 100644
--- a/src/storage/StoragePlugin.hxx
+++ b/src/storage/StoragePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx
index b965ceea8..a8e33c788 100644
--- a/src/storage/plugins/LocalStorage.cxx
+++ b/src/storage/plugins/LocalStorage.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/LocalStorage.hxx b/src/storage/plugins/LocalStorage.hxx
index 7295d38e7..ea6bc357c 100644
--- a/src/storage/plugins/LocalStorage.hxx
+++ b/src/storage/plugins/LocalStorage.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index 324b40b6f..dc9826214 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/NfsStorage.hxx b/src/storage/plugins/NfsStorage.hxx
index f7e18effc..bc757cf8c 100644
--- a/src/storage/plugins/NfsStorage.hxx
+++ b/src/storage/plugins/NfsStorage.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/SmbclientStorage.cxx b/src/storage/plugins/SmbclientStorage.cxx
index 70a6e16bb..49c9952f2 100644
--- a/src/storage/plugins/SmbclientStorage.cxx
+++ b/src/storage/plugins/SmbclientStorage.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/storage/plugins/SmbclientStorage.hxx b/src/storage/plugins/SmbclientStorage.hxx
index 7c198d920..dd047f97e 100644
--- a/src/storage/plugins/SmbclientStorage.hxx
+++ b/src/storage/plugins/SmbclientStorage.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/Clock.cxx b/src/system/Clock.cxx
index 9baa0c0ca..38b24420d 100644
--- a/src/system/Clock.cxx
+++ b/src/system/Clock.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/Clock.hxx b/src/system/Clock.hxx
index 333a41000..7a710477e 100644
--- a/src/system/Clock.hxx
+++ b/src/system/Clock.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EPollFD.cxx b/src/system/EPollFD.cxx
index 43e74712f..08051cf06 100644
--- a/src/system/EPollFD.cxx
+++ b/src/system/EPollFD.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EPollFD.hxx b/src/system/EPollFD.hxx
index 8b9d7d2ba..d12561b5d 100644
--- a/src/system/EPollFD.hxx
+++ b/src/system/EPollFD.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EventFD.cxx b/src/system/EventFD.cxx
index 9ac4c1d94..2c1cef040 100644
--- a/src/system/EventFD.cxx
+++ b/src/system/EventFD.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EventFD.hxx b/src/system/EventFD.hxx
index 2a70461d9..654547078 100644
--- a/src/system/EventFD.hxx
+++ b/src/system/EventFD.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EventPipe.cxx b/src/system/EventPipe.cxx
index b8fc85aed..8b3141492 100644
--- a/src/system/EventPipe.cxx
+++ b/src/system/EventPipe.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/EventPipe.hxx b/src/system/EventPipe.hxx
index 42b3bb93d..229d5633e 100644
--- a/src/system/EventPipe.hxx
+++ b/src/system/EventPipe.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/FatalError.cxx b/src/system/FatalError.cxx
index 35e94f169..664b96a6c 100644
--- a/src/system/FatalError.cxx
+++ b/src/system/FatalError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,6 @@
#include "util/Domain.hxx"
#include "LogV.hxx"
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
-
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
@@ -78,18 +74,31 @@ FatalError(const char *msg, const Error &error)
FormatFatalError("%s: %s", msg, error.GetMessage());
}
+#ifdef WIN32
+
+void
+FatalSystemError(const char *msg, DWORD code)
+{
+ char buffer[256];
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, code, 0,
+ buffer, sizeof(buffer), nullptr);
+ FormatFatalError("%s: %s", msg, buffer);
+}
+
+#endif
+
void
FatalSystemError(const char *msg)
{
- const char *system_error;
#ifdef WIN32
- system_error = g_win32_error_message(GetLastError());
+ FatalSystemError(msg, GetLastError());
#else
- system_error = strerror(errno);
-#endif
-
+ const char *system_error = strerror(errno);
FormatError(fatal_error_domain, "%s: %s", msg, system_error);
Abort();
+#endif
}
void
diff --git a/src/system/FatalError.hxx b/src/system/FatalError.hxx
index d4698b3d9..89363feeb 100644
--- a/src/system/FatalError.hxx
+++ b/src/system/FatalError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,10 @@
#include "check.h"
#include "Compiler.h"
+#ifdef WIN32
+#include <windef.h>
+#endif
+
class Error;
/**
@@ -53,6 +57,14 @@ gcc_noreturn
void
FatalSystemError(const char *msg);
+#ifdef WIN32
+
+gcc_noreturn
+void
+FatalSystemError(const char *msg, DWORD code);
+
+#endif
+
gcc_noreturn
void
FormatFatalSystemError(const char *fmt, ...);
diff --git a/src/system/PeriodClock.hxx b/src/system/PeriodClock.hxx
index 1ba74ece2..c189577f5 100644
--- a/src/system/PeriodClock.hxx
+++ b/src/system/PeriodClock.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/Resolver.cxx b/src/system/Resolver.cxx
index a94217bac..389b3d4b5 100644
--- a/src/system/Resolver.cxx
+++ b/src/system/Resolver.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/Resolver.hxx b/src/system/Resolver.hxx
index 54922d98f..a9596c299 100644
--- a/src/system/Resolver.hxx
+++ b/src/system/Resolver.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SignalFD.cxx b/src/system/SignalFD.cxx
index 173a0cc8c..92d2eec01 100644
--- a/src/system/SignalFD.cxx
+++ b/src/system/SignalFD.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SignalFD.hxx b/src/system/SignalFD.hxx
index 11bf30f74..d376c6b59 100644
--- a/src/system/SignalFD.hxx
+++ b/src/system/SignalFD.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SocketError.cxx b/src/system/SocketError.cxx
index e138f4dd3..c4c9d7a2c 100644
--- a/src/system/SocketError.cxx
+++ b/src/system/SocketError.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SocketError.hxx b/src/system/SocketError.hxx
index 01abc9884..c9435d6fb 100644
--- a/src/system/SocketError.hxx
+++ b/src/system/SocketError.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SocketUtil.cxx b/src/system/SocketUtil.cxx
index b9df0d59d..26fc94bd4 100644
--- a/src/system/SocketUtil.cxx
+++ b/src/system/SocketUtil.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/SocketUtil.hxx b/src/system/SocketUtil.hxx
index 652788759..ad02ef481 100644
--- a/src/system/SocketUtil.hxx
+++ b/src/system/SocketUtil.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/system/fd_util.c b/src/system/fd_util.c
index b53ecda00..b6dd89674 100644
--- a/src/system/fd_util.c
+++ b/src/system/fd_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/system/fd_util.h b/src/system/fd_util.h
index f4a940e91..5b95cbc4f 100644
--- a/src/system/fd_util.h
+++ b/src/system/fd_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* Redistribution and use in source and binary forms, with or without
@@ -103,7 +103,7 @@ socketpair_cloexec_nonblock(int domain, int type, int protocol, int sv[2]);
#endif
-#ifdef HAVE_LIBMPDCLIENT
+#ifdef ENABLE_LIBMPDCLIENT
/* Avoid symbol conflict with statically linked libmpdclient */
#define socket_cloexec_nonblock socket_cloexec_nonblock_noconflict
#endif
diff --git a/src/tag/Aiff.cxx b/src/tag/Aiff.cxx
index c2498c9e9..7235b76a8 100644
--- a/src/tag/Aiff.cxx
+++ b/src/tag/Aiff.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Aiff.hxx b/src/tag/Aiff.hxx
index cd323ee2e..f9b11b5a6 100644
--- a/src/tag/Aiff.hxx
+++ b/src/tag/Aiff.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ApeLoader.cxx b/src/tag/ApeLoader.cxx
index f473c910e..786ecfe8f 100644
--- a/src/tag/ApeLoader.cxx
+++ b/src/tag/ApeLoader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ApeLoader.hxx b/src/tag/ApeLoader.hxx
index ce82cc35d..1bdfe692d 100644
--- a/src/tag/ApeLoader.hxx
+++ b/src/tag/ApeLoader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ApeReplayGain.cxx b/src/tag/ApeReplayGain.cxx
index 345f45710..139d44d1f 100644
--- a/src/tag/ApeReplayGain.cxx
+++ b/src/tag/ApeReplayGain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ApeReplayGain.hxx b/src/tag/ApeReplayGain.hxx
index 03c899c5c..faf68f0e3 100644
--- a/src/tag/ApeReplayGain.hxx
+++ b/src/tag/ApeReplayGain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ApeTag.cxx b/src/tag/ApeTag.cxx
index f714a1624..49ae7a036 100644
--- a/src/tag/ApeTag.cxx
+++ b/src/tag/ApeTag.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,6 @@
#include <string.h>
const struct tag_table ape_tags[] = {
- { "album artist", TAG_ALBUM_ARTIST },
{ "year", TAG_DATE },
{ nullptr, TAG_NUM_OF_ITEM_TYPES }
};
diff --git a/src/tag/ApeTag.hxx b/src/tag/ApeTag.hxx
index edebf076c..20d1d7b81 100644
--- a/src/tag/ApeTag.hxx
+++ b/src/tag/ApeTag.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Format.cxx b/src/tag/Format.cxx
new file mode 100644
index 000000000..de4db57ef
--- /dev/null
+++ b/src/tag/Format.cxx
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "config.h"
+#include "Format.hxx"
+#include "Tag.hxx"
+#include "util/format.h"
+#include "util/StringUtil.hxx"
+
+#include <algorithm>
+
+#include <string.h>
+#include <time.h>
+
+struct FormatTagContext {
+ const Tag &tag;
+
+ char buffer[256];
+
+ explicit FormatTagContext(const Tag &_tag):tag(_tag) {}
+};
+
+/**
+ * Is this a character unsafe to use in a path name segment?
+ */
+static constexpr bool
+IsUnsafeChar(char ch)
+{
+ return
+ /* disallow characters illegal in file names on
+ Windows (Linux allows almost anything) */
+ ch == '\\' || ch == '/' || ch == ':' || ch == '*' ||
+ ch == '?' || ch == '<' || ch == '>' || ch == '|' ||
+ /* allow space, but disallow all other whitespace */
+ (unsigned char)ch < 0x20;
+}
+
+gcc_pure
+static bool
+HasUnsafeChar(const char *s)
+{
+ for (; *s; ++s)
+ if (IsUnsafeChar(*s))
+ return true;
+
+ return false;
+}
+
+static const char *
+SanitizeString(const char *s, char *buffer, size_t buffer_size)
+{
+ /* skip leading dots to avoid generating "../" sequences */
+ while (*s == '.')
+ ++s;
+
+ if (!HasUnsafeChar(s))
+ return s;
+
+ char *end = CopyString(buffer, s, buffer_size);
+ std::replace_if(buffer, end, IsUnsafeChar, ' ');
+ return buffer;
+}
+
+gcc_pure gcc_nonnull_all
+static const char *
+TagGetter(const void *object, const char *name)
+{
+ const auto &_ctx = *(const FormatTagContext *)object;
+ auto &ctx = const_cast<FormatTagContext &>(_ctx);
+
+ if (strcmp(name, "iso8601") == 0) {
+ time_t t = time(nullptr);
+#ifdef WIN32
+ const struct tm *tm2 = gmtime(&t);
+#else
+ struct tm tm;
+ const struct tm *tm2 = gmtime_r(&t, &tm);
+#endif
+ if (tm2 == nullptr)
+ return "";
+
+ strftime(ctx.buffer, sizeof(ctx.buffer),
+#ifdef WIN32
+ /* kludge: use underscore instead of colon on
+ Windows because colons are not allowed in
+ file names, and this library is mostly
+ used to generate file names */
+ "%Y-%m-%dT%H_%M_%SZ",
+#else
+ "%FT%TZ",
+#endif
+ tm2);
+ return ctx.buffer;
+ }
+
+ const Tag &tag = ctx.tag;
+
+ TagType tag_type = tag_name_parse_i(name);
+ if (tag_type == TAG_NUM_OF_ITEM_TYPES)
+ /* unknown tag name */
+ return nullptr;
+
+ const char *value = tag.GetValue(tag_type);
+ if (value == nullptr)
+ /* known tag name, but not present in this object */
+ value = "";
+
+ // TODO: handle multiple tag values
+ return SanitizeString(value, ctx.buffer, sizeof(ctx.buffer));
+}
+
+char *
+FormatTag(const Tag &tag, const char *format)
+{
+ FormatTagContext ctx(tag);
+ return format_object(format, &ctx, TagGetter);
+}
diff --git a/src/tag/Format.hxx b/src/tag/Format.hxx
new file mode 100644
index 000000000..a08e687d0
--- /dev/null
+++ b/src/tag/Format.hxx
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_TAG_FORMAT_HXX
+#define MPD_TAG_FORMAT_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+struct Tag;
+
+gcc_malloc gcc_nonnull_all
+char *
+FormatTag(const Tag &tag, const char *format);
+
+#endif
diff --git a/src/tag/MixRamp.cxx b/src/tag/MixRamp.cxx
index e1b6e43c5..cbec047de 100644
--- a/src/tag/MixRamp.cxx
+++ b/src/tag/MixRamp.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/MixRamp.hxx b/src/tag/MixRamp.hxx
index 5b4e2dc30..7255bac4d 100644
--- a/src/tag/MixRamp.hxx
+++ b/src/tag/MixRamp.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ReplayGain.cxx b/src/tag/ReplayGain.cxx
index 83a48f243..edf8c92f1 100644
--- a/src/tag/ReplayGain.cxx
+++ b/src/tag/ReplayGain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/ReplayGain.hxx b/src/tag/ReplayGain.hxx
index 2bf5e0db1..a2e897235 100644
--- a/src/tag/ReplayGain.hxx
+++ b/src/tag/ReplayGain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Riff.cxx b/src/tag/Riff.cxx
index c630f082d..741225813 100644
--- a/src/tag/Riff.cxx
+++ b/src/tag/Riff.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Riff.hxx b/src/tag/Riff.hxx
index a9af67b7a..b15716882 100644
--- a/src/tag/Riff.hxx
+++ b/src/tag/Riff.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Set.cxx b/src/tag/Set.cxx
index 6a55a450f..22d1728ad 100644
--- a/src/tag/Set.cxx
+++ b/src/tag/Set.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -75,7 +75,7 @@ TagSet::InsertUnique(const Tag &src, TagType type, const char *value,
else
builder.AddItem(type, value);
CopyTagMask(builder, src, group_mask);
-#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
+#if CLANG_OR_GCC_VERSION(4,8)
emplace(builder.Commit());
#else
insert(builder.Commit());
diff --git a/src/tag/Set.hxx b/src/tag/Set.hxx
index b5acfcb36..aab994008 100644
--- a/src/tag/Set.hxx
+++ b/src/tag/Set.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Tag.cxx b/src/tag/Tag.cxx
index 92ac4214c..571e67fa8 100644
--- a/src/tag/Tag.cxx
+++ b/src/tag/Tag.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/Tag.hxx b/src/tag/Tag.hxx
index f1d3d5767..aca2bf6a0 100644
--- a/src/tag/Tag.hxx
+++ b/src/tag/Tag.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagBuilder.cxx b/src/tag/TagBuilder.cxx
index 93518f6e9..46024b44c 100644
--- a/src/tag/TagBuilder.cxx
+++ b/src/tag/TagBuilder.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagBuilder.hxx b/src/tag/TagBuilder.hxx
index aff581313..19186ab75 100644
--- a/src/tag/TagBuilder.hxx
+++ b/src/tag/TagBuilder.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagConfig.cxx b/src/tag/TagConfig.cxx
index 00f20d1c0..df40c2bc0 100644
--- a/src/tag/TagConfig.cxx
+++ b/src/tag/TagConfig.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -35,7 +35,8 @@
void
TagLoadConfig()
{
- const char *value = config_get_string(CONF_METADATA_TO_USE, nullptr);
+ const char *value = config_get_string(ConfigOption::METADATA_TO_USE,
+ nullptr);
if (value == nullptr)
return;
diff --git a/src/tag/TagConfig.hxx b/src/tag/TagConfig.hxx
index 0088e9757..05c6594c6 100644
--- a/src/tag/TagConfig.hxx
+++ b/src/tag/TagConfig.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagHandler.cxx b/src/tag/TagHandler.cxx
index 2cbb83242..9bbaae36a 100644
--- a/src/tag/TagHandler.cxx
+++ b/src/tag/TagHandler.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagHandler.hxx b/src/tag/TagHandler.hxx
index c12b605bc..e87c299fc 100644
--- a/src/tag/TagHandler.hxx
+++ b/src/tag/TagHandler.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagId3.cxx b/src/tag/TagId3.cxx
index 02dc58364..ade1fd007 100644
--- a/src/tag/TagId3.cxx
+++ b/src/tag/TagId3.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -66,12 +66,14 @@
static constexpr Domain id3_domain("id3");
+gcc_pure
static inline bool
tag_is_id3v1(struct id3_tag *tag)
{
return (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) != 0;
}
+gcc_pure
static id3_utf8_t *
tag_id3_getstring(const struct id3_frame *frame, unsigned i)
{
@@ -97,7 +99,8 @@ import_id3_string(bool is_id3v1, const id3_ucs4_t *ucs4)
/* use encoding field here? */
const char *encoding;
if (is_id3v1 &&
- (encoding = config_get_string(CONF_ID3V1_ENCODING, nullptr)) != nullptr) {
+ (encoding = config_get_string(ConfigOption::ID3V1_ENCODING,
+ nullptr)) != nullptr) {
id3_latin1_t *isostr = id3_ucs4_latin1duplicate(ucs4);
if (gcc_unlikely(isostr == nullptr))
return nullptr;
@@ -249,10 +252,11 @@ tag_id3_import_comment(struct id3_tag *tag, const char *id, TagType type,
* Parse a TXXX name, and convert it to a TagType enum value.
* Returns TAG_NUM_OF_ITEM_TYPES if the TXXX name is not understood.
*/
+gcc_pure
static TagType
tag_id3_parse_txxx_name(const char *name)
{
- static const struct tag_table txxx_tags[] = {
+ static constexpr struct tag_table txxx_tags[] = {
{ "ALBUMARTISTSORT", TAG_ALBUM_ARTIST_SORT },
{ "MusicBrainz Artist Id", TAG_MUSICBRAINZ_ARTISTID },
{ "MusicBrainz Album Id", TAG_MUSICBRAINZ_ALBUMID },
diff --git a/src/tag/TagId3.hxx b/src/tag/TagId3.hxx
index 1928d539d..94dfb1794 100644
--- a/src/tag/TagId3.hxx
+++ b/src/tag/TagId3.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,7 +29,7 @@ struct Tag;
struct id3_tag;
class Error;
-#ifdef HAVE_ID3TAG
+#ifdef ENABLE_ID3TAG
bool
tag_id3_scan(Path path_fs,
diff --git a/src/tag/TagItem.hxx b/src/tag/TagItem.hxx
index 489ecde3a..0aa52f700 100644
--- a/src/tag/TagItem.hxx
+++ b/src/tag/TagItem.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagNames.c b/src/tag/TagNames.c
index e051c5863..056d714e4 100644
--- a/src/tag/TagNames.c
+++ b/src/tag/TagNames.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagPool.cxx b/src/tag/TagPool.cxx
index 29f605337..0280948fd 100644
--- a/src/tag/TagPool.cxx
+++ b/src/tag/TagPool.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -87,7 +87,7 @@ calc_hash(TagType type, const char *p)
return hash ^ type;
}
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
constexpr
#endif
static inline TagPoolSlot *
diff --git a/src/tag/TagPool.hxx b/src/tag/TagPool.hxx
index 990ee87bd..7fba85b54 100644
--- a/src/tag/TagPool.hxx
+++ b/src/tag/TagPool.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagRva2.cxx b/src/tag/TagRva2.cxx
index bbb6d11e6..241deeb23 100644
--- a/src/tag/TagRva2.cxx
+++ b/src/tag/TagRva2.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagRva2.hxx b/src/tag/TagRva2.hxx
index df559f472..510dd043e 100644
--- a/src/tag/TagRva2.hxx
+++ b/src/tag/TagRva2.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagSettings.c b/src/tag/TagSettings.c
index e0c577c2b..4582bd3c0 100644
--- a/src/tag/TagSettings.c
+++ b/src/tag/TagSettings.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagSettings.h b/src/tag/TagSettings.h
index 33f89d4be..cf91b52e1 100644
--- a/src/tag/TagSettings.h
+++ b/src/tag/TagSettings.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagString.cxx b/src/tag/TagString.cxx
index 4f07cd62a..85227de24 100644
--- a/src/tag/TagString.cxx
+++ b/src/tag/TagString.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagString.hxx b/src/tag/TagString.hxx
index eccc2aa47..f4cba9a40 100644
--- a/src/tag/TagString.hxx
+++ b/src/tag/TagString.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagTable.cxx b/src/tag/TagTable.cxx
index c6e1cff54..e2a22b642 100644
--- a/src/tag/TagTable.cxx
+++ b/src/tag/TagTable.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagTable.hxx b/src/tag/TagTable.hxx
index 095b4cbff..0d72cba99 100644
--- a/src/tag/TagTable.hxx
+++ b/src/tag/TagTable.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/TagType.h b/src/tag/TagType.h
index 0aa6b4a51..6f68d53d0 100644
--- a/src/tag/TagType.h
+++ b/src/tag/TagType.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/VorbisComment.cxx b/src/tag/VorbisComment.cxx
index 2dfc058d8..2c45470d4 100644
--- a/src/tag/VorbisComment.cxx
+++ b/src/tag/VorbisComment.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/tag/VorbisComment.hxx b/src/tag/VorbisComment.hxx
index 1dd3371c8..e48e9b7a9 100644
--- a/src/tag/VorbisComment.hxx
+++ b/src/tag/VorbisComment.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/thread/Id.hxx b/src/thread/Id.hxx
index 11be0a56b..60006e31a 100644
--- a/src/thread/Id.hxx
+++ b/src/thread/Id.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/thread/Name.hxx b/src/thread/Name.hxx
index a99208dab..999cebf73 100644
--- a/src/thread/Name.hxx
+++ b/src/thread/Name.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/thread/Slack.hxx b/src/thread/Slack.hxx
index 66b2254a4..3f9c71d52 100644
--- a/src/thread/Slack.hxx
+++ b/src/thread/Slack.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/thread/Thread.cxx b/src/thread/Thread.cxx
index 2932d478f..78675d84e 100644
--- a/src/thread/Thread.cxx
+++ b/src/thread/Thread.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/thread/Thread.hxx b/src/thread/Thread.hxx
index 976ff5625..668f5e9f7 100644
--- a/src/thread/Thread.hxx
+++ b/src/thread/Thread.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/unix/Daemon.cxx b/src/unix/Daemon.cxx
index 490b2def5..3787244d7 100644
--- a/src/unix/Daemon.cxx
+++ b/src/unix/Daemon.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/unix/Daemon.hxx b/src/unix/Daemon.hxx
index fe5681511..40db4e8d7 100644
--- a/src/unix/Daemon.hxx
+++ b/src/unix/Daemon.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/unix/PidFile.hxx b/src/unix/PidFile.hxx
index a242c7810..fab63a563 100644
--- a/src/unix/PidFile.hxx
+++ b/src/unix/PidFile.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/unix/SignalHandlers.cxx b/src/unix/SignalHandlers.cxx
index 4aef4fa71..47085b4fd 100644
--- a/src/unix/SignalHandlers.cxx
+++ b/src/unix/SignalHandlers.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/unix/SignalHandlers.hxx b/src/unix/SignalHandlers.hxx
index 551b373c1..573db7511 100644
--- a/src/unix/SignalHandlers.hxx
+++ b/src/unix/SignalHandlers.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/Alloc.cxx b/src/util/Alloc.cxx
index 006e09701..c2676ca3d 100644
--- a/src/util/Alloc.cxx
+++ b/src/util/Alloc.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -75,3 +75,87 @@ xstrndup(const char *s, size_t n)
return p;
}
+
+#if CLANG_OR_GCC_VERSION(4,7)
+
+template<typename... Args>
+static inline size_t
+FillLengths(size_t *lengths, const char *a, Args&&... args)
+{
+ return FillLengths(lengths, a) + FillLengths(lengths + 1, args...);
+}
+
+template<>
+inline size_t
+FillLengths(size_t *lengths, const char *a)
+{
+ return *lengths = strlen(a);
+}
+
+template<typename... Args>
+static inline void
+StringCat(char *p, const size_t *lengths, const char *a, Args&&... args)
+{
+ StringCat(p, lengths, a);
+ StringCat(p + *lengths, lengths + 1, args...);
+}
+
+template<>
+inline void
+StringCat(char *p, const size_t *lengths, const char *a)
+{
+ memcpy(p, a, *lengths);
+}
+
+#endif
+
+template<typename... Args>
+gcc_malloc gcc_nonnull_all
+static inline char *
+t_xstrcatdup(Args&&... args)
+{
+#if CLANG_OR_GCC_VERSION(4,7)
+ constexpr size_t n = sizeof...(args);
+
+ size_t lengths[n];
+ const size_t total = FillLengths(lengths, args...);
+
+ char *p = (char *)xalloc(total + 1);
+ StringCat(p, lengths, args...);
+ p[total] = 0;
+ return p;
+#else
+ /* fallback implementation for gcc 4.6, because that old
+ compiler is too buggy to compile the above template
+ functions */
+ const char *const argv[] = { args... };
+
+ size_t total = 0;
+ for (auto i : argv)
+ total += strlen(i);
+
+ char *p = (char *)xalloc(total + 1), *q = p;
+ for (auto i : argv)
+ q = stpcpy(q, i);
+
+ return p;
+#endif
+}
+
+char *
+xstrcatdup(const char *a, const char *b)
+{
+ return t_xstrcatdup(a, b);
+}
+
+char *
+xstrcatdup(const char *a, const char *b, const char *c)
+{
+ return t_xstrcatdup(a, b, c);
+}
+
+char *
+xstrcatdup(const char *a, const char *b, const char *c, const char *d)
+{
+ return t_xstrcatdup(a, b, c, d);
+}
diff --git a/src/util/Alloc.hxx b/src/util/Alloc.hxx
index 15c123b7a..9e1007e69 100644
--- a/src/util/Alloc.hxx
+++ b/src/util/Alloc.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -64,4 +64,23 @@ gcc_malloc gcc_nonnull_all
char *
xstrndup(const char *s, size_t n);
+/**
+ * Concatenate two strings, returning a new allocation. Use free() to
+ * free it.
+ *
+ * This function never fails; in out-of-memory situations, it aborts
+ * the process.
+ */
+gcc_malloc gcc_nonnull_all
+char *
+xstrcatdup(const char *a, const char *b);
+
+gcc_malloc gcc_nonnull_all
+char *
+xstrcatdup(const char *a, const char *b, const char *c);
+
+gcc_malloc gcc_nonnull_all
+char *
+xstrcatdup(const char *a, const char *b, const char *c, const char *d);
+
#endif
diff --git a/src/util/ByteReverse.cxx b/src/util/ByteReverse.cxx
index 5cc8692a7..c0c2946ca 100644
--- a/src/util/ByteReverse.cxx
+++ b/src/util/ByteReverse.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/ByteReverse.hxx b/src/util/ByteReverse.hxx
index 0c060c0cb..55d6a64db 100644
--- a/src/util/ByteReverse.hxx
+++ b/src/util/ByteReverse.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/Cast.hxx b/src/util/Cast.hxx
index 887137da4..647171970 100644
--- a/src/util/Cast.hxx
+++ b/src/util/Cast.hxx
@@ -84,7 +84,7 @@ ContainerAttributeOffset(const A C::*p)
* Cast the given pointer to a struct member to its parent structure.
*/
template<class C, class A>
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
constexpr
#endif
static inline C &
@@ -97,7 +97,7 @@ ContainerCast(A &a, A C::*member)
* Cast the given pointer to a struct member to its parent structure.
*/
template<class C, class A>
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
constexpr
#endif
static inline const C &
diff --git a/src/util/CharUtil.hxx b/src/util/CharUtil.hxx
index 84a88a94e..efd40896a 100644
--- a/src/util/CharUtil.hxx
+++ b/src/util/CharUtil.hxx
@@ -128,7 +128,7 @@ ToUpperASCII(char ch)
/**
* Convert the specified ASCII character (0x00..0x7f) to lower case.
- * Unlike toupper(), it ignores the system locale.
+ * Unlike tolower(), it ignores the system locale.
*/
constexpr
static inline char
diff --git a/src/util/DivideString.cxx b/src/util/DivideString.cxx
new file mode 100644
index 000000000..8e3d5a1b8
--- /dev/null
+++ b/src/util/DivideString.cxx
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "DivideString.hxx"
+#include "StringUtil.hxx"
+
+#include <string.h>
+
+DivideString::DivideString(const char *s, char separator, bool strip)
+ :first(nullptr)
+{
+ const char *x = strchr(s, separator);
+ if (x == nullptr)
+ return;
+
+ size_t length = x - s;
+ second = x + 1;
+
+ if (strip)
+ second = StripLeft(second);
+
+ if (strip) {
+ const char *end = s + length;
+ s = StripLeft(s);
+ end = StripRight(s, end);
+ length = end - s;
+ }
+
+ first = new char[length + 1];
+ memcpy(first, s, length);
+ first[length] = 0;
+}
diff --git a/src/util/DivideString.hxx b/src/util/DivideString.hxx
new file mode 100644
index 000000000..d98b512a6
--- /dev/null
+++ b/src/util/DivideString.hxx
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2003-2015 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 MPD_DIVIDE_STRING_HXX
+#define MPD_DIVIDE_STRING_HXX
+
+#include "Compiler.h"
+
+#include <assert.h>
+
+/**
+ * Split a given constant string at a separator character. Duplicates
+ * the first part to be able to null-terminate it.
+ */
+class DivideString {
+ char *first;
+ const char *second;
+
+public:
+ /**
+ * @param strip strip the first part and left-strip the second
+ * part?
+ */
+ DivideString(const char *s, char separator, bool strip=false);
+
+ ~DivideString() {
+ delete[] first;
+ }
+
+ /**
+ * Was the separator found?
+ */
+ bool IsDefined() const {
+ return first != nullptr;
+ }
+
+ /**
+ * Is the first part empty?
+ */
+ bool IsEmpty() const {
+ assert(IsDefined());
+
+ return *first == 0;
+ }
+
+ const char *GetFirst() const {
+ assert(IsDefined());
+
+ return first;
+ }
+
+ const char *GetSecond() const {
+ assert(IsDefined());
+
+ return second;
+ }
+};
+
+#endif
diff --git a/src/util/Error.cxx b/src/util/Error.cxx
index 92b2cc5d0..67a1b03fd 100644
--- a/src/util/Error.cxx
+++ b/src/util/Error.cxx
@@ -32,7 +32,7 @@
#include "Domain.hxx"
#ifdef WIN32
-#include <glib.h>
+#include <windows.h>
#endif
#include <errno.h>
@@ -135,7 +135,11 @@ Error::FormatErrno(const char *fmt, ...)
void
Error::SetLastError(DWORD _code, const char *prefix)
{
- const char *msg = g_win32_error_message(_code);
+ char msg[256];
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, _code, 0, msg, sizeof(msg), nullptr);
+
Format(win32_domain, int(_code), "%s: %s", prefix, msg);
}
diff --git a/src/util/FormatString.cxx b/src/util/FormatString.cxx
index d222a505c..5ada067cb 100644
--- a/src/util/FormatString.cxx
+++ b/src/util/FormatString.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/FormatString.hxx b/src/util/FormatString.hxx
index dc1ac3c67..b0f8dd7f9 100644
--- a/src/util/FormatString.hxx
+++ b/src/util/FormatString.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/LazyRandomEngine.cxx b/src/util/LazyRandomEngine.cxx
index b0aac913c..abd83da8c 100644
--- a/src/util/LazyRandomEngine.cxx
+++ b/src/util/LazyRandomEngine.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/LazyRandomEngine.hxx b/src/util/LazyRandomEngine.hxx
index 4156b3bb1..7b9b1c655 100644
--- a/src/util/LazyRandomEngine.hxx
+++ b/src/util/LazyRandomEngine.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/Manual.hxx b/src/util/Manual.hxx
index 75cffac06..6ba932bdd 100644
--- a/src/util/Manual.hxx
+++ b/src/util/Manual.hxx
@@ -41,7 +41,7 @@
#include <assert.h>
-#if defined(__clang__) || GCC_CHECK_VERSION(4,7)
+#if CLANG_OR_GCC_VERSION(4,7)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
@@ -54,12 +54,7 @@
*/
template<class T>
class Manual {
-#if GCC_OLDER_THAN(4,8)
- /* no alignas() on gcc < 4.8: apply worst-case fallback */
- __attribute__((aligned(8)))
-#else
- alignas(T)
-#endif
+ gcc_alignas(T, 8)
char data[sizeof(T)];
#ifndef NDEBUG
@@ -89,32 +84,46 @@ public:
void Destruct() {
assert(initialized);
- T *t = (T *)data;
- t->T::~T();
+ T &t = Get();
+ t.T::~T();
#ifndef NDEBUG
initialized = false;
#endif
}
+ T &Get() {
+ assert(initialized);
+
+ void *p = static_cast<void *>(data);
+ return *static_cast<T *>(p);
+ }
+
+ const T &Get() const {
+ assert(initialized);
+
+ const void *p = static_cast<const void *>(data);
+ return *static_cast<const T *>(p);
+ }
+
operator T &() {
- return *(T *)data;
+ return Get();
}
operator const T &() const {
- return *(const T *)data;
+ return Get();
}
T *operator->() {
- return (T *)data;
+ return &Get();
}
const T *operator->() const {
- return (T *)data;
+ return &Get();
}
};
-#if defined(__clang__) || GCC_VERSION >= 40700
+#if CLANG_OR_GCC_VERSION(4,7)
#pragma GCC diagnostic pop
#endif
diff --git a/src/util/OptionDef.hxx b/src/util/OptionDef.hxx
index dd82154c4..29b7e268b 100644
--- a/src/util/OptionDef.hxx
+++ b/src/util/OptionDef.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/OptionParser.cxx b/src/util/OptionParser.cxx
index b10008527..45be084c9 100644
--- a/src/util/OptionParser.cxx
+++ b/src/util/OptionParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/OptionParser.hxx b/src/util/OptionParser.hxx
index b9d34adbb..c6c794a7d 100644
--- a/src/util/OptionParser.hxx
+++ b/src/util/OptionParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/PeakBuffer.cxx b/src/util/PeakBuffer.cxx
index e4624bbec..da3b275d8 100644
--- a/src/util/PeakBuffer.cxx
+++ b/src/util/PeakBuffer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/PeakBuffer.hxx b/src/util/PeakBuffer.hxx
index 702a3dee0..784b3cdbd 100644
--- a/src/util/PeakBuffer.hxx
+++ b/src/util/PeakBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/RefCount.hxx b/src/util/RefCount.hxx
index 02ef8818c..c6cf2e41f 100644
--- a/src/util/RefCount.hxx
+++ b/src/util/RefCount.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* Redistribution and use in source and binary forms, with or without
diff --git a/src/util/SliceBuffer.hxx b/src/util/SliceBuffer.hxx
index 63ca087ae..16c1cf744 100644
--- a/src/util/SliceBuffer.hxx
+++ b/src/util/SliceBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/SplitString.cxx b/src/util/SplitString.cxx
index 75e799279..9588312f8 100644
--- a/src/util/SplitString.cxx
+++ b/src/util/SplitString.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,20 +18,42 @@
*/
#include "SplitString.hxx"
+#include "StringUtil.hxx"
#include <string.h>
-SplitString::SplitString(const char *s, char separator)
- :first(nullptr)
+std::forward_list<std::string>
+SplitString(const char *s, char separator, bool strip)
{
- const char *x = strchr(s, separator);
- if (x == nullptr)
- return;
+ if (strip)
+ s = StripLeft(s);
- size_t length = x - s;
- second = x + 1;
+ std::forward_list<std::string> list;
+ if (*s == 0)
+ return list;
- first = new char[length + 1];
- memcpy(first, s, length);
- first[length] = 0;
+ auto i = list.before_begin();
+
+ while (true) {
+ const char *next = strchr(s, separator);
+ if (next == nullptr)
+ break;
+
+ const char *end = next++;
+ if (strip)
+ end = StripRight(s, end);
+
+ i = list.emplace_after(i, s, end);
+
+ s = next;
+ if (strip)
+ s = StripLeft(s);
+ }
+
+ const char *end = s + strlen(s);
+ if (strip)
+ end = StripRight(s, end);
+
+ list.emplace_after(i, s, end);
+ return list;
}
diff --git a/src/util/SplitString.hxx b/src/util/SplitString.hxx
index 96ffb21ec..545470c7a 100644
--- a/src/util/SplitString.hxx
+++ b/src/util/SplitString.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,52 +20,20 @@
#ifndef MPD_SPLIT_STRING_HXX
#define MPD_SPLIT_STRING_HXX
-#include "Compiler.h"
-
-#include <assert.h>
+#include <forward_list>
+#include <string>
/**
- * Split a given constant string at a separator character. Duplicates
- * the first part to be able to null-terminate it.
+ * Split a string at a certain separator character into sub strings
+ * and returns a list of these.
+ *
+ * Two consecutive separator characters result in an empty string in
+ * the list.
+ *
+ * An empty input string, as a special case, results in an empty list
+ * (and not a list with an empty string).
*/
-class SplitString {
- char *first;
- const char *second;
-
-public:
- SplitString(const char *s, char separator);
-
- ~SplitString() {
- delete[] first;
- }
-
- /**
- * Was the separator found?
- */
- bool IsDefined() const {
- return first != nullptr;
- }
-
- /**
- * Is the first part empty?
- */
- bool IsEmpty() const {
- assert(IsDefined());
-
- return *first == 0;
- }
-
- const char *GetFirst() const {
- assert(IsDefined());
-
- return first;
- }
-
- const char *GetSecond() const {
- assert(IsDefined());
-
- return second;
- }
-};
+std::forward_list<std::string>
+SplitString(const char *s, char separator, bool strip=true);
#endif
diff --git a/src/util/StringUtil.cxx b/src/util/StringUtil.cxx
index bcade2b3b..60734ad8d 100644
--- a/src/util/StringUtil.cxx
+++ b/src/util/StringUtil.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -120,3 +120,23 @@ string_array_contains(const char *const* haystack, const char *needle)
return false;
}
+
+void
+ToUpperASCII(char *dest, const char *src, size_t size)
+{
+ assert(dest != nullptr);
+ assert(src != nullptr);
+ assert(size > 1);
+
+ char *const end = dest + size - 1;
+
+ do {
+ char ch = *src++;
+ if (ch == 0)
+ break;
+
+ *dest++ = ToUpperASCII(ch);
+ } while (dest < end);
+
+ *dest = 0;
+}
diff --git a/src/util/StringUtil.hxx b/src/util/StringUtil.hxx
index 9beda5441..9f2dab935 100644
--- a/src/util/StringUtil.hxx
+++ b/src/util/StringUtil.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -114,4 +114,12 @@ gcc_pure
bool
string_array_contains(const char *const* haystack, const char *needle);
+/**
+ * Convert the specified ASCII string (0x00..0x7f) to upper case.
+ *
+ * @param size the destination buffer size
+ */
+void
+ToUpperASCII(char *dest, const char *src, size_t size);
+
#endif
diff --git a/src/util/UriUtil.cxx b/src/util/UriUtil.cxx
index 54d0ded77..0782304e3 100644
--- a/src/util/UriUtil.cxx
+++ b/src/util/UriUtil.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/UriUtil.hxx b/src/util/UriUtil.hxx
index d478d5b92..e8edfb5a0 100644
--- a/src/util/UriUtil.hxx
+++ b/src/util/UriUtil.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/bit_reverse.c b/src/util/bit_reverse.c
index 9226c4261..271eee166 100644
--- a/src/util/bit_reverse.c
+++ b/src/util/bit_reverse.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/bit_reverse.h b/src/util/bit_reverse.h
index b39b02e92..f4d378e61 100644
--- a/src/util/bit_reverse.h
+++ b/src/util/bit_reverse.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/util/format.c b/src/util/format.c
new file mode 100644
index 000000000..66243c8ec
--- /dev/null
+++ b/src/util/format.c
@@ -0,0 +1,259 @@
+/*
+ * music player command (mpc)
+ * Copyright (C) 2003-2015 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.
+ */
+
+#include "format.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/**
+ * Reallocate the given string and append the source string.
+ */
+gcc_malloc
+static char *
+string_append(char *dest, const char *src, size_t len)
+{
+ size_t destlen = dest != NULL
+ ? strlen(dest)
+ : 0;
+
+ dest = realloc(dest, destlen + len + 1);
+ memcpy(dest + destlen, src, len);
+ dest[destlen + len] = '\0';
+
+ return dest;
+}
+
+/**
+ * Skip the format string until the current group is closed by either
+ * '&', '|' or ']' (supports nesting).
+ */
+gcc_pure
+static const char *
+skip_format(const char *p)
+{
+ unsigned stack = 0;
+
+ while (*p != '\0') {
+ if (*p == '[')
+ stack++;
+ else if (*p == '#' && p[1] != '\0')
+ /* skip escaped stuff */
+ ++p;
+ else if (stack > 0) {
+ if (*p == ']')
+ --stack;
+ } else if (*p == '&' || *p == '|' || *p == ']')
+ break;
+
+ ++p;
+ }
+
+ return p;
+}
+
+static bool
+is_name_char(char ch)
+{
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') || ch == '_';
+}
+
+static char *
+format_object2(const char *format, const char **last, const void *object,
+ const char *(*getter)(const void *object, const char *name))
+{
+ char *ret = NULL;
+ const char *p;
+ bool found = false;
+
+ for (p = format; *p != '\0';) {
+ switch (p[0]) {
+ case '|':
+ ++p;
+ if (!found) {
+ /* nothing found yet: try the next
+ section */
+ free(ret);
+ ret = NULL;
+ } else
+ /* already found a value: skip the
+ next section */
+ p = skip_format(p);
+ break;
+
+ case '&':
+ ++p;
+ if (!found)
+ /* nothing found yet, so skip this
+ section */
+ p = skip_format(p);
+ else
+ /* we found something yet, but it will
+ only be used if the next section
+ also found something, so reset the
+ flag */
+ found = false;
+ break;
+
+ case '[': {
+ char *t = format_object2(p + 1, &p, object, getter);
+ if (t != NULL) {
+ ret = string_append(ret, t, strlen(t));
+ free(t);
+ found = true;
+ }
+ }
+ break;
+
+ case ']':
+ if (last != NULL)
+ *last = p + 1;
+ if (!found) {
+ free(ret);
+ ret = NULL;
+ }
+ return ret;
+
+ case '\\': {
+ /* take care of escape sequences */
+ char ltemp;
+ switch (p[1]) {
+ case 'a':
+ ltemp = '\a';
+ break;
+
+ case 'b':
+ ltemp = '\b';
+ break;
+
+ case 't':
+ ltemp = '\t';
+ break;
+
+ case 'n':
+ ltemp = '\n';
+ break;
+
+ case 'v':
+ ltemp = '\v';
+ break;
+
+ case 'f':
+ ltemp = '\f';
+ break;
+
+ case 'r':
+ ltemp = '\r';
+ break;
+
+ case '[':
+ case ']':
+ ltemp = p[1];
+ break;
+
+ default:
+ /* unknown escape: copy the
+ backslash */
+ ltemp = p[0];
+ --p;
+ break;
+ }
+
+ ret = string_append(ret, &ltemp, 1);
+ p += 2;
+ }
+ break;
+
+ case '%': {
+ /* find the extent of this format specifier
+ (stop at \0, ' ', or esc) */
+ const char *end = p + 1;
+ while (is_name_char(*end))
+ ++end;
+
+ const size_t length = end - p + 1;
+
+ if (*end != '%') {
+ ret = string_append(ret, p, length - 1);
+ p = end;
+ continue;
+ }
+
+ char name[32];
+ if (length > (int)sizeof(name)) {
+ ret = string_append(ret, p, length);
+ p = end + 1;
+ continue;
+ }
+
+ memcpy(name, p + 1, length - 2);
+ name[length - 2] = 0;
+
+ const char *value = getter(object, name);
+ size_t value_length;
+ if (value != NULL) {
+ if (*value != 0)
+ found = true;
+ value_length = strlen(value);
+ } else {
+ /* unknown variable: copy verbatim
+ from format string */
+ value = p;
+ value_length = length;
+ }
+
+ ret = string_append(ret, value, value_length);
+
+ /* advance past the specifier */
+ p = end + 1;
+ }
+ break;
+
+ case '#':
+ /* let the escape character escape itself */
+ if (p[1] != '\0') {
+ ret = string_append(ret, p + 1, 1);
+ p += 2;
+ break;
+ }
+
+ /* fall through */
+
+ default:
+ /* pass-through non-escaped portions of the format string */
+ ret = string_append(ret, p, 1);
+ ++p;
+ }
+ }
+
+ if (last != NULL)
+ *last = p;
+ return ret;
+}
+
+char *
+format_object(const char *format, const void *object,
+ const char *(*getter)(const void *object, const char *name))
+{
+ return format_object2(format, NULL, object, getter);
+}
diff --git a/src/util/format.h b/src/util/format.h
new file mode 100644
index 000000000..fa3624b51
--- /dev/null
+++ b/src/util/format.h
@@ -0,0 +1,51 @@
+/*
+ * music player command (mpc)
+ * Copyright (C) 2003-2015 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 MPC_FORMAT_H
+#define MPC_FORMAT_H
+
+#include "Compiler.h"
+
+struct mpd_song;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Pretty-print an object into a string using the given format
+ * specification.
+ *
+ * @param format the format string
+ * @param object the object
+ * @param getter a getter function that extracts a value from the object
+ * @return the resulting string to be freed by free(); NULL if
+ * no format string group produced any output
+ */
+gcc_malloc
+char *
+format_object(const char *format, const void *object,
+ const char *(*getter)(const void *object, const char *name));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/win32/Win32Main.cxx b/src/win32/Win32Main.cxx
index 75a1e9a23..8bef63f3c 100644
--- a/src/win32/Win32Main.cxx
+++ b/src/win32/Win32Main.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -29,8 +29,6 @@
#include <cstdlib>
#include <atomic>
-#include <glib.h>
-
#include <windows.h>
static int service_argc;
@@ -42,7 +40,7 @@ static SERVICE_STATUS_HANDLE service_handle;
static void WINAPI
service_main(DWORD argc, CHAR *argv[]);
-static SERVICE_TABLE_ENTRY service_registry[] = {
+static constexpr SERVICE_TABLE_ENTRY service_registry[] = {
{service_name, service_main},
{nullptr, nullptr}
};
@@ -82,19 +80,12 @@ service_dispatcher(gcc_unused DWORD control, gcc_unused DWORD event_type,
static void WINAPI
service_main(gcc_unused DWORD argc, gcc_unused CHAR *argv[])
{
- DWORD error_code;
- gchar* error_message;
-
service_handle =
RegisterServiceCtrlHandlerEx(service_name,
service_dispatcher, nullptr);
- if (service_handle == 0) {
- error_code = GetLastError();
- error_message = g_win32_error_message(error_code);
- FormatFatalError("RegisterServiceCtrlHandlerEx() failed: %s",
- error_message);
- }
+ if (service_handle == 0)
+ FatalSystemError("RegisterServiceCtrlHandlerEx() failed");
service_notify_status(SERVICE_START_PENDING);
mpd_main(service_argc, service_argv);
@@ -131,16 +122,13 @@ console_handler(DWORD event)
int win32_main(int argc, char *argv[])
{
- DWORD error_code;
- gchar* error_message;
-
service_argc = argc;
service_argv = argv;
if (StartServiceCtrlDispatcher(service_registry))
return 0; /* run as service successefully */
- error_code = GetLastError();
+ const DWORD error_code = GetLastError();
if (error_code == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
/* running as console app */
running.store(false);
@@ -149,9 +137,7 @@ int win32_main(int argc, char *argv[])
return mpd_main(argc, argv);
}
- error_message = g_win32_error_message(error_code);
- FormatFatalError("StartServiceCtrlDispatcher() failed: %s",
- error_message);
+ FatalSystemError("StartServiceCtrlDispatcher() failed", error_code);
}
void win32_app_started()
diff --git a/src/win32/mpd.ico b/src/win32/mpd.ico
deleted file mode 100644
index 86fd9fe43..000000000
--- a/src/win32/mpd.ico
+++ /dev/null
Binary files differ
diff --git a/src/win32/mpd_win32_rc.rc.in b/src/win32/mpd_win32_rc.rc.in
deleted file mode 100644
index e5312dc78..000000000
--- a/src/win32/mpd_win32_rc.rc.in
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <windows.h>
-
-#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/win32/mpd.ico"
-
-1 VERSIONINFO
-FILETYPE VFT_APP
-FILEOS VOS__WINDOWS32
-PRODUCTVERSION VERSION_NUMBER
-
-FILEVERSION VERSION_NUMBER
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "Music Player Daemon Project"
- VALUE "ProductName", "Music Player Daemon"
- VALUE "ProductVersion", VERSION_NUMBER_STR
- VALUE "InternalName", "mpd"
- VALUE "OriginalFilename", "mpd.exe"
- VALUE "FileVersion", "@VERSION@"
- VALUE "FileDescription", "Music Player Daemon @VERSION@"
- VALUE "LegalCopyright", "Copyright \251 The Music Player Daemon Project"
- END
- END
-
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
diff --git a/src/zeroconf/AvahiPoll.cxx b/src/zeroconf/AvahiPoll.cxx
index 20d5d74e6..1c75cda5a 100644
--- a/src/zeroconf/AvahiPoll.cxx
+++ b/src/zeroconf/AvahiPoll.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/AvahiPoll.hxx b/src/zeroconf/AvahiPoll.hxx
index e194d3370..ab340565d 100644
--- a/src/zeroconf/AvahiPoll.hxx
+++ b/src/zeroconf/AvahiPoll.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfAvahi.cxx b/src/zeroconf/ZeroconfAvahi.cxx
index 5adda38f9..46393e9f6 100644
--- a/src/zeroconf/ZeroconfAvahi.cxx
+++ b/src/zeroconf/ZeroconfAvahi.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfAvahi.hxx b/src/zeroconf/ZeroconfAvahi.hxx
index 09a199f55..2719de528 100644
--- a/src/zeroconf/ZeroconfAvahi.hxx
+++ b/src/zeroconf/ZeroconfAvahi.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfBonjour.cxx b/src/zeroconf/ZeroconfBonjour.cxx
index 8d7565e0e..3f395f54e 100644
--- a/src/zeroconf/ZeroconfBonjour.cxx
+++ b/src/zeroconf/ZeroconfBonjour.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfBonjour.hxx b/src/zeroconf/ZeroconfBonjour.hxx
index cff52815e..70d9039c8 100644
--- a/src/zeroconf/ZeroconfBonjour.hxx
+++ b/src/zeroconf/ZeroconfBonjour.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfGlue.cxx b/src/zeroconf/ZeroconfGlue.cxx
index 95797491b..f00395e7c 100644
--- a/src/zeroconf/ZeroconfGlue.cxx
+++ b/src/zeroconf/ZeroconfGlue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@ ZeroconfInit(gcc_unused EventLoop &loop)
{
const char *serviceName;
- zeroconfEnabled = config_get_bool(CONF_ZEROCONF_ENABLED,
+ zeroconfEnabled = config_get_bool(ConfigOption::ZEROCONF_ENABLED,
DEFAULT_ZEROCONF_ENABLED);
if (!zeroconfEnabled)
return;
@@ -56,7 +56,8 @@ ZeroconfInit(gcc_unused EventLoop &loop)
return;
}
- serviceName = config_get_string(CONF_ZEROCONF_NAME, SERVICE_NAME);
+ serviceName = config_get_string(ConfigOption::ZEROCONF_NAME,
+ SERVICE_NAME);
#ifdef HAVE_AVAHI
AvahiInit(loop, serviceName);
diff --git a/src/zeroconf/ZeroconfGlue.hxx b/src/zeroconf/ZeroconfGlue.hxx
index 5d2f29642..7abd07e65 100644
--- a/src/zeroconf/ZeroconfGlue.hxx
+++ b/src/zeroconf/ZeroconfGlue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/zeroconf/ZeroconfInternal.hxx b/src/zeroconf/ZeroconfInternal.hxx
index 4d47d260a..3376062ff 100644
--- a/src/zeroconf/ZeroconfInternal.hxx
+++ b/src/zeroconf/ZeroconfInternal.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify