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
3d3a1232
Commit
3d3a1232
authored
Jul 05, 2018
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tag/Handler: convert to class with virtual methods
parent
09d41762
Show whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
411 additions
and
493 deletions
+411
-493
TagArchive.cxx
src/TagArchive.cxx
+2
-2
TagArchive.hxx
src/TagArchive.hxx
+2
-2
TagFile.cxx
src/TagFile.cxx
+11
-11
TagFile.hxx
src/TagFile.hxx
+2
-3
TagStream.cxx
src/TagStream.cxx
+11
-9
TagStream.hxx
src/TagStream.hxx
+5
-5
FileCommands.cxx
src/command/FileCommands.cxx
+14
-14
OtherCommands.cxx
src/command/OtherCommands.cxx
+13
-14
DecoderPlugin.hxx
src/decoder/DecoderPlugin.hxx
+7
-13
AdPlugDecoderPlugin.cxx
src/decoder/plugins/AdPlugDecoderPlugin.cxx
+8
-11
AudiofileDecoderPlugin.cxx
src/decoder/plugins/AudiofileDecoderPlugin.cxx
+2
-3
DsdLib.cxx
src/decoder/plugins/DsdLib.cxx
+3
-4
DsdLib.hxx
src/decoder/plugins/DsdLib.hxx
+3
-4
DsdiffDecoderPlugin.cxx
src/decoder/plugins/DsdiffDecoderPlugin.cxx
+10
-13
DsfDecoderPlugin.cxx
src/decoder/plugins/DsfDecoderPlugin.cxx
+3
-5
FaadDecoderPlugin.cxx
src/decoder/plugins/FaadDecoderPlugin.cxx
+2
-4
FfmpegDecoderPlugin.cxx
src/decoder/plugins/FfmpegDecoderPlugin.cxx
+13
-17
FfmpegMetaData.cxx
src/decoder/plugins/FfmpegMetaData.cxx
+11
-15
FfmpegMetaData.hxx
src/decoder/plugins/FfmpegMetaData.hxx
+2
-3
FlacDecoderPlugin.cxx
src/decoder/plugins/FlacDecoderPlugin.cxx
+8
-12
FlacMetadata.cxx
src/decoder/plugins/FlacMetadata.cxx
+16
-19
FlacMetadata.hxx
src/decoder/plugins/FlacMetadata.hxx
+3
-3
FluidsynthDecoderPlugin.cxx
src/decoder/plugins/FluidsynthDecoderPlugin.cxx
+1
-2
GmeDecoderPlugin.cxx
src/decoder/plugins/GmeDecoderPlugin.cxx
+15
-26
MadDecoderPlugin.cxx
src/decoder/plugins/MadDecoderPlugin.cxx
+2
-4
MikmodDecoderPlugin.cxx
src/decoder/plugins/MikmodDecoderPlugin.cxx
+2
-4
ModplugDecoderPlugin.cxx
src/decoder/plugins/ModplugDecoderPlugin.cxx
+3
-6
MpcdecDecoderPlugin.cxx
src/decoder/plugins/MpcdecDecoderPlugin.cxx
+2
-3
Mpg123DecoderPlugin.cxx
src/decoder/plugins/Mpg123DecoderPlugin.cxx
+2
-3
OpusDecoderPlugin.cxx
src/decoder/plugins/OpusDecoderPlugin.cxx
+9
-11
OpusTags.cxx
src/decoder/plugins/OpusTags.cxx
+7
-7
OpusTags.hxx
src/decoder/plugins/OpusTags.hxx
+2
-2
SidplayDecoderPlugin.cxx
src/decoder/plugins/SidplayDecoderPlugin.cxx
+11
-17
SndfileDecoderPlugin.cxx
src/decoder/plugins/SndfileDecoderPlugin.cxx
+5
-7
VorbisDecoderPlugin.cxx
src/decoder/plugins/VorbisDecoderPlugin.cxx
+5
-7
WavpackDecoderPlugin.cxx
src/decoder/plugins/WavpackDecoderPlugin.cxx
+4
-6
WildmidiDecoderPlugin.cxx
src/decoder/plugins/WildmidiDecoderPlugin.cxx
+2
-3
VorbisComments.cxx
src/lib/xiph/VorbisComments.cxx
+11
-15
VorbisComments.hxx
src/lib/xiph/VorbisComments.hxx
+2
-3
EmbeddedCuePlaylistPlugin.cxx
src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
+22
-18
ApeTag.cxx
src/tag/ApeTag.cxx
+9
-14
ApeTag.hxx
src/tag/ApeTag.hxx
+2
-5
Generic.cxx
src/tag/Generic.cxx
+5
-5
Generic.hxx
src/tag/Generic.hxx
+3
-3
Handler.cxx
src/tag/Handler.cxx
+6
-24
Handler.hxx
src/tag/Handler.hxx
+66
-39
Id3Scan.cxx
src/tag/Id3Scan.cxx
+36
-44
Id3Scan.hxx
src/tag/Id3Scan.hxx
+3
-5
read_tags.cxx
test/read_tags.cxx
+23
-24
No files found.
src/TagArchive.cxx
View file @
3d3a1232
...
...
@@ -25,7 +25,7 @@
bool
tag_archive_scan
(
ArchiveFile
&
archive
,
const
char
*
path_utf8
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
TagHandler
&
handler
)
noexcept
try
{
Mutex
mutex
;
...
...
@@ -33,7 +33,7 @@ try {
if
(
!
is
)
return
false
;
return
tag_stream_scan
(
*
is
,
handler
,
handler_ctx
);
return
tag_stream_scan
(
*
is
,
handler
);
}
catch
(
const
std
::
exception
&
e
)
{
return
false
;
}
...
...
src/TagArchive.hxx
View file @
3d3a1232
...
...
@@ -23,7 +23,7 @@
#include "check.h"
class
ArchiveFile
;
struct
TagHandler
;
class
TagHandler
;
class
TagBuilder
;
/**
...
...
@@ -36,7 +36,7 @@ class TagBuilder;
*/
bool
tag_archive_scan
(
ArchiveFile
&
archive
,
const
char
*
path_utf8
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
;
TagHandler
&
handler
)
noexcept
;
/**
* Scan the tags of a song file inside an archive. Invokes matching
...
...
src/TagFile.cxx
View file @
3d3a1232
...
...
@@ -36,21 +36,20 @@ class TagFileScan {
const
Path
path_fs
;
const
char
*
const
suffix
;
const
TagHandler
&
handler
;
void
*
handler_ctx
;
TagHandler
&
handler
;
Mutex
mutex
;
InputStreamPtr
is
;
public
:
TagFileScan
(
Path
_path_fs
,
const
char
*
_suffix
,
const
TagHandler
&
_handler
,
void
*
_handler_ctx
)
noexcept
TagHandler
&
_handler
)
noexcept
:
path_fs
(
_path_fs
),
suffix
(
_suffix
),
handler
(
_handler
),
handler_ctx
(
_handler_ctx
)
,
handler
(
_handler
),
is
(
nullptr
)
{}
bool
ScanFile
(
const
DecoderPlugin
&
plugin
)
noexcept
{
return
plugin
.
ScanFile
(
path_fs
,
handler
,
handler_ctx
);
return
plugin
.
ScanFile
(
path_fs
,
handler
);
}
bool
ScanStream
(
const
DecoderPlugin
&
plugin
)
noexcept
{
...
...
@@ -72,7 +71,7 @@ public:
}
/* now try the stream_tag() method */
return
plugin
.
ScanStream
(
*
is
,
handler
,
handler_ctx
);
return
plugin
.
ScanStream
(
*
is
,
handler
);
}
bool
Scan
(
const
DecoderPlugin
&
plugin
)
noexcept
{
...
...
@@ -82,8 +81,7 @@ public:
};
bool
tag_file_scan
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
tag_file_scan
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
assert
(
!
path_fs
.
IsNull
());
...
...
@@ -95,7 +93,7 @@ tag_file_scan(Path path_fs,
const
auto
suffix_utf8
=
Path
::
FromFS
(
suffix
).
ToUTF8
();
TagFileScan
tfs
(
path_fs
,
suffix_utf8
.
c_str
(),
handler
,
handler_ctx
);
TagFileScan
tfs
(
path_fs
,
suffix_utf8
.
c_str
(),
handler
);
return
decoder_plugins_try
([
&
](
const
DecoderPlugin
&
plugin
){
return
tfs
.
Scan
(
plugin
);
});
...
...
@@ -104,11 +102,13 @@ tag_file_scan(Path path_fs,
bool
tag_file_scan
(
Path
path
,
TagBuilder
&
builder
)
noexcept
{
if
(
!
tag_file_scan
(
path
,
full_tag_handler
,
&
builder
))
FullTagHandler
h
(
builder
);
if
(
!
tag_file_scan
(
path
,
h
))
return
false
;
if
(
builder
.
empty
())
ScanGenericTags
(
path
,
full_tag_handler
,
&
builder
);
ScanGenericTags
(
path
,
h
);
return
true
;
}
src/TagFile.hxx
View file @
3d3a1232
...
...
@@ -23,7 +23,7 @@
#include "check.h"
class
Path
;
struct
TagHandler
;
class
TagHandler
;
class
TagBuilder
;
/**
...
...
@@ -34,8 +34,7 @@ class TagBuilder;
* found)
*/
bool
tag_file_scan
(
Path
path
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
;
tag_file_scan
(
Path
path
,
TagHandler
&
handler
)
noexcept
;
/**
* Scan the tags of a song file. Invokes matching decoder plugins,
...
...
src/TagStream.cxx
View file @
3d3a1232
...
...
@@ -46,7 +46,7 @@ CheckDecoderPlugin(const DecoderPlugin &plugin,
}
bool
tag_stream_scan
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
ctx
)
tag_stream_scan
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
assert
(
is
.
IsReady
());
...
...
@@ -62,44 +62,46 @@ tag_stream_scan(InputStream &is, const TagHandler &handler, void *ctx)
mime
=
(
mime_base
=
GetMimeTypeBase
(
mime
)).
c_str
();
return
decoder_plugins_try
([
suffix
,
mime
,
&
is
,
&
handler
,
ctx
](
const
DecoderPlugin
&
plugin
){
&
handler
](
const
DecoderPlugin
&
plugin
){
try
{
is
.
LockRewind
();
}
catch
(...)
{
}
return
CheckDecoderPlugin
(
plugin
,
suffix
,
mime
)
&&
plugin
.
ScanStream
(
is
,
handler
,
ctx
);
plugin
.
ScanStream
(
is
,
handler
);
});
}
bool
tag_stream_scan
(
const
char
*
uri
,
const
TagHandler
&
handler
,
void
*
ctx
)
tag_stream_scan
(
const
char
*
uri
,
TagHandler
&
handler
)
noexcept
try
{
Mutex
mutex
;
auto
is
=
InputStream
::
OpenReady
(
uri
,
mutex
);
return
tag_stream_scan
(
*
is
,
handler
,
ctx
);
return
tag_stream_scan
(
*
is
,
handler
);
}
catch
(
const
std
::
exception
&
e
)
{
return
false
;
}
bool
tag_stream_scan
(
InputStream
&
is
,
TagBuilder
&
builder
)
tag_stream_scan
(
InputStream
&
is
,
TagBuilder
&
builder
)
noexcept
{
assert
(
is
.
IsReady
());
if
(
!
tag_stream_scan
(
is
,
full_tag_handler
,
&
builder
))
FullTagHandler
h
(
builder
);
if
(
!
tag_stream_scan
(
is
,
h
))
return
false
;
if
(
builder
.
empty
())
ScanGenericTags
(
is
,
full_tag_handler
,
&
builder
);
ScanGenericTags
(
is
,
h
);
return
true
;
}
bool
tag_stream_scan
(
const
char
*
uri
,
TagBuilder
&
builder
)
tag_stream_scan
(
const
char
*
uri
,
TagBuilder
&
builder
)
noexcept
try
{
Mutex
mutex
;
...
...
src/TagStream.hxx
View file @
3d3a1232
...
...
@@ -23,7 +23,7 @@
#include "check.h"
class
InputStream
;
struct
TagHandler
;
class
TagHandler
;
class
TagBuilder
;
/**
...
...
@@ -34,10 +34,10 @@ class TagBuilder;
* found)
*/
bool
tag_stream_scan
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
ctx
)
;
tag_stream_scan
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
;
bool
tag_stream_scan
(
const
char
*
uri
,
const
TagHandler
&
handler
,
void
*
ctx
)
;
tag_stream_scan
(
const
char
*
uri
,
TagHandler
&
handler
)
noexcept
;
/**
* Scan the tags of an #InputStream. Invokes matching decoder
...
...
@@ -48,9 +48,9 @@ tag_stream_scan(const char *uri, const TagHandler &handler, void *ctx);
* found)
*/
bool
tag_stream_scan
(
InputStream
&
is
,
TagBuilder
&
builder
);
tag_stream_scan
(
InputStream
&
is
,
TagBuilder
&
builder
)
noexcept
;
bool
tag_stream_scan
(
const
char
*
uri
,
TagBuilder
&
builder
);
tag_stream_scan
(
const
char
*
uri
,
TagBuilder
&
builder
)
noexcept
;
#endif
src/command/FileCommands.cxx
View file @
3d3a1232
...
...
@@ -137,25 +137,24 @@ IsValidValue(const char *p) noexcept
return
true
;
}
static
void
print_pair
(
const
char
*
key
,
const
char
*
value
,
void
*
ctx
)
{
auto
&
r
=
*
(
Response
*
)
ctx
;
class
PrintCommentHandler
final
:
public
NullTagHandler
{
Response
&
response
;
if
(
IsValidName
(
key
)
&&
IsValidValue
(
value
))
r
.
Format
(
"%s: %s
\n
"
,
key
,
value
);
}
public
:
explicit
PrintCommentHandler
(
Response
&
_response
)
noexcept
:
NullTagHandler
(
WANT_PAIR
),
response
(
_response
)
{
}
static
constexpr
TagHandler
print_comment_handler
=
{
nullptr
,
nullptr
,
print_pair
,
void
OnPair
(
const
char
*
key
,
const
char
*
value
)
noexcept
override
{
if
(
IsValidName
(
key
)
&&
IsValidValue
(
value
))
response
.
Format
(
"%s: %s
\n
"
,
key
,
value
);
}
};
static
CommandResult
read_stream_comments
(
Response
&
r
,
const
char
*
uri
)
{
if
(
!
tag_stream_scan
(
uri
,
print_comment_handler
,
&
r
))
{
PrintCommentHandler
h
(
r
);
if
(
!
tag_stream_scan
(
uri
,
h
))
{
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Failed to load file"
);
return
CommandResult
::
ERROR
;
}
...
...
@@ -167,12 +166,13 @@ read_stream_comments(Response &r, const char *uri)
static
CommandResult
read_file_comments
(
Response
&
r
,
const
Path
path_fs
)
{
if
(
!
tag_file_scan
(
path_fs
,
print_comment_handler
,
&
r
))
{
PrintCommentHandler
h
(
r
);
if
(
!
tag_file_scan
(
path_fs
,
h
))
{
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Failed to load file"
);
return
CommandResult
::
ERROR
;
}
ScanGenericTags
(
path_fs
,
print_comment_handler
,
&
r
);
ScanGenericTags
(
path_fs
,
h
);
return
CommandResult
::
OK
;
...
...
src/command/OtherCommands.cxx
View file @
3d3a1232
...
...
@@ -93,15 +93,6 @@ handle_kill(gcc_unused Client &client, gcc_unused Request request,
return
CommandResult
::
KILL
;
}
static
void
print_tag
(
TagType
type
,
const
char
*
value
,
void
*
ctx
)
{
auto
&
r
=
*
(
Response
*
)
ctx
;
if
(
r
.
GetClient
().
tag_mask
.
Test
(
type
))
tag_print
(
r
,
type
,
value
);
}
CommandResult
handle_listfiles
(
Client
&
client
,
Request
args
,
Response
&
r
)
{
...
...
@@ -149,16 +140,24 @@ handle_listfiles(Client &client, Request args, Response &r)
gcc_unreachable
();
}
static
constexpr
TagHandler
print_tag_handler
=
{
nullptr
,
print_tag
,
nullptr
,
class
PrintTagHandler
final
:
public
NullTagHandler
{
Response
&
response
;
public
:
explicit
PrintTagHandler
(
Response
&
_response
)
noexcept
:
NullTagHandler
(
WANT_TAG
),
response
(
_response
)
{}
void
OnTag
(
TagType
type
,
const
char
*
value
)
noexcept
override
{
if
(
response
.
GetClient
().
tag_mask
.
Test
(
type
))
tag_print
(
response
,
type
,
value
);
}
};
static
CommandResult
handle_lsinfo_absolute
(
Response
&
r
,
const
char
*
uri
)
{
if
(
!
tag_stream_scan
(
uri
,
print_tag_handler
,
&
r
))
{
PrintTagHandler
h
(
r
);
if
(
!
tag_stream_scan
(
uri
,
h
))
{
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
return
CommandResult
::
ERROR
;
}
...
...
src/decoder/DecoderPlugin.hxx
View file @
3d3a1232
...
...
@@ -26,7 +26,7 @@
struct
ConfigBlock
;
class
InputStream
;
struct
TagHandler
;
class
TagHandler
;
class
Path
;
class
DecoderClient
;
class
DetachedSong
;
...
...
@@ -71,18 +71,14 @@ struct DecoderPlugin {
*
* @return false if the operation has failed
*/
bool
(
*
scan_file
)(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
;
bool
(
*
scan_file
)(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
;
/**
* Scan metadata of a file.
*
* @return false if the operation has failed
*/
bool
(
*
scan_stream
)(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
;
bool
(
*
scan_stream
)(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
;
/**
* @brief Return a "virtual" filename for subtracks in
...
...
@@ -139,20 +135,18 @@ struct DecoderPlugin {
* Read the tag of a file.
*/
template
<
typename
P
>
bool
ScanFile
(
P
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
const
noexcept
{
bool
ScanFile
(
P
path_fs
,
TagHandler
&
handler
)
const
noexcept
{
return
scan_file
!=
nullptr
?
scan_file
(
path_fs
,
handler
,
handler_ctx
)
?
scan_file
(
path_fs
,
handler
)
:
false
;
}
/**
* Read the tag of a stream.
*/
bool
ScanStream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
const
noexcept
{
bool
ScanStream
(
InputStream
&
is
,
TagHandler
&
handler
)
const
noexcept
{
return
scan_stream
!=
nullptr
?
scan_stream
(
is
,
handler
,
handler_ctx
)
?
scan_stream
(
is
,
handler
)
:
false
;
}
...
...
src/decoder/plugins/AdPlugDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -83,16 +83,14 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
static
void
adplug_scan_tag
(
TagType
type
,
const
std
::
string
&
value
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
TagHandler
&
handler
)
noexcept
{
if
(
!
value
.
empty
())
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
value
.
c_str
());
handler
.
OnTag
(
type
,
value
.
c_str
());
}
static
bool
adplug_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
adplug_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
CEmuopl
opl
(
sample_rate
,
true
,
true
);
opl
.
init
();
...
...
@@ -101,16 +99,15 @@ adplug_scan_file(Path path_fs,
if
(
player
==
nullptr
)
return
false
;
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
::
FromMS
(
player
->
songlength
()));
handler
.
OnDuration
(
SongTime
::
FromMS
(
player
->
songlength
()));
if
(
handler
.
tag
!=
nullptr
)
{
if
(
handler
.
WantTag
()
)
{
adplug_scan_tag
(
TAG_TITLE
,
player
->
gettitle
(),
handler
,
handler_ctx
);
handler
);
adplug_scan_tag
(
TAG_ARTIST
,
player
->
getauthor
(),
handler
,
handler_ctx
);
handler
);
adplug_scan_tag
(
TAG_COMMENT
,
player
->
getdesc
(),
handler
,
handler_ctx
);
handler
);
}
delete
player
;
...
...
src/decoder/plugins/AudiofileDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -256,14 +256,13 @@ audiofile_get_duration(InputStream &is) noexcept
}
static
bool
audiofile_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
audiofile_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
const
auto
duration
=
audiofile_get_duration
(
is
);
if
(
duration
.
IsNegative
())
return
false
;
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
duration
));
handler
.
OnDuration
(
SongTime
(
duration
));
return
true
;
}
...
...
src/decoder/plugins/DsdLib.cxx
View file @
3d3a1232
...
...
@@ -115,9 +115,8 @@ dsdlib_valid_freq(uint32_t samplefreq) noexcept
#ifdef ENABLE_ID3TAG
void
dsdlib_tag_id3
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
,
offset_type
tagoffset
)
dsdlib_tag_id3
(
InputStream
&
is
,
TagHandler
&
handler
,
offset_type
tagoffset
)
{
if
(
tagoffset
==
0
||
!
is
.
KnownSize
())
return
;
...
...
@@ -150,7 +149,7 @@ dsdlib_tag_id3(InputStream &is,
if
(
id3_tag
==
nullptr
)
return
;
scan_id3_tag
(
id3_tag
,
handler
,
handler_ctx
);
scan_id3_tag
(
id3_tag
,
handler
);
id3_tag_delete
(
id3_tag
);
return
;
...
...
src/decoder/plugins/DsdLib.hxx
View file @
3d3a1232
...
...
@@ -26,7 +26,7 @@
#include <stdint.h>
struct
TagHandler
;
class
TagHandler
;
class
DecoderClient
;
class
InputStream
;
...
...
@@ -79,8 +79,7 @@ dsdlib_valid_freq(uint32_t samplefreq) noexcept;
* DSF and DSDIFF files are imported
*/
void
dsdlib_tag_id3
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
,
offset_type
tagoffset
);
dsdlib_tag_id3
(
InputStream
&
is
,
TagHandler
&
handler
,
offset_type
tagoffset
);
#endif
src/decoder/plugins/DsdiffDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -186,8 +186,8 @@ dsdiff_read_prop(DecoderClient *client, InputStream &is,
static
void
dsdiff_handle_native_tag
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
,
offset_type
tagoffset
,
TagHandler
&
handler
,
offset_type
tagoffset
,
TagType
type
)
{
if
(
!
dsdlib_skip_to
(
nullptr
,
is
,
tagoffset
))
...
...
@@ -212,7 +212,7 @@ dsdiff_handle_native_tag(InputStream &is,
return
;
string
[
length
]
=
'\0'
;
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
label
);
handler
.
OnTag
(
type
,
label
);
return
;
}
...
...
@@ -228,8 +228,7 @@ static bool
dsdiff_read_metadata_extra
(
DecoderClient
*
client
,
InputStream
&
is
,
DsdiffMetaData
*
metadata
,
DsdiffChunkHeader
*
chunk_header
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
{
/* skip from DSD data to next chunk header */
...
...
@@ -286,17 +285,17 @@ dsdiff_read_metadata_extra(DecoderClient *client, InputStream &is,
if
(
id3_offset
!=
0
)
{
/* a ID3 tag has preference over the other tags, do not process
other tags if we have one */
dsdlib_tag_id3
(
is
,
handler
,
handler_ctx
,
id3_offset
);
dsdlib_tag_id3
(
is
,
handler
,
id3_offset
);
return
true
;
}
#endif
if
(
artist_offset
!=
0
)
dsdiff_handle_native_tag
(
is
,
handler
,
handler_ctx
,
dsdiff_handle_native_tag
(
is
,
handler
,
artist_offset
,
TAG_ARTIST
);
if
(
title_offset
!=
0
)
dsdiff_handle_native_tag
(
is
,
handler
,
handler_ctx
,
dsdiff_handle_native_tag
(
is
,
handler
,
title_offset
,
TAG_TITLE
);
return
true
;
}
...
...
@@ -449,9 +448,7 @@ dsdiff_stream_decode(DecoderClient &client, InputStream &is)
}
static
bool
dsdiff_scan_stream
(
InputStream
&
is
,
gcc_unused
const
TagHandler
&
handler
,
gcc_unused
void
*
handler_ctx
)
noexcept
dsdiff_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
DsdiffMetaData
metadata
;
DsdiffChunkHeader
chunk_header
;
...
...
@@ -469,11 +466,11 @@ dsdiff_scan_stream(InputStream &is,
uint64_t
n_frames
=
metadata
.
chunk_size
/
metadata
.
channels
;
auto
songtime
=
SongTime
::
FromScale
<
uint64_t
>
(
n_frames
,
sample_rate
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
songtime
);
handler
.
OnDuration
(
songtime
);
/* Read additional metadata and created tags if available */
dsdiff_read_metadata_extra
(
nullptr
,
is
,
&
metadata
,
&
chunk_header
,
handler
,
handler_ctx
);
handler
);
return
true
;
}
...
...
src/decoder/plugins/DsfDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -325,9 +325,7 @@ dsf_stream_decode(DecoderClient &client, InputStream &is)
}
static
bool
dsf_scan_stream
(
InputStream
&
is
,
gcc_unused
const
TagHandler
&
handler
,
gcc_unused
void
*
handler_ctx
)
noexcept
dsf_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
/* check DSF metadata */
DsfMetaData
metadata
;
...
...
@@ -342,11 +340,11 @@ dsf_scan_stream(InputStream &is,
const
auto
n_blocks
=
metadata
.
n_blocks
;
auto
songtime
=
SongTime
::
FromScale
<
uint64_t
>
(
n_blocks
*
DSF_BLOCK_SIZE
,
sample_rate
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
songtime
);
handler
.
OnDuration
(
songtime
);
#ifdef ENABLE_ID3TAG
/* Add available tags from the ID3 tag */
dsdlib_tag_id3
(
is
,
handler
,
handler_ctx
,
metadata
.
id3_offset
);
dsdlib_tag_id3
(
is
,
handler
,
metadata
.
id3_offset
);
#endif
return
true
;
}
...
...
src/decoder/plugins/FaadDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -414,16 +414,14 @@ faad_stream_decode(DecoderClient &client, InputStream &is)
}
static
bool
faad_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
faad_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
auto
result
=
faad_get_file_time
(
is
);
if
(
!
result
.
first
)
return
false
;
if
(
!
result
.
second
.
IsNegative
())
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
result
.
second
));
handler
.
OnDuration
(
SongTime
(
result
.
second
));
return
true
;
}
...
...
src/decoder/plugins/FfmpegDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -572,21 +572,20 @@ FfmpegParseMetaData(DecoderClient &client,
}
static
void
FfmpegScanMetadata
(
const
AVStream
&
stream
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
FfmpegScanMetadata
(
const
AVStream
&
stream
,
TagHandler
&
handler
)
noexcept
{
FfmpegScanDictionary
(
stream
.
metadata
,
handler
,
handler_ctx
);
FfmpegScanDictionary
(
stream
.
metadata
,
handler
);
}
static
void
FfmpegScanMetadata
(
const
AVFormatContext
&
format_context
,
int
audio_stream
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
assert
(
audio_stream
>=
0
);
FfmpegScanDictionary
(
format_context
.
metadata
,
handler
,
handler_ctx
);
FfmpegScanDictionary
(
format_context
.
metadata
,
handler
);
FfmpegScanMetadata
(
*
format_context
.
streams
[
audio_stream
],
handler
,
handler_ctx
);
handler
);
}
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
...
...
@@ -595,8 +594,8 @@ static void
FfmpegScanTag
(
const
AVFormatContext
&
format_context
,
int
audio_stream
,
TagBuilder
&
tag
)
{
F
fmpegScanMetadata
(
format_context
,
audio_stream
,
full_tag_handler
,
&
tag
);
F
ullTagHandler
h
(
tag
);
FfmpegScanMetadata
(
format_context
,
audio_stream
,
h
);
}
/**
...
...
@@ -828,7 +827,7 @@ ffmpeg_decode(DecoderClient &client, InputStream &input)
static
bool
FfmpegScanStream
(
AVFormatContext
&
format_context
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
int
find_result
=
avformat_find_stream_info
(
&
format_context
,
nullptr
);
...
...
@@ -841,22 +840,19 @@ FfmpegScanStream(AVFormatContext &format_context,
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
,
handler
.
OnDuration
(
FromFfmpegTime
(
stream
.
duration
,
stream
.
time_base
));
else
if
(
format_context
.
duration
!=
(
int64_t
)
AV_NOPTS_VALUE
)
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
FromFfmpegTime
(
format_context
.
duration
,
handler
.
OnDuration
(
FromFfmpegTime
(
format_context
.
duration
,
AV_TIME_BASE_Q
));
FfmpegScanMetadata
(
format_context
,
audio_stream
,
handler
,
handler_ctx
);
FfmpegScanMetadata
(
format_context
,
audio_stream
,
handler
);
return
true
;
}
static
bool
ffmpeg_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
ffmpeg_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
AVInputFormat
*
input_format
=
ffmpeg_probe
(
nullptr
,
is
);
if
(
input_format
==
nullptr
)
...
...
@@ -877,7 +873,7 @@ ffmpeg_scan_stream(InputStream &is,
avformat_close_input
(
&
f
);
};
return
FfmpegScanStream
(
*
f
,
handler
,
handler_ctx
);
return
FfmpegScanStream
(
*
f
,
handler
);
}
/**
...
...
src/decoder/plugins/FfmpegMetaData.cxx
View file @
3d3a1232
...
...
@@ -43,46 +43,42 @@ static constexpr struct tag_table ffmpeg_tags[] = {
static
void
FfmpegScanTag
(
TagType
type
,
AVDictionary
*
m
,
const
char
*
name
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
AVDictionaryEntry
*
mt
=
nullptr
;
while
((
mt
=
av_dict_get
(
m
,
name
,
mt
,
0
))
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
mt
->
value
);
handler
.
OnTag
(
type
,
mt
->
value
);
}
static
void
FfmpegScanPairs
(
AVDictionary
*
dict
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
FfmpegScanPairs
(
AVDictionary
*
dict
,
TagHandler
&
handler
)
noexcept
{
AVDictionaryEntry
*
i
=
nullptr
;
while
((
i
=
av_dict_get
(
dict
,
""
,
i
,
AV_DICT_IGNORE_SUFFIX
))
!=
nullptr
)
tag_handler_invoke_pair
(
handler
,
handler_ctx
,
i
->
key
,
i
->
value
);
handler
.
OnPair
(
i
->
key
,
i
->
value
);
}
void
FfmpegScanDictionary
(
AVDictionary
*
dict
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
FfmpegScanDictionary
(
AVDictionary
*
dict
,
TagHandler
&
handler
)
noexcept
{
if
(
handler
.
tag
!=
nullptr
)
{
if
(
handler
.
WantTag
()
)
{
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
++
i
)
FfmpegScanTag
(
TagType
(
i
),
dict
,
tag_item_names
[
i
],
handler
,
handler_ctx
);
handler
);
for
(
const
struct
tag_table
*
i
=
ffmpeg_tags
;
i
->
name
!=
nullptr
;
++
i
)
FfmpegScanTag
(
i
->
type
,
dict
,
i
->
name
,
handler
,
handler_ctx
);
handler
);
for
(
const
struct
tag_table
*
i
=
musicbrainz_txxx_tags
;
i
->
name
!=
nullptr
;
++
i
)
FfmpegScanTag
(
i
->
type
,
dict
,
i
->
name
,
handler
,
handler_ctx
);
handler
);
}
if
(
handler
.
pair
!=
nullptr
)
FfmpegScanPairs
(
dict
,
handler
,
handler_ctx
);
if
(
handler
.
WantPair
()
)
FfmpegScanPairs
(
dict
,
handler
);
}
src/decoder/plugins/FfmpegMetaData.hxx
View file @
3d3a1232
...
...
@@ -21,10 +21,9 @@
#define MPD_FFMPEG_METADATA_HXX
struct
AVDictionary
;
struct
TagHandler
;
class
TagHandler
;
void
FfmpegScanDictionary
(
AVDictionary
*
dict
,
const
TagHandler
&
handler
,
void
*
handler_ctx
);
FfmpegScanDictionary
(
AVDictionary
*
dict
,
TagHandler
&
handler
)
noexcept
;
#endif
src/decoder/plugins/FlacDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -69,8 +69,7 @@ flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
}
static
bool
flac_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
flac_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
FlacMetadataChain
chain
;
if
(
!
chain
.
Read
(
NarrowPath
(
path_fs
)))
{
...
...
@@ -80,13 +79,12 @@ flac_scan_file(Path path_fs,
return
false
;
}
chain
.
Scan
(
handler
,
handler_ctx
);
chain
.
Scan
(
handler
);
return
true
;
}
static
bool
flac_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
flac_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
FlacMetadataChain
chain
;
if
(
!
chain
.
Read
(
is
))
{
...
...
@@ -96,7 +94,7 @@ flac_scan_stream(InputStream &is,
return
false
;
}
chain
.
Scan
(
handler
,
handler_ctx
);
chain
.
Scan
(
handler
);
return
true
;
}
...
...
@@ -315,8 +313,7 @@ oggflac_init(gcc_unused const ConfigBlock &block)
}
static
bool
oggflac_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
oggflac_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
FlacMetadataChain
chain
;
if
(
!
chain
.
ReadOgg
(
NarrowPath
(
path_fs
)))
{
...
...
@@ -326,13 +323,12 @@ oggflac_scan_file(Path path_fs,
return
false
;
}
chain
.
Scan
(
handler
,
handler_ctx
);
chain
.
Scan
(
handler
);
return
true
;
}
static
bool
oggflac_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
oggflac_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
FlacMetadataChain
chain
;
if
(
!
chain
.
ReadOgg
(
is
))
{
...
...
@@ -342,7 +338,7 @@ oggflac_scan_stream(InputStream &is,
return
false
;
}
chain
.
Scan
(
handler
,
handler_ctx
);
chain
.
Scan
(
handler
);
return
true
;
}
...
...
src/decoder/plugins/FlacMetadata.cxx
View file @
3d3a1232
...
...
@@ -79,11 +79,11 @@ flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
static
bool
flac_copy_comment
(
const
FLAC__StreamMetadata_VorbisComment_Entry
*
entry
,
const
char
*
name
,
TagType
tag_type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
char
*
value
=
flac_comment_value
(
entry
,
name
);
if
(
value
!=
nullptr
)
{
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
tag_type
,
value
);
handler
.
OnTag
(
tag_type
,
value
);
return
true
;
}
...
...
@@ -92,36 +92,33 @@ flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
static
void
flac_scan_comment
(
const
FLAC__StreamMetadata_VorbisComment_Entry
*
entry
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
if
(
handler
.
pair
!=
nullptr
)
{
if
(
handler
.
WantPair
()
)
{
const
char
*
comment
=
(
const
char
*
)
entry
->
entry
;
const
DivideString
split
(
comment
,
'='
);
if
(
split
.
IsDefined
()
&&
!
split
.
empty
())
tag_handler_invoke_pair
(
handler
,
handler_ctx
,
split
.
GetFirst
(),
split
.
GetSecond
());
handler
.
OnPair
(
split
.
GetFirst
(),
split
.
GetSecond
());
}
for
(
const
struct
tag_table
*
i
=
xiph_tags
;
i
->
name
!=
nullptr
;
++
i
)
if
(
flac_copy_comment
(
entry
,
i
->
name
,
i
->
type
,
handler
,
handler_ctx
))
if
(
flac_copy_comment
(
entry
,
i
->
name
,
i
->
type
,
handler
))
return
;
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
++
i
)
if
(
flac_copy_comment
(
entry
,
tag_item_names
[
i
],
(
TagType
)
i
,
handler
,
handler_ctx
))
handler
))
return
;
}
static
void
flac_scan_comments
(
const
FLAC__StreamMetadata_VorbisComment
*
comment
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
for
(
unsigned
i
=
0
;
i
<
comment
->
num_comments
;
++
i
)
flac_scan_comment
(
&
comment
->
comments
[
i
],
handler
,
handler_ctx
);
handler
);
}
gcc_pure
...
...
@@ -136,18 +133,17 @@ flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) noexcept
void
flac_scan_metadata
(
const
FLAC__StreamMetadata
*
block
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
switch
(
block
->
type
)
{
case
FLAC__METADATA_TYPE_VORBIS_COMMENT
:
flac_scan_comments
(
&
block
->
data
.
vorbis_comment
,
handler
,
handler_ctx
);
handler
);
break
;
case
FLAC__METADATA_TYPE_STREAMINFO
:
if
(
block
->
data
.
stream_info
.
sample_rate
>
0
)
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
flac_duration
(
&
block
->
data
.
stream_info
));
handler
.
OnDuration
(
flac_duration
(
&
block
->
data
.
stream_info
));
break
;
default
:
...
...
@@ -159,12 +155,13 @@ Tag
flac_vorbis_comments_to_tag
(
const
FLAC__StreamMetadata_VorbisComment
*
comment
)
{
TagBuilder
tag_builder
;
flac_scan_comments
(
comment
,
add_tag_handler
,
&
tag_builder
);
AddTagHandler
h
(
tag_builder
);
flac_scan_comments
(
comment
,
h
);
return
tag_builder
.
Commit
();
}
void
FlacMetadataChain
::
Scan
(
const
TagHandler
&
handler
,
void
*
handler_ctx
)
FlacMetadataChain
::
Scan
(
TagHandler
&
handler
)
noexcept
{
FLACMetadataIterator
iterator
(
*
this
);
...
...
@@ -173,6 +170,6 @@ FlacMetadataChain::Scan(const TagHandler &handler, void *handler_ctx)
if
(
block
==
nullptr
)
break
;
flac_scan_metadata
(
block
,
handler
,
handler_ctx
);
flac_scan_metadata
(
block
,
handler
);
}
while
(
iterator
.
Next
());
}
src/decoder/plugins/FlacMetadata.hxx
View file @
3d3a1232
...
...
@@ -25,7 +25,7 @@
#include <FLAC/metadata.h>
struct
TagHandler
;
class
TagHandler
;
class
MixRampInfo
;
class
FlacMetadataChain
{
...
...
@@ -82,7 +82,7 @@ public:
return
FLAC__Metadata_ChainStatusString
[
GetStatus
()];
}
void
Scan
(
const
TagHandler
&
handler
,
void
*
handler_ctx
)
;
void
Scan
(
TagHandler
&
handler
)
noexcept
;
};
class
FLACMetadataIterator
{
...
...
@@ -126,6 +126,6 @@ flac_vorbis_comments_to_tag(const FLAC__StreamMetadata_VorbisComment *comment);
void
flac_scan_metadata
(
const
FLAC__StreamMetadata
*
block
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
;
TagHandler
&
handler
)
noexcept
;
#endif
src/decoder/plugins/FluidsynthDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -193,8 +193,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
static
bool
fluidsynth_scan_file
(
Path
path_fs
,
gcc_unused
const
TagHandler
&
handler
,
gcc_unused
void
*
handler_ctx
)
noexcept
gcc_unused
TagHandler
&
handler
)
noexcept
{
return
fluid_is_midifile
(
path_fs
.
c_str
());
}
...
...
src/decoder/plugins/GmeDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -215,15 +215,13 @@ gme_file_decode(DecoderClient &client, Path path_fs)
static
void
ScanGmeInfo
(
const
gme_info_t
&
info
,
unsigned
song_num
,
int
track_count
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
if
(
info
.
play_length
>
0
)
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
::
FromMS
(
info
.
play_length
));
handler
.
OnDuration
(
SongTime
::
FromMS
(
info
.
play_length
));
if
(
track_count
>
1
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TRACK
,
StringFormat
<
16
>
(
"%u"
,
song_num
+
1
));
handler
.
OnTag
(
TAG_TRACK
,
StringFormat
<
16
>
(
"%u"
,
song_num
+
1
));
if
(
info
.
song
!=
nullptr
)
{
if
(
track_count
>
1
)
{
...
...
@@ -232,33 +230,26 @@ ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count,
StringFormat
<
1024
>
(
"%s (%u/%d)"
,
info
.
song
,
song_num
+
1
,
track_count
);
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
tag_title
);
handler
.
OnTag
(
TAG_TITLE
,
tag_title
);
}
else
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
info
.
song
);
handler
.
OnTag
(
TAG_TITLE
,
info
.
song
);
}
if
(
info
.
author
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_ARTIST
,
info
.
author
);
handler
.
OnTag
(
TAG_ARTIST
,
info
.
author
);
if
(
info
.
game
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_ALBUM
,
info
.
game
);
handler
.
OnTag
(
TAG_ALBUM
,
info
.
game
);
if
(
info
.
comment
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_COMMENT
,
info
.
comment
);
handler
.
OnTag
(
TAG_COMMENT
,
info
.
comment
);
if
(
info
.
copyright
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_DATE
,
info
.
copyright
);
handler
.
OnTag
(
TAG_DATE
,
info
.
copyright
);
}
static
bool
ScanMusicEmu
(
Music_Emu
*
emu
,
unsigned
song_num
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
ScanMusicEmu
(
Music_Emu
*
emu
,
unsigned
song_num
,
TagHandler
&
handler
)
noexcept
{
gme_info_t
*
ti
;
const
char
*
gme_err
=
gme_track_info
(
emu
,
&
ti
,
song_num
);
...
...
@@ -271,14 +262,12 @@ ScanMusicEmu(Music_Emu *emu, unsigned song_num,
AtScopeExit
(
ti
)
{
gme_free_info
(
ti
);
};
ScanGmeInfo
(
*
ti
,
song_num
,
gme_track_count
(
emu
),
handler
,
handler_ctx
);
ScanGmeInfo
(
*
ti
,
song_num
,
gme_track_count
(
emu
),
handler
);
return
true
;
}
static
bool
gme_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
gme_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
const
auto
container
=
ParseContainerPath
(
path_fs
);
...
...
@@ -289,7 +278,7 @@ gme_scan_file(Path path_fs,
AtScopeExit
(
emu
)
{
gme_delete
(
emu
);
};
return
ScanMusicEmu
(
emu
,
container
.
track
,
handler
,
handler_ctx
);
return
ScanMusicEmu
(
emu
,
container
.
track
,
handler
);
}
static
std
::
forward_list
<
DetachedSong
>
...
...
@@ -316,8 +305,8 @@ gme_container_scan(Path path_fs)
auto
tail
=
list
.
before_begin
();
for
(
unsigned
i
=
0
;
i
<
num_songs
;
++
i
)
{
ScanMusicEmu
(
emu
,
i
,
add_tag_handler
,
&
tag_builder
);
AddTagHandler
h
(
tag_builder
);
ScanMusicEmu
(
emu
,
i
,
h
);
const
auto
track_name
=
StringFormat
<
64
>
(
SUBTUNE_PREFIX
"%03u.%s"
,
i
+
1
,
...
...
src/decoder/plugins/MadDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -1062,16 +1062,14 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
}
static
bool
mad_decoder_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
mad_decoder_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
const
auto
result
=
mad_decoder_total_file_time
(
is
);
if
(
!
result
.
first
)
return
false
;
if
(
!
result
.
second
.
IsNegative
())
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
result
.
second
));
handler
.
OnDuration
(
SongTime
(
result
.
second
));
return
true
;
}
...
...
src/decoder/plugins/MikmodDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -185,8 +185,7 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
}
static
bool
mikmod_decoder_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
mikmod_decoder_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
/* deconstify the path because libmikmod wants a non-const
string pointer */
...
...
@@ -204,8 +203,7 @@ mikmod_decoder_scan_file(Path path_fs,
char
*
title
=
Player_LoadTitle
(
path2
);
if
(
title
!=
nullptr
)
{
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
title
);
handler
.
OnTag
(
TAG_TITLE
,
title
);
#if (LIBMIKMOD_VERSION >= 0x030200)
MikMod_free
(
title
);
#else
...
...
src/decoder/plugins/ModplugDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -175,20 +175,17 @@ mod_decode(DecoderClient &client, InputStream &is)
}
static
bool
modplug_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
modplug_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
ModPlugFile
*
f
=
LoadModPlugFile
(
nullptr
,
is
);
if
(
f
==
nullptr
)
return
false
;
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
::
FromMS
(
ModPlug_GetLength
(
f
)));
handler
.
OnDuration
(
SongTime
::
FromMS
(
ModPlug_GetLength
(
f
)));
const
char
*
title
=
ModPlug_GetName
(
f
);
if
(
title
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
title
);
handler
.
OnTag
(
TAG_TITLE
,
title
);
ModPlug_Unload
(
f
);
...
...
src/decoder/plugins/MpcdecDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -257,14 +257,13 @@ mpcdec_get_file_duration(InputStream &is)
}
static
bool
mpcdec_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
mpcdec_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
const
auto
duration
=
mpcdec_get_file_duration
(
is
);
if
(
duration
.
IsNegative
())
return
false
;
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
duration
));
handler
.
OnDuration
(
SongTime
(
duration
));
return
true
;
}
...
...
src/decoder/plugins/Mpg123DecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -279,8 +279,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
}
static
bool
mpd_mpg123_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
mpd_mpg123_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
int
error
;
mpg123_handle
*
const
handle
=
mpg123_new
(
nullptr
,
&
error
);
...
...
@@ -316,7 +315,7 @@ mpd_mpg123_scan_file(Path path_fs,
SongTime
::
FromScale
<
uint64_t
>
(
num_samples
,
audio_format
.
sample_rate
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
duration
);
handler
.
OnDuration
(
duration
);
return
true
;
}
...
...
src/decoder/plugins/OpusDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -207,10 +207,9 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
rgi
.
Clear
();
TagBuilder
tag_builder
;
AddTagHandler
h
(
tag_builder
);
if
(
ScanOpusTags
(
packet
.
packet
,
packet
.
bytes
,
&
rgi
,
add_tag_handler
,
&
tag_builder
)
&&
if
(
ScanOpusTags
(
packet
.
packet
,
packet
.
bytes
,
&
rgi
,
h
)
&&
!
tag_builder
.
empty
())
{
client
.
SubmitReplayGain
(
&
rgi
);
...
...
@@ -314,7 +313,7 @@ ReadAndParseOpusHead(OggSyncState &sync, OggStreamState &stream,
static
bool
ReadAndVisitOpusTags
(
OggSyncState
&
sync
,
OggStreamState
&
stream
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
{
ogg_packet
packet
;
...
...
@@ -322,12 +321,12 @@ ReadAndVisitOpusTags(OggSyncState &sync, OggStreamState &stream,
IsOpusTags
(
packet
)
&&
ScanOpusTags
(
packet
.
packet
,
packet
.
bytes
,
nullptr
,
handler
,
handler_ctx
);
handler
);
}
static
void
VisitOpusDuration
(
InputStream
&
is
,
OggSyncState
&
sync
,
OggStreamState
&
stream
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
{
ogg_packet
packet
;
...
...
@@ -335,13 +334,12 @@ VisitOpusDuration(InputStream &is, OggSyncState &sync, OggStreamState &stream,
const
auto
duration
=
SongTime
::
FromScale
<
uint64_t
>
(
packet
.
granulepos
,
opus_sample_rate
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
duration
);
handler
.
OnDuration
(
duration
);
}
}
static
bool
mpd_opus_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
mpd_opus_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
InputStreamReader
reader
(
is
);
OggSyncState
oy
(
reader
);
...
...
@@ -354,10 +352,10 @@ mpd_opus_scan_stream(InputStream &is,
unsigned
channels
;
if
(
!
ReadAndParseOpusHead
(
oy
,
os
,
channels
)
||
!
ReadAndVisitOpusTags
(
oy
,
os
,
handler
,
handler_ctx
))
!
ReadAndVisitOpusTags
(
oy
,
os
,
handler
))
return
false
;
VisitOpusDuration
(
is
,
oy
,
os
,
handler
,
handler_ctx
);
VisitOpusDuration
(
is
,
oy
,
os
,
handler
);
return
true
;
}
...
...
src/decoder/plugins/OpusTags.cxx
View file @
3d3a1232
...
...
@@ -43,7 +43,7 @@ ParseOpusTagName(const char *name) noexcept
static
void
ScanOneOpusTag
(
const
char
*
name
,
const
char
*
value
,
ReplayGainInfo
*
rgi
,
const
TagHandler
&
handler
,
void
*
ctx
)
TagHandler
&
handler
)
noexcept
{
if
(
rgi
!=
nullptr
&&
strcmp
(
name
,
"R128_TRACK_GAIN"
)
==
0
)
{
/* R128_TRACK_GAIN is a Q7.8 fixed point number in
...
...
@@ -63,25 +63,25 @@ ScanOneOpusTag(const char *name, const char *value,
rgi
->
album
.
gain
=
double
(
l
)
/
256.
;
}
tag_handler_invoke_pair
(
handler
,
ctx
,
name
,
value
);
handler
.
OnPair
(
name
,
value
);
if
(
handler
.
tag
!=
nullptr
)
{
if
(
handler
.
WantTag
()
)
{
TagType
t
=
ParseOpusTagName
(
name
);
if
(
t
!=
TAG_NUM_OF_ITEM_TYPES
)
tag_handler_invoke_tag
(
handler
,
ctx
,
t
,
value
);
handler
.
OnTag
(
t
,
value
);
}
}
bool
ScanOpusTags
(
const
void
*
data
,
size_t
size
,
ReplayGainInfo
*
rgi
,
const
TagHandler
&
handler
,
void
*
ctx
)
TagHandler
&
handler
)
noexcept
{
OpusReader
r
(
data
,
size
);
if
(
!
r
.
Expect
(
"OpusTags"
,
8
))
return
false
;
if
(
handler
.
pair
==
nullptr
&&
handler
.
tag
==
nullptr
)
if
(
!
handler
.
WantPair
()
&&
!
handler
.
WantTag
()
)
return
true
;
if
(
!
r
.
SkipString
())
...
...
@@ -100,7 +100,7 @@ ScanOpusTags(const void *data, size_t size,
if
(
eq
!=
nullptr
&&
eq
>
p
)
{
*
eq
=
0
;
ScanOneOpusTag
(
p
,
eq
+
1
,
rgi
,
handler
,
ctx
);
ScanOneOpusTag
(
p
,
eq
+
1
,
rgi
,
handler
);
}
delete
[]
p
;
...
...
src/decoder/plugins/OpusTags.hxx
View file @
3d3a1232
...
...
@@ -25,11 +25,11 @@
#include <stddef.h>
struct
ReplayGainInfo
;
struct
TagHandler
;
class
TagHandler
;
bool
ScanOpusTags
(
const
void
*
data
,
size_t
size
,
ReplayGainInfo
*
rgi
,
const
TagHandler
&
handler
,
void
*
ctx
)
;
TagHandler
&
handler
)
noexcept
;
#endif
src/decoder/plugins/SidplayDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -405,7 +405,7 @@ GetInfoString(const SidTuneInfo &info, unsigned i) noexcept
static
void
ScanSidTuneInfo
(
const
SidTuneInfo
&
info
,
unsigned
track
,
unsigned
n_tracks
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
/* title */
const
char
*
title
=
GetInfoString
(
info
,
0
);
...
...
@@ -416,31 +416,26 @@ ScanSidTuneInfo(const SidTuneInfo &info, unsigned track, unsigned n_tracks,
const
auto
tag_title
=
StringFormat
<
1024
>
(
"%s (%u/%u)"
,
title
,
track
,
n_tracks
);
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
tag_title
);
handler
.
OnTag
(
TAG_TITLE
,
tag_title
);
}
else
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TITLE
,
title
);
handler
.
OnTag
(
TAG_TITLE
,
title
);
/* artist */
const
char
*
artist
=
GetInfoString
(
info
,
1
);
if
(
artist
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_ARTIST
,
artist
);
handler
.
OnTag
(
TAG_ARTIST
,
artist
);
/* date */
const
char
*
date
=
GetInfoString
(
info
,
2
);
if
(
date
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_DATE
,
date
);
handler
.
OnTag
(
TAG_DATE
,
date
);
/* track */
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_TRACK
,
StringFormat
<
16
>
(
"%u"
,
track
));
handler
.
OnTag
(
TAG_TRACK
,
StringFormat
<
16
>
(
"%u"
,
track
));
}
static
bool
sidplay_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
sidplay_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
const
auto
container
=
ParseContainerPath
(
path_fs
);
const
unsigned
song_num
=
container
.
track
;
...
...
@@ -463,13 +458,12 @@ sidplay_scan_file(Path path_fs,
const
unsigned
n_tracks
=
info
.
songs
;
#endif
ScanSidTuneInfo
(
info
,
song_num
,
n_tracks
,
handler
,
handler_ctx
);
ScanSidTuneInfo
(
info
,
song_num
,
n_tracks
,
handler
);
/* time */
const
auto
duration
=
get_song_length
(
tune
);
if
(
!
duration
.
IsNegative
())
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
duration
));
handler
.
OnDuration
(
SongTime
(
duration
));
return
true
;
}
...
...
@@ -506,8 +500,8 @@ sidplay_container_scan(Path path_fs)
for
(
unsigned
i
=
1
;
i
<=
n_tracks
;
++
i
)
{
tune
.
selectSong
(
i
);
ScanSidTuneInfo
(
info
,
i
,
n_tracks
,
add_tag_handler
,
&
tag_builder
);
AddTagHandler
h
(
tag_builder
);
ScanSidTuneInfo
(
info
,
i
,
n_tracks
,
h
);
char
track_name
[
32
];
/* Construct container/tune path names, eg.
...
...
src/decoder/plugins/SndfileDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -240,11 +240,11 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
static
void
sndfile_handle_tag
(
SNDFILE
*
sf
,
int
str
,
TagType
tag
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
char
*
value
=
sf_get_string
(
sf
,
str
);
if
(
value
!=
nullptr
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
tag
,
value
);
handler
.
OnTag
(
tag
,
value
);
}
static
constexpr
struct
{
...
...
@@ -261,8 +261,7 @@ static constexpr struct {
};
static
bool
sndfile_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
sndfile_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
SF_INFO
info
;
...
...
@@ -280,11 +279,10 @@ sndfile_scan_stream(InputStream &is,
return
false
;
}
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
sndfile_duration
(
info
));
handler
.
OnDuration
(
sndfile_duration
(
info
));
for
(
auto
i
:
sndfile_tags
)
sndfile_handle_tag
(
sf
,
i
.
str
,
i
.
tag
,
handler
,
handler_ctx
);
sndfile_handle_tag
(
sf
,
i
.
str
,
i
.
tag
,
handler
);
sf_close
(
sf
);
...
...
src/decoder/plugins/VorbisDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -348,7 +348,7 @@ static void
VisitVorbisDuration
(
InputStream
&
is
,
OggSyncState
&
sync
,
OggStreamState
&
stream
,
unsigned
sample_rate
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
ogg_packet
packet
;
...
...
@@ -358,12 +358,11 @@ VisitVorbisDuration(InputStream &is,
const
auto
duration
=
SongTime
::
FromScale
<
uint64_t
>
(
packet
.
granulepos
,
sample_rate
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
duration
);
handler
.
OnDuration
(
duration
);
}
static
bool
vorbis_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
vorbis_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
/* initialize libogg */
...
...
@@ -397,12 +396,11 @@ vorbis_scan_stream(InputStream &is,
/* visit the Vorbis comments we just read */
vorbis_comments_scan
(
vc
.
user_comments
,
handler
,
handler_ctx
);
vorbis_comments_scan
(
vc
.
user_comments
,
handler
);
/* check the song duration by locating the e_o_s packet */
VisitVorbisDuration
(
is
,
sync
,
stream
,
vi
.
rate
,
handler
,
handler_ctx
);
VisitVorbisDuration
(
is
,
sync
,
stream
,
vi
.
rate
,
handler
);
return
true
;
}
...
...
src/decoder/plugins/WavpackDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -578,8 +578,7 @@ wavpack_filedecode(DecoderClient &client, Path path_fs)
* Reads metainfo from the specified file.
*/
static
bool
wavpack_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
wavpack_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
WavpackContext
*
wpc
;
...
...
@@ -595,14 +594,13 @@ wavpack_scan_file(Path path_fs,
const
auto
duration
=
GetDuration
(
wpc
);
if
(
!
duration
.
IsNegative
())
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
duration
));
handler
.
OnDuration
(
SongTime
(
duration
));
return
true
;
}
static
bool
wavpack_scan_stream
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
wavpack_scan_stream
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
WavpackInput
isp
(
nullptr
,
is
);
...
...
@@ -620,7 +618,7 @@ wavpack_scan_stream(InputStream &is,
const
auto
duration
=
GetDuration
(
wpc
);
if
(
!
duration
.
IsNegative
())
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
SongTime
(
duration
));
handler
.
OnDuration
(
SongTime
(
duration
));
return
true
;
}
...
...
src/decoder/plugins/WildmidiDecoderPlugin.cxx
View file @
3d3a1232
...
...
@@ -126,8 +126,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
}
static
bool
wildmidi_scan_file
(
Path
path_fs
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
noexcept
wildmidi_scan_file
(
Path
path_fs
,
TagHandler
&
handler
)
noexcept
{
midi
*
wm
=
WildMidi_Open
(
path_fs
.
c_str
());
if
(
wm
==
nullptr
)
...
...
@@ -142,7 +141,7 @@ wildmidi_scan_file(Path path_fs,
const
auto
duration
=
SongTime
::
FromScale
<
uint64_t
>
(
info
->
approx_total_samples
,
WILDMIDI_SAMPLE_RATE
);
tag_handler_invoke_duration
(
handler
,
handler_ctx
,
duration
);
handler
.
OnDuration
(
duration
);
WildMidi_Close
(
wm
);
...
...
src/lib/xiph/VorbisComments.cxx
View file @
3d3a1232
...
...
@@ -53,13 +53,13 @@ vorbis_comments_to_replay_gain(ReplayGainInfo &rgi, char **comments) noexcept
static
bool
vorbis_copy_comment
(
const
char
*
comment
,
const
char
*
name
,
TagType
tag_type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
char
*
value
;
value
=
vorbis_comment_value
(
comment
,
name
);
if
(
value
!=
nullptr
)
{
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
tag_type
,
value
);
handler
.
OnTag
(
tag_type
,
value
);
return
true
;
}
...
...
@@ -67,36 +67,31 @@ vorbis_copy_comment(const char *comment,
}
static
void
vorbis_scan_comment
(
const
char
*
comment
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
vorbis_scan_comment
(
const
char
*
comment
,
TagHandler
&
handler
)
noexcept
{
if
(
handler
.
pair
!=
nullptr
)
{
if
(
handler
.
WantPair
()
)
{
const
DivideString
split
(
comment
,
'='
);
if
(
split
.
IsDefined
()
&&
!
split
.
empty
())
tag_handler_invoke_pair
(
handler
,
handler_ctx
,
split
.
GetFirst
(),
split
.
GetSecond
());
handler
.
OnPair
(
split
.
GetFirst
(),
split
.
GetSecond
());
}
for
(
const
struct
tag_table
*
i
=
xiph_tags
;
i
->
name
!=
nullptr
;
++
i
)
if
(
vorbis_copy_comment
(
comment
,
i
->
name
,
i
->
type
,
handler
,
handler_ctx
))
handler
))
return
;
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
++
i
)
if
(
vorbis_copy_comment
(
comment
,
tag_item_names
[
i
],
TagType
(
i
),
handler
,
handler_ctx
))
handler
))
return
;
}
void
vorbis_comments_scan
(
char
**
comments
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
vorbis_comments_scan
(
char
**
comments
,
TagHandler
&
handler
)
noexcept
{
while
(
*
comments
)
vorbis_scan_comment
(
*
comments
++
,
handler
,
handler_ctx
);
vorbis_scan_comment
(
*
comments
++
,
handler
);
}
...
...
@@ -104,7 +99,8 @@ std::unique_ptr<Tag>
vorbis_comments_to_tag
(
char
**
comments
)
noexcept
{
TagBuilder
tag_builder
;
vorbis_comments_scan
(
comments
,
add_tag_handler
,
&
tag_builder
);
AddTagHandler
h
(
tag_builder
);
vorbis_comments_scan
(
comments
,
h
);
return
tag_builder
.
empty
()
?
nullptr
:
tag_builder
.
CommitNew
();
...
...
src/lib/xiph/VorbisComments.hxx
View file @
3d3a1232
...
...
@@ -25,15 +25,14 @@
#include <memory>
struct
ReplayGainInfo
;
struct
TagHandler
;
class
TagHandler
;
struct
Tag
;
bool
vorbis_comments_to_replay_gain
(
ReplayGainInfo
&
rgi
,
char
**
comments
)
noexcept
;
void
vorbis_comments_scan
(
char
**
comments
,
const
TagHandler
&
handler
,
void
*
handler_ctx
);
vorbis_comments_scan
(
char
**
comments
,
TagHandler
&
handler
)
noexcept
;
std
::
unique_ptr
<
Tag
>
vorbis_comments_to_tag
(
char
**
comments
)
noexcept
;
...
...
src/playlist/plugins/EmbeddedCuePlaylistPlugin.cxx
View file @
3d3a1232
...
...
@@ -71,22 +71,23 @@ public:
virtual
std
::
unique_ptr
<
DetachedSong
>
NextSong
()
override
;
};
static
void
embcue_tag_pair
(
const
char
*
name
,
const
char
*
value
,
void
*
ctx
)
{
EmbeddedCuePlaylist
*
playlist
=
(
EmbeddedCuePlaylist
*
)
ctx
;
class
ExtractCuesheetTagHandler
final
:
public
NullTagHandler
{
public
:
std
::
string
cuesheet
;
if
(
playlist
->
cuesheet
.
empty
()
&&
StringEqualsCaseASCII
(
name
,
"cuesheet"
))
playlist
->
cuesheet
=
value
;
}
ExtractCuesheetTagHandler
()
noexcept
:
NullTagHandler
(
WANT_PAIR
)
{}
static
constexpr
TagHandler
embcue_tag_handler
=
{
nullptr
,
nullptr
,
embcue_tag_pair
,
void
OnPair
(
const
char
*
key
,
const
char
*
value
)
noexcept
override
;
};
void
ExtractCuesheetTagHandler
::
OnPair
(
const
char
*
name
,
const
char
*
value
)
noexcept
{
if
(
cuesheet
.
empty
()
&&
StringEqualsCaseASCII
(
name
,
"cuesheet"
))
cuesheet
=
value
;
}
static
std
::
unique_ptr
<
SongEnumerator
>
embcue_playlist_open_uri
(
const
char
*
uri
,
gcc_unused
Mutex
&
mutex
)
...
...
@@ -97,18 +98,21 @@ embcue_playlist_open_uri(const char *uri,
const
auto
path_fs
=
AllocatedPath
::
FromUTF8Throw
(
uri
);
auto
playlist
=
std
::
make_unique
<
EmbeddedCuePlaylist
>
();
tag_file_scan
(
path_fs
,
embcue_tag_handler
,
playlist
.
get
());
if
(
playlist
->
cuesheet
.
empty
())
ScanGenericTags
(
path_fs
,
embcue_tag_handler
,
playlist
.
get
());
ExtractCuesheetTagHandler
extract_cuesheet
;
tag_file_scan
(
path_fs
,
extract_cuesheet
);
if
(
extract_cuesheet
.
cuesheet
.
empty
())
ScanGenericTags
(
path_fs
,
extract_cuesheet
);
if
(
playlist
->
cuesheet
.
empty
())
if
(
extract_cuesheet
.
cuesheet
.
empty
())
/* no "CUESHEET" tag found */
return
nullptr
;
auto
playlist
=
std
::
make_unique
<
EmbeddedCuePlaylist
>
();
playlist
->
filename
=
PathTraitsUTF8
::
GetBase
(
uri
);
playlist
->
cuesheet
=
std
::
move
(
extract_cuesheet
.
cuesheet
);
playlist
->
next
=
&
playlist
->
cuesheet
[
0
];
playlist
->
parser
=
new
CueParser
();
...
...
src/tag/ApeTag.cxx
View file @
3d3a1232
...
...
@@ -76,7 +76,7 @@ ForEachValue(const char *value, const char *end, C &&callback)
static
bool
tag_ape_import_item
(
unsigned
long
flags
,
const
char
*
key
,
StringView
value
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
/* we only care about utf-8 text tags */
if
((
flags
&
(
0x3
<<
1
))
!=
0
)
...
...
@@ -85,36 +85,31 @@ tag_ape_import_item(unsigned long flags,
const
auto
begin
=
value
.
begin
();
const
auto
end
=
value
.
end
();
if
(
handler
.
pair
!=
nullptr
)
ForEachValue
(
begin
,
end
,
[
handler
,
handler_ctx
,
key
](
const
char
*
_value
)
{
handler
.
pair
(
key
,
_value
,
handler_ctx
);
if
(
handler
.
WantPair
())
ForEachValue
(
begin
,
end
,
[
&
handler
,
key
](
const
char
*
_value
)
{
handler
.
OnPair
(
key
,
_value
);
});
TagType
type
=
tag_ape_name_parse
(
key
);
if
(
type
==
TAG_NUM_OF_ITEM_TYPES
)
return
false
;
ForEachValue
(
begin
,
end
,
[
handler
,
handler_ctx
,
type
](
const
char
*
_value
)
{
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
_value
);
ForEachValue
(
begin
,
end
,
[
&
handler
,
type
](
const
char
*
_value
)
{
handler
.
OnTag
(
type
,
_value
);
});
return
true
;
}
bool
tag_ape_scan2
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
tag_ape_scan2
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
bool
recognized
=
false
;
auto
callback
=
[
handler
,
handler_ctx
,
&
recognized
]
auto
callback
=
[
&
handler
,
&
recognized
]
(
unsigned
long
flags
,
const
char
*
key
,
StringView
value
)
{
recognized
|=
tag_ape_import_item
(
flags
,
key
,
value
,
handler
,
handler_ctx
);
recognized
|=
tag_ape_import_item
(
flags
,
key
,
value
,
handler
);
return
true
;
};
...
...
src/tag/ApeTag.hxx
View file @
3d3a1232
...
...
@@ -20,10 +20,8 @@
#ifndef MPD_APE_TAG_HXX
#define MPD_APE_TAG_HXX
#include "Table.hxx"
class
InputStream
;
struct
TagHandler
;
class
TagHandler
;
/**
* Scan the APE tags of a stream.
...
...
@@ -31,7 +29,6 @@ struct TagHandler;
* @param path_fs the path of the file in filesystem encoding
*/
bool
tag_ape_scan2
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
);
tag_ape_scan2
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
;
#endif
src/tag/Generic.cxx
View file @
3d3a1232
...
...
@@ -30,9 +30,9 @@
#include <exception>
bool
ScanGenericTags
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
ctx
)
ScanGenericTags
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
if
(
tag_ape_scan2
(
is
,
handler
,
ctx
))
if
(
tag_ape_scan2
(
is
,
handler
))
return
true
;
#ifdef ENABLE_ID3TAG
...
...
@@ -42,19 +42,19 @@ ScanGenericTags(InputStream &is, const TagHandler &handler, void *ctx)
return
false
;
}
return
tag_id3_scan
(
is
,
handler
,
ctx
);
return
tag_id3_scan
(
is
,
handler
);
#else
return
false
;
#endif
}
bool
ScanGenericTags
(
Path
path
,
const
TagHandler
&
handler
,
void
*
ctx
)
ScanGenericTags
(
Path
path
,
TagHandler
&
handler
)
noexcept
try
{
Mutex
mutex
;
auto
is
=
OpenLocalInputStream
(
path
,
mutex
);
return
ScanGenericTags
(
*
is
,
handler
,
ctx
);
return
ScanGenericTags
(
*
is
,
handler
);
}
catch
(...)
{
LogError
(
std
::
current_exception
());
return
false
;
...
...
src/tag/Generic.hxx
View file @
3d3a1232
...
...
@@ -22,7 +22,7 @@
#include "check.h"
struct
TagHandler
;
class
TagHandler
;
class
InputStream
;
class
Path
;
...
...
@@ -31,12 +31,12 @@ class Path;
* stream does not need to be rewound.
*/
bool
ScanGenericTags
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
ctx
)
;
ScanGenericTags
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
;
/**
* Attempts to scan APE or ID3 tags from the specified file.
*/
bool
ScanGenericTags
(
Path
path
,
const
TagHandler
&
handler
,
void
*
ctx
)
;
ScanGenericTags
(
Path
path
,
TagHandler
&
handler
)
noexcept
;
#endif
src/tag/Handler.cxx
View file @
3d3a1232
...
...
@@ -25,19 +25,15 @@
#include <stdlib.h>
static
void
add_tag_duration
(
SongTime
duration
,
void
*
ctx
)
void
AddTagHandler
::
OnDuration
(
SongTime
duration
)
noexcept
{
TagBuilder
&
tag
=
*
(
TagBuilder
*
)
ctx
;
tag
.
SetDuration
(
duration
);
}
static
void
add_tag_tag
(
TagType
type
,
const
char
*
value
,
void
*
ctx
)
void
AddTagHandler
::
OnTag
(
TagType
type
,
const
char
*
value
)
noexcept
{
TagBuilder
&
tag
=
*
(
TagBuilder
*
)
ctx
;
if
(
type
==
TAG_TRACK
||
type
==
TAG_DISC
)
{
/* filter out this extra data and leading zeroes */
char
*
end
;
...
...
@@ -48,24 +44,10 @@ add_tag_tag(TagType type, const char *value, void *ctx)
tag
.
AddItem
(
type
,
value
);
}
const
TagHandler
add_tag_handler
=
{
add_tag_duration
,
add_tag_tag
,
nullptr
,
};
static
void
full_tag_pair
(
const
char
*
name
,
gcc_unused
const
char
*
value
,
void
*
ctx
)
void
FullTagHandler
::
OnPair
(
const
char
*
name
,
gcc_unused
const
char
*
value
)
noexcept
{
TagBuilder
&
tag
=
*
(
TagBuilder
*
)
ctx
;
if
(
StringEqualsCaseASCII
(
name
,
"cuesheet"
))
tag
.
SetHasPlaylist
(
true
);
}
const
TagHandler
full_tag_handler
=
{
add_tag_duration
,
add_tag_tag
,
full_tag_pair
,
};
src/tag/Handler.hxx
View file @
3d3a1232
...
...
@@ -23,19 +23,45 @@
#include "check.h"
#include "Type.h"
#include "Chrono.hxx"
#include "Compiler.h"
#include <assert.h>
class
TagBuilder
;
/**
* A
callback tabl
e for receiving metadata of a song.
* A
n interfac
e for receiving metadata of a song.
*/
struct
TagHandler
{
class
TagHandler
{
const
unsigned
want_mask
;
public
:
static
constexpr
unsigned
WANT_DURATION
=
0x1
;
static
constexpr
unsigned
WANT_TAG
=
0x2
;
static
constexpr
unsigned
WANT_PAIR
=
0x4
;
explicit
TagHandler
(
unsigned
_want_mask
)
noexcept
:
want_mask
(
_want_mask
)
{}
TagHandler
(
const
TagHandler
&
)
=
delete
;
TagHandler
&
operator
=
(
const
TagHandler
&
)
=
delete
;
bool
WantDuration
()
const
noexcept
{
return
want_mask
&
WANT_DURATION
;
}
bool
WantTag
()
const
noexcept
{
return
want_mask
&
WANT_TAG
;
}
bool
WantPair
()
const
noexcept
{
return
want_mask
&
WANT_PAIR
;
}
/**
* Declare the duration of a song. Do not call
* this when the duration could not be determined, because
* there is no magic value for "unknown duration".
*/
v
oid
(
*
duration
)(
SongTime
duration
,
void
*
ctx
)
;
v
irtual
void
OnDuration
(
SongTime
duration
)
noexcept
=
0
;
/**
* A tag has been read.
...
...
@@ -43,56 +69,57 @@ struct TagHandler {
* @param the value of the tag; the pointer will become
* invalid after returning
*/
v
oid
(
*
tag
)(
TagType
type
,
const
char
*
value
,
void
*
ctx
)
;
v
irtual
void
OnTag
(
TagType
type
,
const
char
*
value
)
noexcept
=
0
;
/**
* A name-value pair has been read. It is the codec specific
* representation of tags.
*/
v
oid
(
*
pair
)(
const
char
*
key
,
const
char
*
value
,
void
*
ctx
)
;
v
irtual
void
OnPair
(
const
char
*
key
,
const
char
*
value
)
noexcept
=
0
;
};
static
inline
void
tag_handler_invoke_duration
(
const
TagHandler
&
handler
,
void
*
ctx
,
SongTime
duration
)
noexcept
{
if
(
handler
.
duration
!=
nullptr
)
handler
.
duration
(
duration
,
ctx
);
}
static
inline
void
tag_handler_invoke_tag
(
const
TagHandler
&
handler
,
void
*
ctx
,
TagType
type
,
const
char
*
value
)
noexcept
{
assert
((
unsigned
)
type
<
TAG_NUM_OF_ITEM_TYPES
);
assert
(
value
!=
nullptr
);
if
(
handler
.
tag
!=
nullptr
)
handler
.
tag
(
type
,
value
,
ctx
);
}
static
inline
void
tag_handler_invoke_pair
(
const
TagHandler
&
handler
,
void
*
ctx
,
const
char
*
name
,
const
char
*
value
)
noexcept
{
assert
(
name
!=
nullptr
);
assert
(
value
!=
nullptr
);
if
(
handler
.
pair
!=
nullptr
)
handler
.
pair
(
name
,
value
,
ctx
);
}
class
NullTagHandler
:
public
TagHandler
{
public
:
explicit
NullTagHandler
(
unsigned
_want_mask
)
noexcept
:
TagHandler
(
_want_mask
)
{}
void
OnDuration
(
gcc_unused
SongTime
duration
)
noexcept
override
{}
void
OnTag
(
gcc_unused
TagType
type
,
gcc_unused
const
char
*
value
)
noexcept
override
{}
void
OnPair
(
gcc_unused
const
char
*
key
,
gcc_unused
const
char
*
value
)
noexcept
override
{}
};
/**
* This #TagHandler implementation adds tag values to a #TagBuilder
object
*
(casted from the context pointer)
.
* This #TagHandler implementation adds tag values to a #TagBuilder
*
object
.
*/
extern
const
TagHandler
add_tag_handler
;
class
AddTagHandler
:
public
NullTagHandler
{
protected
:
TagBuilder
&
tag
;
AddTagHandler
(
unsigned
_want_mask
,
TagBuilder
&
_builder
)
noexcept
:
NullTagHandler
(
_want_mask
),
tag
(
_builder
)
{}
public
:
explicit
AddTagHandler
(
TagBuilder
&
_builder
)
noexcept
:
AddTagHandler
(
WANT_DURATION
|
WANT_TAG
,
_builder
)
{}
void
OnDuration
(
SongTime
duration
)
noexcept
override
;
void
OnTag
(
TagType
type
,
const
char
*
value
)
noexcept
override
;
};
/**
* This #TagHandler implementation adds tag values to a #TagBuilder object
* (casted from the context pointer), and supports the has_playlist
* attribute.
*/
extern
const
TagHandler
full_tag_handler
;
class
FullTagHandler
:
public
AddTagHandler
{
public
:
explicit
FullTagHandler
(
TagBuilder
&
_builder
)
noexcept
:
AddTagHandler
(
WANT_DURATION
|
WANT_TAG
|
WANT_PAIR
,
_builder
)
{}
void
OnPair
(
const
char
*
key
,
const
char
*
value
)
noexcept
override
;
};
#endif
src/tag/Id3Scan.cxx
View file @
3d3a1232
...
...
@@ -100,7 +100,7 @@ import_id3_string(const id3_ucs4_t *ucs4)
static
void
tag_id3_import_text_frame
(
const
struct
id3_frame
*
frame
,
TagType
type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
if
(
frame
->
nfields
!=
2
)
return
;
...
...
@@ -133,8 +133,7 @@ tag_id3_import_text_frame(const struct id3_frame *frame,
AtScopeExit
(
utf8
)
{
free
(
utf8
);
};
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
(
const
char
*
)
utf8
);
handler
.
OnTag
(
type
,
(
const
char
*
)
utf8
);
}
}
...
...
@@ -144,13 +143,13 @@ tag_id3_import_text_frame(const struct id3_frame *frame,
*/
static
void
tag_id3_import_text
(
struct
id3_tag
*
tag
,
const
char
*
id
,
TagType
type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
struct
id3_frame
*
frame
;
for
(
unsigned
i
=
0
;
(
frame
=
id3_tag_findframe
(
tag
,
id
,
i
))
!=
nullptr
;
++
i
)
tag_id3_import_text_frame
(
frame
,
type
,
handler
,
handler_ctx
);
handler
);
}
/**
...
...
@@ -164,8 +163,7 @@ tag_id3_import_text(struct id3_tag *tag, const char *id, TagType type,
*/
static
void
tag_id3_import_comment_frame
(
const
struct
id3_frame
*
frame
,
TagType
type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
if
(
frame
->
nfields
!=
4
)
return
;
...
...
@@ -185,7 +183,7 @@ tag_id3_import_comment_frame(const struct id3_frame *frame, TagType type,
AtScopeExit
(
utf8
)
{
free
(
utf8
);
};
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
(
const
char
*
)
utf8
);
handler
.
OnTag
(
type
,
(
const
char
*
)
utf8
);
}
/**
...
...
@@ -194,13 +192,13 @@ tag_id3_import_comment_frame(const struct id3_frame *frame, TagType type,
*/
static
void
tag_id3_import_comment
(
struct
id3_tag
*
tag
,
const
char
*
id
,
TagType
type
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
const
struct
id3_frame
*
frame
;
for
(
unsigned
i
=
0
;
(
frame
=
id3_tag_findframe
(
tag
,
id
,
i
))
!=
nullptr
;
++
i
)
tag_id3_import_comment_frame
(
frame
,
type
,
handler
,
handler_ctx
);
handler
);
}
/**
...
...
@@ -220,8 +218,7 @@ tag_id3_parse_txxx_name(const char *name) noexcept
*/
static
void
tag_id3_import_musicbrainz
(
struct
id3_tag
*
id3_tag
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
for
(
unsigned
i
=
0
;;
++
i
)
{
const
id3_frame
*
frame
=
id3_tag_findframe
(
id3_tag
,
"TXXX"
,
i
);
...
...
@@ -240,15 +237,12 @@ tag_id3_import_musicbrainz(struct id3_tag *id3_tag,
AtScopeExit
(
value
)
{
free
(
value
);
};
tag_handler_invoke_pair
(
handler
,
handler_ctx
,
(
const
char
*
)
name
,
(
const
char
*
)
value
);
handler
.
OnPair
((
const
char
*
)
name
,
(
const
char
*
)
value
);
TagType
type
=
tag_id3_parse_txxx_name
((
const
char
*
)
name
);
if
(
type
!=
TAG_NUM_OF_ITEM_TYPES
)
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
type
,
(
const
char
*
)
value
);
handler
.
OnTag
(
type
,
(
const
char
*
)
value
);
}
}
...
...
@@ -257,7 +251,7 @@ tag_id3_import_musicbrainz(struct id3_tag *id3_tag,
*/
static
void
tag_id3_import_ufid
(
struct
id3_tag
*
id3_tag
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
TagHandler
&
handler
)
noexcept
{
for
(
unsigned
i
=
0
;;
++
i
)
{
const
id3_frame
*
frame
=
id3_tag_findframe
(
id3_tag
,
"UFID"
,
i
);
...
...
@@ -284,65 +278,63 @@ tag_id3_import_ufid(struct id3_tag *id3_tag,
continue
;
std
::
string
p
((
const
char
*
)
value
,
length
);
tag_handler_invoke_tag
(
handler
,
handler_ctx
,
TAG_MUSICBRAINZ_TRACKID
,
p
.
c_str
());
handler
.
OnTag
(
TAG_MUSICBRAINZ_TRACKID
,
p
.
c_str
());
}
}
void
scan_id3_tag
(
struct
id3_tag
*
tag
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
scan_id3_tag
(
struct
id3_tag
*
tag
,
TagHandler
&
handler
)
noexcept
{
tag_id3_import_text
(
tag
,
ID3_FRAME_ARTIST
,
TAG_ARTIST
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_ALBUM_ARTIST
,
TAG_ALBUM_ARTIST
,
handler
,
handler_ctx
);
TAG_ALBUM_ARTIST
,
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_ARTIST_SORT
,
TAG_ARTIST_SORT
,
handler
,
handler_ctx
);
TAG_ARTIST_SORT
,
handler
);
tag_id3_import_text
(
tag
,
"TSOA"
,
TAG_ALBUM_SORT
,
handler
,
handler_ctx
);
tag_id3_import_text
(
tag
,
"TSOA"
,
TAG_ALBUM_SORT
,
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_ALBUM_ARTIST_SORT
,
TAG_ALBUM_ARTIST_SORT
,
handler
,
handler_ctx
);
TAG_ALBUM_ARTIST_SORT
,
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_TITLE
,
TAG_TITLE
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_ALBUM
,
TAG_ALBUM
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_TRACK
,
TAG_TRACK
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_YEAR
,
TAG_DATE
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_ORIGINAL_RELEASE_DATE
,
TAG_ORIGINAL_DATE
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_GENRE
,
TAG_GENRE
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_COMPOSER
,
TAG_COMPOSER
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
"TPE3"
,
TAG_PERFORMER
,
handler
,
handler_ctx
);
tag_id3_import_text
(
tag
,
"TPE4"
,
TAG_PERFORMER
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
"TPE4"
,
TAG_PERFORMER
,
handler
);
tag_id3_import_comment
(
tag
,
ID3_FRAME_COMMENT
,
TAG_COMMENT
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_text
(
tag
,
ID3_FRAME_DISC
,
TAG_DISC
,
handler
,
handler_ctx
);
handler
);
tag_id3_import_musicbrainz
(
tag
,
handler
,
handler_ctx
);
tag_id3_import_ufid
(
tag
,
handler
,
handler_ctx
);
tag_id3_import_musicbrainz
(
tag
,
handler
);
tag_id3_import_ufid
(
tag
,
handler
);
}
std
::
unique_ptr
<
Tag
>
tag_id3_import
(
struct
id3_tag
*
tag
)
{
TagBuilder
tag_builder
;
scan_id3_tag
(
tag
,
add_tag_handler
,
&
tag_builder
);
AddTagHandler
h
(
tag_builder
);
scan_id3_tag
(
tag
,
h
);
return
tag_builder
.
empty
()
?
nullptr
:
tag_builder
.
CommitNew
();
}
bool
tag_id3_scan
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
)
tag_id3_scan
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
{
UniqueId3Tag
tag
;
...
...
@@ -355,6 +347,6 @@ tag_id3_scan(InputStream &is,
return
false
;
}
scan_id3_tag
(
tag
.
get
(),
handler
,
handler_ctx
);
scan_id3_tag
(
tag
.
get
(),
handler
);
return
true
;
}
src/tag/Id3Scan.hxx
View file @
3d3a1232
...
...
@@ -25,13 +25,12 @@
#include <memory>
class
InputStream
;
struct
TagHandler
;
class
TagHandler
;
struct
Tag
;
struct
id3_tag
;
bool
tag_id3_scan
(
InputStream
&
is
,
const
TagHandler
&
handler
,
void
*
handler_ctx
);
tag_id3_scan
(
InputStream
&
is
,
TagHandler
&
handler
)
noexcept
;
std
::
unique_ptr
<
Tag
>
tag_id3_import
(
id3_tag
*
);
...
...
@@ -41,7 +40,6 @@ tag_id3_import(id3_tag *);
*
*/
void
scan_id3_tag
(
id3_tag
*
tag
,
const
TagHandler
&
handler
,
void
*
handler_ctx
);
scan_id3_tag
(
id3_tag
*
tag
,
TagHandler
&
handler
)
noexcept
;
#endif
test/read_tags.cxx
View file @
3d3a1232
...
...
@@ -40,31 +40,29 @@
#include <locale.h>
#endif
static
bool
empty
=
true
;
class
DumpTagHandler
final
:
public
NullTagHandler
{
bool
empty
=
true
;
static
void
print_duration
(
SongTime
duration
,
gcc_unused
void
*
ctx
)
{
public
:
DumpTagHandler
()
noexcept
:
NullTagHandler
(
WANT_DURATION
|
WANT_TAG
|
WANT_PAIR
)
{}
bool
IsEmpty
()
const
noexcept
{
return
empty
;
}
void
OnDuration
(
SongTime
duration
)
noexcept
override
{
printf
(
"duration=%f
\n
"
,
duration
.
ToDoubleS
());
}
}
static
void
print_tag
(
TagType
type
,
const
char
*
value
,
gcc_unused
void
*
ctx
)
{
void
OnTag
(
TagType
type
,
const
char
*
value
)
noexcept
override
{
printf
(
"[%s]=%s
\n
"
,
tag_item_names
[
type
],
value
);
empty
=
false
;
}
static
void
print_pair
(
const
char
*
name
,
const
char
*
value
,
gcc_unused
void
*
ctx
)
{
printf
(
"
\"
%s
\"
=%s
\n
"
,
name
,
value
);
}
}
static
constexpr
TagHandler
print_handler
=
{
print_duration
,
print_tag
,
print_pair
,
void
OnPair
(
const
char
*
key
,
const
char
*
value
)
noexcept
override
{
printf
(
"
\"
%s
\"
=%s
\n
"
,
key
,
value
);
}
};
int
main
(
int
argc
,
char
**
argv
)
...
...
@@ -100,9 +98,10 @@ try {
return
EXIT_FAILURE
;
}
DumpTagHandler
h
;
bool
success
;
try
{
success
=
plugin
->
ScanFile
(
path
,
print_handler
,
nullptr
);
success
=
plugin
->
ScanFile
(
path
,
h
);
}
catch
(
const
std
::
exception
&
e
)
{
LogError
(
e
);
success
=
false
;
...
...
@@ -113,7 +112,7 @@ try {
if
(
!
success
&&
plugin
->
scan_stream
!=
NULL
)
{
is
=
InputStream
::
OpenReady
(
path
.
c_str
(),
mutex
);
success
=
plugin
->
ScanStream
(
*
is
,
print_handler
,
nullptr
);
success
=
plugin
->
ScanStream
(
*
is
,
h
);
}
if
(
!
success
)
{
...
...
@@ -121,11 +120,11 @@ try {
return
EXIT_FAILURE
;
}
if
(
empty
)
{
if
(
h
.
IsEmpty
()
)
{
if
(
is
)
ScanGenericTags
(
*
is
,
print_handler
,
nullptr
);
ScanGenericTags
(
*
is
,
h
);
else
ScanGenericTags
(
path
,
print_handler
,
nullptr
);
ScanGenericTags
(
path
,
h
);
}
return
0
;
...
...
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