Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
33f5e03e
Commit
33f5e03e
authored
Jun 17, 2019
by
Max Kellermann
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v0.21.x'
parents
fd7caab8
2c3eeb71
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
184 additions
and
288 deletions
+184
-288
NEWS
NEWS
+6
-0
AndroidManifest.xml
android/AndroidManifest.xml
+2
-2
tags.xml
doc/include/tags.xml
+0
-165
MusicChunk.hxx
src/MusicChunk.hxx
+13
-1
DatabaseCommands.cxx
src/command/DatabaseCommands.cxx
+17
-10
DatabasePrint.cxx
src/db/DatabasePrint.cxx
+12
-24
DatabasePrint.hxx
src/db/DatabasePrint.hxx
+2
-1
Interface.hxx
src/db/Interface.hxx
+7
-7
UniqueTags.cxx
src/db/UniqueTags.cxx
+16
-20
UniqueTags.hxx
src/db/UniqueTags.hxx
+4
-2
ProxyDatabasePlugin.cxx
src/db/plugins/ProxyDatabasePlugin.cxx
+45
-40
SimpleDatabasePlugin.cxx
src/db/plugins/simple/SimpleDatabasePlugin.cxx
+5
-3
SimpleDatabasePlugin.hxx
src/db/plugins/simple/SimpleDatabasePlugin.hxx
+2
-3
UpnpDatabasePlugin.cxx
src/db/plugins/upnp/UpnpDatabasePlugin.cxx
+7
-7
OssOutputPlugin.cxx
src/output/plugins/OssOutputPlugin.cxx
+3
-2
Export.hxx
src/pcm/Export.hxx
+2
-1
RecursiveMap.hxx
src/util/RecursiveMap.hxx
+41
-0
No files found.
NEWS
View file @
33f5e03e
...
...
@@ -12,6 +12,12 @@ ver 0.22 (not yet released)
- ffmpeg: new plugin based on FFmpeg's libavfilter library
- hdcd: new plugin based on FFmpeg's "af_hdcd" for HDCD playback
ver 0.21.11 (not yet released)
* output
- alsa, osx: fix distortions with DSD_U32 and DoP on 32 bit CPUs
* protocol
- fix "list" with multiple "group" levels
ver 0.21.10 (2019/06/05)
* decoder
- opus: fix duplicate tags
...
...
android/AndroidManifest.xml
View file @
33f5e03e
...
...
@@ -2,8 +2,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"org.musicpd"
android:installLocation=
"auto"
android:versionCode=
"3
3
"
android:versionName=
"0.21.1
0
"
>
android:versionCode=
"3
4
"
android:versionName=
"0.21.1
1
"
>
<uses-sdk
android:minSdkVersion=
"21"
android:targetSdkVersion=
"26"
/>
...
...
doc/include/tags.xml
deleted
100644 → 0
View file @
fd7caab8
<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE itemizedlist PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<itemizedlist>
<listitem>
<para>
<varname>
artist
</varname>
: the artist name. Its meaning is not
well-defined; see
<varname>
composer
</varname>
and
<varname>
performer
</varname>
for more specific tags.
</para>
</listitem>
<listitem>
<para>
<varname>
artistsort
</varname>
: same as
<varname>
artist
</varname>
, but for sorting. This usually omits
prefixes such as "The".
</para>
</listitem>
<listitem>
<para>
<varname>
album
</varname>
: the album name.
</para>
</listitem>
<listitem>
<para>
<varname>
albumsort
</varname>
: same as
<varname>
album
</varname>
,
but for sorting.
</para>
</listitem>
<listitem>
<para>
<varname>
albumartist
</varname>
: on multi-artist albums, this is
the artist name which shall be used for the whole album. The
exact meaning of this tag is not well-defined.
</para>
</listitem>
<listitem>
<para>
<varname>
albumartistsort
</varname>
: same as
<varname>
albumartist
</varname>
, but for sorting.
</para>
</listitem>
<listitem>
<para>
<varname>
title
</varname>
: the song title.
</para>
</listitem>
<listitem>
<para>
<varname>
track
</varname>
: the decimal track number within the
album.
</para>
</listitem>
<listitem>
<para>
<varname>
name
</varname>
: a name for this song. This is not the
song title. The exact meaning of this tag is not well-defined.
It is often used by badly configured internet radio stations
with broken tags to squeeze both the artist name and the song
title in one tag.
</para>
</listitem>
<listitem>
<para>
<varname>
genre
</varname>
: the music genre.
</para>
</listitem>
<listitem>
<para>
<varname>
date
</varname>
: the song's release date. This is
usually a 4-digit year.
</para>
</listitem>
<listitem>
<para>
<varname>
composer
</varname>
: the artist who composed the song.
</para>
</listitem>
<listitem>
<para>
<varname>
performer
</varname>
: the artist who performed the song.
</para>
</listitem>
<listitem>
<para>
<varname>
comment
</varname>
: a human-readable comment about this
song. The exact meaning of this tag is not well-defined.
</para>
</listitem>
<listitem>
<para>
<varname>
disc
</varname>
: the decimal disc number in a multi-disc
album.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_artistid
</varname>
: the artist id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_albumid
</varname>
: the album id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_albumartistid
</varname>
: the album artist
id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_trackid
</varname>
: the track id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_releasetrackid
</varname>
: the release track
id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
<listitem>
<para>
<varname>
musicbrainz_workid
</varname>
: the work id in the
<ulink
url=
"https://picard.musicbrainz.org/docs/mappings/"
>
MusicBrainz
</ulink>
database.
</para>
</listitem>
</itemizedlist>
src/MusicChunk.hxx
View file @
33f5e03e
...
...
@@ -43,7 +43,15 @@ struct MusicChunk;
/**
* Meta information for #MusicChunk.
*/
struct
MusicChunkInfo
{
struct
alignas
(
8
)
MusicChunkInfo
{
/* align to multiple of 8 bytes, which adds padding at the
end, so the size of MusicChunk::data is also a multiple of
8 bytes; this is a workaround for a bug in the DSD_U32 and
DoP converters which require processing 8 bytes at a time,
discarding the remainder */
/* TODO: once all converters have been fixed, we should remove
this workaround */
/** the next chunk in a linked list */
MusicChunkPtr
next
;
...
...
@@ -119,6 +127,10 @@ struct MusicChunk : MusicChunkInfo {
/** the data (probably PCM) */
uint8_t
data
[
CHUNK_SIZE
-
sizeof
(
MusicChunkInfo
)];
/* TODO: remove this check once all converters have been fixed
(see comment in struct MusicChunkInfo for details) */
static_assert
(
sizeof
(
data
)
%
8
==
0
,
"Wrong alignment"
);
/**
* Prepares appending to the music chunk. Returns a buffer
* where you may write into. After you are finished, call
...
...
src/command/DatabaseCommands.cxx
View file @
33f5e03e
...
...
@@ -260,7 +260,7 @@ handle_list(Client &client, Request args, Response &r)
}
std
::
unique_ptr
<
SongFilter
>
filter
;
TagType
group
=
TAG_NUM_OF_ITEM_TYPES
;
std
::
vector
<
TagType
>
tag_types
;
if
(
args
.
size
==
1
&&
/* parantheses are the syntax for filter expressions: no
...
...
@@ -278,20 +278,31 @@ handle_list(Client &client, Request args, Response &r)
args
.
shift
()));
}
if
(
args
.
size
>=
2
&&
StringIsEqual
(
args
[
args
.
size
-
2
],
"group"
))
{
while
(
args
.
size
>=
2
&&
StringIsEqual
(
args
[
args
.
size
-
2
],
"group"
))
{
const
char
*
s
=
args
[
args
.
size
-
1
];
group
=
tag_name_parse_i
(
s
);
const
auto
group
=
tag_name_parse_i
(
s
);
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
{
r
.
FormatError
(
ACK_ERROR_ARG
,
"Unknown tag type: %s"
,
s
);
return
CommandResult
::
ERROR
;
}
if
(
group
==
tagType
||
std
::
find
(
tag_types
.
begin
(),
tag_types
.
end
(),
group
)
!=
tag_types
.
end
())
{
r
.
Error
(
ACK_ERROR_ARG
,
"Conflicting group"
);
return
CommandResult
::
ERROR
;
}
tag_types
.
emplace_back
(
group
);
args
.
pop_back
();
args
.
pop_back
();
}
tag_types
.
emplace_back
(
tagType
);
if
(
!
args
.
empty
())
{
filter
.
reset
(
new
SongFilter
());
try
{
...
...
@@ -304,13 +315,9 @@ handle_list(Client &client, Request args, Response &r)
filter
->
Optimize
();
}
if
(
tagType
<
TAG_NUM_OF_ITEM_TYPES
&&
tagType
==
group
)
{
r
.
Error
(
ACK_ERROR_ARG
,
"Conflicting group"
);
return
CommandResult
::
ERROR
;
}
PrintUniqueTags
(
r
,
client
.
GetPartition
(),
tagType
,
group
,
filter
.
get
());
{
&
tag_types
.
front
(),
tag_types
.
size
()},
filter
.
get
());
return
CommandResult
::
OK
;
}
...
...
src/db/DatabasePrint.cxx
View file @
33f5e03e
...
...
@@ -35,6 +35,7 @@
#include "Interface.hxx"
#include "fs/Traits.hxx"
#include "time/ChronoUtil.hxx"
#include "util/RecursiveMap.hxx"
#include <functional>
...
...
@@ -186,42 +187,29 @@ PrintSongUris(Response &r, Partition &partition,
}
static
void
PrintUniqueTags
(
Response
&
r
,
TagType
tag_type
,
const
std
::
set
<
std
::
string
>
&
values
)
PrintUniqueTags
(
Response
&
r
,
ConstBuffer
<
TagType
>
tag_types
,
const
RecursiveMap
<
std
::
string
>
&
map
)
noexcept
{
const
char
*
const
name
=
tag_item_names
[
tag_type
];
for
(
const
auto
&
i
:
values
)
r
.
Format
(
"%s: %s
\n
"
,
name
,
i
.
c_str
());
}
const
char
*
const
name
=
tag_item_names
[
tag_types
.
front
()];
tag_types
.
pop_front
();
static
void
PrintGroupedUniqueTags
(
Response
&
r
,
TagType
tag_type
,
TagType
group
,
const
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
&
groups
)
{
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
{
for
(
const
auto
&
i
:
groups
)
PrintUniqueTags
(
r
,
tag_type
,
i
.
second
);
return
;
}
for
(
const
auto
&
i
:
map
)
{
r
.
Format
(
"%s: %s
\n
"
,
name
,
i
.
first
.
c_str
());
const
char
*
const
group_name
=
tag_item_names
[
group
];
for
(
const
auto
&
i
:
groups
)
{
r
.
Format
(
"%s: %s
\n
"
,
group_name
,
i
.
first
.
c_str
());
PrintUniqueTags
(
r
,
tag_type
,
i
.
second
);
if
(
!
tag_types
.
empty
())
PrintUniqueTags
(
r
,
tag_types
,
i
.
second
);
}
}
void
PrintUniqueTags
(
Response
&
r
,
Partition
&
partition
,
TagType
type
,
TagType
group
,
ConstBuffer
<
TagType
>
tag_types
,
const
SongFilter
*
filter
)
{
assert
(
type
<
TAG_NUM_OF_ITEM_TYPES
);
const
Database
&
db
=
partition
.
GetDatabaseOrThrow
();
const
DatabaseSelection
selection
(
""
,
true
,
filter
);
Print
GroupedUniqueTags
(
r
,
type
,
group
,
db
.
CollectUniqueTags
(
selection
,
type
,
group
));
Print
UniqueTags
(
r
,
tag_types
,
db
.
CollectUniqueTags
(
selection
,
tag_types
));
}
src/db/DatabasePrint.hxx
View file @
33f5e03e
...
...
@@ -22,6 +22,7 @@
#include <stdint.h>
template
<
typename
T
>
struct
ConstBuffer
;
enum
TagType
:
uint8_t
;
class
TagMask
;
class
SongFilter
;
...
...
@@ -45,7 +46,7 @@ PrintSongUris(Response &r, Partition &partition,
void
PrintUniqueTags
(
Response
&
r
,
Partition
&
partition
,
TagType
type
,
TagType
group
,
ConstBuffer
<
TagType
>
tag_types
,
const
SongFilter
*
filter
);
#endif
src/db/Interface.hxx
View file @
33f5e03e
...
...
@@ -25,15 +25,14 @@
#include "util/Compiler.h"
#include <chrono>
#include <map>
#include <set>
#include <string>
struct
DatabasePlugin
;
struct
DatabaseStats
;
struct
DatabaseSelection
;
struct
LightSong
;
class
TagMask
;
template
<
typename
Key
>
class
RecursiveMap
;
template
<
typename
T
>
struct
ConstBuffer
;
class
Database
{
const
DatabasePlugin
&
plugin
;
...
...
@@ -106,13 +105,14 @@ public:
}
/**
* Collect unique values of the given tag type.
* Collect unique values of the given tag types. Each item in
* the #tag_types parameter results in one nesting level in
* the return value.
*
* Throws on error.
*/
virtual
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
=
TAG_NUM_OF_ITEM_TYPES
)
const
=
0
;
virtual
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
ConstBuffer
<
TagType
>
tag_types
)
const
=
0
;
/**
* Throws on error.
...
...
src/db/UniqueTags.cxx
View file @
33f5e03e
...
...
@@ -21,36 +21,32 @@
#include "Interface.hxx"
#include "song/LightSong.hxx"
#include "tag/VisitFallback.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RecursiveMap.hxx"
static
void
Collect
Tags
(
std
::
set
<
std
::
string
>
&
result
,
const
Tag
&
tag
,
TagType
tag_type
)
noexcept
Collect
UniqueTags
(
RecursiveMap
<
std
::
string
>
&
result
,
const
Tag
&
tag
,
ConstBuffer
<
TagType
>
tag_types
)
noexcept
{
VisitTagWithFallbackOrEmpty
(
tag
,
tag_type
,
[
&
result
](
const
char
*
value
){
result
.
emplace
(
value
);
});
}
if
(
tag_types
.
empty
())
return
;
static
void
CollectGroupTags
(
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
&
result
,
const
Tag
&
tag
,
TagType
tag_type
,
TagType
group
)
noexcept
{
VisitTagWithFallbackOrEmpty
(
tag
,
group
,
[
&
](
const
char
*
group_name
){
CollectTags
(
result
[
group_name
],
tag
,
tag_type
);
const
auto
tag_type
=
tag_types
.
shift
();
VisitTagWithFallbackOrEmpty
(
tag
,
tag_type
,
[
&
result
,
&
tag
,
tag_types
](
const
char
*
value
){
CollectUniqueTags
(
result
[
value
],
tag
,
tag_types
);
});
}
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
Database
&
db
,
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
ConstBuffer
<
TagType
>
tag_types
)
{
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
result
;
RecursiveMap
<
std
::
string
>
result
;
db
.
Visit
(
selection
,
[
&
result
,
tag_type
,
group
](
const
LightSong
&
song
){
Collect
GroupTags
(
result
,
song
.
tag
,
tag_type
,
group
);
db
.
Visit
(
selection
,
[
&
result
,
tag_type
s
](
const
LightSong
&
song
){
Collect
UniqueTags
(
result
,
song
.
tag
,
tag_types
);
});
return
result
;
...
...
src/db/UniqueTags.hxx
View file @
33f5e03e
...
...
@@ -29,9 +29,11 @@
class
TagMask
;
class
Database
;
struct
DatabaseSelection
;
template
<
typename
Key
>
class
RecursiveMap
;
template
<
typename
T
>
struct
ConstBuffer
;
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
Database
&
db
,
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
);
ConstBuffer
<
TagType
>
tag_types
);
#endif
src/db/plugins/ProxyDatabasePlugin.cxx
View file @
33f5e03e
...
...
@@ -38,6 +38,8 @@
#include "tag/Tag.hxx"
#include "tag/Mask.hxx"
#include "tag/ParseName.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RecursiveMap.hxx"
#include "util/ScopeExit.hxx"
#include "util/RuntimeError.hxx"
#include "protocol/Ack.hxx"
...
...
@@ -127,9 +129,8 @@ public:
VisitSong
visit_song
,
VisitPlaylist
visit_playlist
)
const
override
;
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
const
override
;
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
ConstBuffer
<
TagType
>
tag_types
)
const
override
;
DatabaseStats
GetStats
(
const
DatabaseSelection
&
selection
)
const
override
;
...
...
@@ -412,8 +413,7 @@ SendConstraints(mpd_connection *connection, const DatabaseSelection &selection)
static
bool
SendGroup
(
mpd_connection
*
connection
,
TagType
group
)
{
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
return
true
;
assert
(
group
!=
TAG_NUM_OF_ITEM_TYPES
);
#if LIBMPDCLIENT_CHECK_VERSION(2,12,0)
const
auto
tag
=
Convert
(
group
);
...
...
@@ -428,6 +428,19 @@ SendGroup(mpd_connection *connection, TagType group)
#endif
}
static
bool
SendGroup
(
mpd_connection
*
connection
,
ConstBuffer
<
TagType
>
group
)
{
while
(
!
group
.
empty
())
{
if
(
!
SendGroup
(
connection
,
group
.
back
()))
return
false
;
group
.
pop_back
();
}
return
true
;
}
ProxyDatabase
::
ProxyDatabase
(
EventLoop
&
_loop
,
DatabaseListener
&
_listener
,
const
ConfigBlock
&
block
)
:
Database
(
proxy_db_plugin
),
...
...
@@ -983,17 +996,20 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
helper
.
Commit
();
}
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
RecursiveMap
<
std
::
string
>
ProxyDatabase
::
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
const
ConstBuffer
<
TagType
>
tag_types
)
const
try
{
// TODO: eliminate the const_cast
const_cast
<
ProxyDatabase
*>
(
this
)
->
EnsureConnected
();
enum
mpd_tag_type
tag_type2
=
Convert
(
tag_type
);
enum
mpd_tag_type
tag_type2
=
Convert
(
tag_type
s
.
back
()
);
if
(
tag_type2
==
MPD_TAG_COUNT
)
throw
std
::
runtime_error
(
"Unsupported tag"
);
auto
group
=
tag_types
;
group
.
pop_back
();
if
(
!
mpd_search_db_tags
(
connection
,
tag_type2
)
||
!
SendConstraints
(
connection
,
selection
)
||
!
SendGroup
(
connection
,
group
))
...
...
@@ -1002,44 +1018,33 @@ try {
if
(
!
mpd_search_commit
(
connection
))
ThrowError
(
connection
);
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
result
;
if
(
group
==
TAG_NUM_OF_ITEM_TYPES
)
{
auto
&
values
=
result
[
std
::
string
()];
while
(
auto
*
pair
=
mpd_recv_pair
(
connection
))
{
AtScopeExit
(
this
,
pair
)
{
mpd_return_pair
(
connection
,
pair
);
};
RecursiveMap
<
std
::
string
>
result
;
std
::
vector
<
RecursiveMap
<
std
::
string
>
*>
position
;
position
.
emplace_back
(
&
result
);
const
auto
current_type
=
tag_name_parse_i
(
pair
->
name
);
if
(
current_type
==
TAG_NUM_OF_ITEM_TYPES
)
continue
;
while
(
auto
*
pair
=
mpd_recv_pair
(
connection
))
{
AtScopeExit
(
this
,
pair
)
{
mpd_return_pair
(
connection
,
pair
);
};
if
(
current_type
==
tag_type
)
values
.
emplace
(
pair
->
value
);
}
}
else
{
std
::
set
<
std
::
string
>
*
current_group
=
nullptr
;
const
auto
current_type
=
tag_name_parse_i
(
pair
->
name
);
if
(
current_type
==
TAG_NUM_OF_ITEM_TYPES
)
continue
;
while
(
auto
*
pair
=
mpd_recv_pair
(
connection
))
{
AtScopeExit
(
this
,
pair
)
{
mpd_return_pair
(
connection
,
pair
);
}
;
auto
it
=
std
::
find
(
tag_types
.
begin
(),
tag_types
.
end
(),
current_type
);
if
(
it
==
tag_types
.
end
())
continue
;
const
auto
current_type
=
tag_name_parse_i
(
pair
->
name
);
if
(
current_type
==
TAG_NUM_OF_ITEM_TYPES
)
continue
;
size_t
i
=
std
::
distance
(
tag_types
.
begin
(),
it
);
if
(
i
>
position
.
size
()
)
continue
;
if
(
current_type
==
tag_type
)
{
if
(
current_group
==
nullptr
)
current_group
=
&
result
[
std
::
string
()];
if
(
i
+
1
<
position
.
size
())
position
.
resize
(
i
+
1
);
current_group
->
emplace
(
pair
->
value
);
}
else
if
(
current_type
==
group
)
{
current_group
=
&
result
[
pair
->
value
];
}
}
auto
&
parent
=
*
position
[
i
];
position
.
emplace_back
(
&
parent
[
pair
->
value
]);
}
if
(
!
mpd_response_finish
(
connection
))
...
...
src/db/plugins/simple/SimpleDatabasePlugin.cxx
View file @
33f5e03e
...
...
@@ -42,6 +42,8 @@
#include "fs/FileSystem.hxx"
#include "util/CharUtil.hxx"
#include "util/Domain.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RecursiveMap.hxx"
#include "Log.hxx"
#ifdef ENABLE_ZLIB
...
...
@@ -329,11 +331,11 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
"No such directory"
);
}
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
RecursiveMap
<
std
::
string
>
SimpleDatabase
::
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
const
ConstBuffer
<
TagType
>
tag_types
)
const
{
return
::
CollectUniqueTags
(
*
this
,
selection
,
tag_type
,
group
);
return
::
CollectUniqueTags
(
*
this
,
selection
,
tag_type
s
);
}
DatabaseStats
...
...
src/db/plugins/simple/SimpleDatabasePlugin.hxx
View file @
33f5e03e
...
...
@@ -122,9 +122,8 @@ public:
VisitSong
visit_song
,
VisitPlaylist
visit_playlist
)
const
override
;
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
const
override
;
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
ConstBuffer
<
TagType
>
tag_types
)
const
override
;
DatabaseStats
GetStats
(
const
DatabaseSelection
&
selection
)
const
override
;
...
...
src/db/plugins/upnp/UpnpDatabasePlugin.cxx
View file @
33f5e03e
...
...
@@ -40,10 +40,11 @@
#include "tag/Mask.hxx"
#include "fs/Traits.hxx"
#include "Log.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RecursiveMap.hxx"
#include "util/SplitString.hxx"
#include <string>
#include <set>
#include <assert.h>
#include <string.h>
...
...
@@ -97,9 +98,8 @@ public:
VisitSong
visit_song
,
VisitPlaylist
visit_playlist
)
const
override
;
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag_type
,
TagType
group
)
const
override
;
RecursiveMap
<
std
::
string
>
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
ConstBuffer
<
TagType
>
tag_types
)
const
override
;
DatabaseStats
GetStats
(
const
DatabaseSelection
&
selection
)
const
override
;
...
...
@@ -624,11 +624,11 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
helper
.
Commit
();
}
std
::
map
<
std
::
string
,
std
::
set
<
std
::
string
>
>
RecursiveMap
<
std
::
string
>
UpnpDatabase
::
CollectUniqueTags
(
const
DatabaseSelection
&
selection
,
TagType
tag
,
TagType
group
)
const
ConstBuffer
<
TagType
>
tag_types
)
const
{
return
::
CollectUniqueTags
(
*
this
,
selection
,
tag
,
group
);
return
::
CollectUniqueTags
(
*
this
,
selection
,
tag
_types
);
}
DatabaseStats
...
...
src/output/plugins/OssOutputPlugin.cxx
View file @
33f5e03e
...
...
@@ -670,12 +670,13 @@ OssOutput::Play(const void *chunk, size_t size)
#ifdef AFMT_S24_PACKED
const
auto
e
=
pcm_export
->
Export
({
chunk
,
size
});
if
(
e
.
empty
())
return
size
;
chunk
=
e
.
data
;
size
=
e
.
size
;
#endif
assert
(
size
>
0
);
while
(
true
)
{
ret
=
fd
.
Write
(
chunk
,
size
);
if
(
ret
>
0
)
{
...
...
src/pcm/Export.hxx
View file @
33f5e03e
...
...
@@ -173,7 +173,8 @@ public:
* Export a PCM buffer.
*
* @param src the source PCM buffer
* @return the destination buffer (may be a pointer to the source buffer)
* @return the destination buffer; may be empty (and may be a
* pointer to the source buffer)
*/
ConstBuffer
<
void
>
Export
(
ConstBuffer
<
void
>
src
)
noexcept
;
...
...
src/util/RecursiveMap.hxx
0 → 100644
View file @
33f5e03e
/*
* Copyright 2019 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RECURSIVE_MAP_HXX
#define RECURSIVE_MAP_HXX
#include <map>
/**
* A #std::map which contains instances of itself.
*/
template
<
typename
Key
>
class
RecursiveMap
:
public
std
::
map
<
Key
,
RecursiveMap
<
Key
>>
{};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment