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