TagHandler: pass SongTime to duration()
This commit is contained in:
parent
d9d97bd17b
commit
3158955198
@ -102,7 +102,7 @@ adplug_scan_file(Path path_fs,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
player->songlength() / 1000);
|
SongTime::FromMS(player->songlength()));
|
||||||
|
|
||||||
if (handler->tag != nullptr) {
|
if (handler->tag != nullptr) {
|
||||||
adplug_scan_tag(TAG_TITLE, player->gettitle(),
|
adplug_scan_tag(TAG_TITLE, player->gettitle(),
|
||||||
|
@ -244,19 +244,19 @@ audiofile_stream_decode(Decoder &decoder, InputStream &is)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
static int
|
static SignedSongTime
|
||||||
audiofile_get_duration(InputStream &is)
|
audiofile_get_duration(InputStream &is)
|
||||||
{
|
{
|
||||||
if (!is.IsSeekable() || !is.KnownSize())
|
if (!is.IsSeekable() || !is.KnownSize())
|
||||||
return -1;
|
return SignedSongTime::Negative();
|
||||||
|
|
||||||
AudioFileInputStream afis{nullptr, is};
|
AudioFileInputStream afis{nullptr, is};
|
||||||
AFvirtualfile *vf = setup_virtual_fops(afis);
|
AFvirtualfile *vf = setup_virtual_fops(afis);
|
||||||
AFfilehandle fh = afOpenVirtualFile(vf, "r", nullptr);
|
AFfilehandle fh = afOpenVirtualFile(vf, "r", nullptr);
|
||||||
if (fh == AF_NULL_FILEHANDLE)
|
if (fh == AF_NULL_FILEHANDLE)
|
||||||
return -1;
|
return SignedSongTime::Negative();
|
||||||
|
|
||||||
int duration = audiofile_get_duration(fh).RoundS();
|
const auto duration = audiofile_get_duration(fh);
|
||||||
afCloseFile(fh);
|
afCloseFile(fh);
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
@ -265,11 +265,11 @@ static bool
|
|||||||
audiofile_scan_stream(InputStream &is,
|
audiofile_scan_stream(InputStream &is,
|
||||||
const struct tag_handler *handler, void *handler_ctx)
|
const struct tag_handler *handler, void *handler_ctx)
|
||||||
{
|
{
|
||||||
int total_time = audiofile_get_duration(is);
|
const auto duration = audiofile_get_duration(is);
|
||||||
if (total_time < 0)
|
if (duration.IsNegative())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, total_time);
|
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,8 +474,9 @@ dsdiff_scan_stream(InputStream &is,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* calculate song time and add as tag */
|
/* calculate song time and add as tag */
|
||||||
unsigned songtime = ((metadata.chunk_size / metadata.channels) * 8) /
|
uint64_t n_frames = metadata.chunk_size / audio_format.channels;
|
||||||
metadata.sample_rate;
|
auto songtime = SongTime::FromScale<uint64_t>(n_frames,
|
||||||
|
audio_format.sample_rate);
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, songtime);
|
tag_handler_invoke_duration(handler, handler_ctx, songtime);
|
||||||
|
|
||||||
/* Read additional metadata and created tags if available */
|
/* Read additional metadata and created tags if available */
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static constexpr unsigned DSF_BLOCK_SIZE = 4096;
|
static constexpr unsigned DSF_BLOCK_SIZE = 4096;
|
||||||
static constexpr unsigned DSF_BLOCK_BITS = DSF_BLOCK_SIZE * 8;
|
|
||||||
|
|
||||||
struct DsfMetaData {
|
struct DsfMetaData {
|
||||||
unsigned sample_rate, channels;
|
unsigned sample_rate, channels;
|
||||||
@ -348,8 +347,9 @@ dsf_scan_stream(InputStream &is,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* calculate song time and add as tag */
|
/* calculate song time and add as tag */
|
||||||
unsigned songtime = (metadata.n_blocks * DSF_BLOCK_BITS) /
|
const auto n_blocks = metadata.n_blocks;
|
||||||
metadata.sample_rate;
|
auto songtime = SongTime::FromScale<uint64_t>(n_blocks * DSF_BLOCK_SIZE,
|
||||||
|
audio_format.sample_rate);
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, songtime);
|
tag_handler_invoke_duration(handler, handler_ctx, songtime);
|
||||||
|
|
||||||
#ifdef HAVE_ID3TAG
|
#ifdef HAVE_ID3TAG
|
||||||
|
@ -438,11 +438,9 @@ faad_scan_stream(InputStream &is,
|
|||||||
if (!result.first)
|
if (!result.first)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned duration = result.second.IsNegative()
|
if (!result.second.IsNegative())
|
||||||
? 0
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
: result.second.RoundS();
|
SongTime(result.second));
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,9 +609,12 @@ ffmpeg_scan_stream(InputStream &is,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->duration != (int64_t)AV_NOPTS_VALUE)
|
if (f->duration != (int64_t)AV_NOPTS_VALUE) {
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto duration =
|
||||||
f->duration / AV_TIME_BASE);
|
SongTime::FromScale<uint64_t>(f->duration,
|
||||||
|
AV_TIME_BASE);
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
|
}
|
||||||
|
|
||||||
ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
|
ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
|
||||||
int idx = ffmpeg_find_audio_stream(f);
|
int idx = ffmpeg_find_audio_stream(f);
|
||||||
|
@ -179,6 +179,16 @@ flac_scan_comments(const FLAC__StreamMetadata_VorbisComment *comment,
|
|||||||
handler, handler_ctx);
|
handler, handler_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
static inline SongTime
|
||||||
|
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
|
||||||
|
{
|
||||||
|
assert(stream_info->sample_rate > 0);
|
||||||
|
|
||||||
|
return SongTime::FromScale<uint64_t>(stream_info->total_samples,
|
||||||
|
stream_info->sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flac_scan_metadata(const FLAC__StreamMetadata *block,
|
flac_scan_metadata(const FLAC__StreamMetadata *block,
|
||||||
const struct tag_handler *handler, void *handler_ctx)
|
const struct tag_handler *handler, void *handler_ctx)
|
||||||
|
@ -114,15 +114,6 @@ public:
|
|||||||
struct Tag;
|
struct Tag;
|
||||||
struct ReplayGainInfo;
|
struct ReplayGainInfo;
|
||||||
|
|
||||||
static inline unsigned
|
|
||||||
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
|
|
||||||
{
|
|
||||||
assert(stream_info->sample_rate > 0);
|
|
||||||
|
|
||||||
return (stream_info->total_samples + stream_info->sample_rate - 1) /
|
|
||||||
stream_info->sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
flac_parse_replay_gain(ReplayGainInfo &rgi,
|
flac_parse_replay_gain(ReplayGainInfo &rgi,
|
||||||
const FLAC__StreamMetadata *block);
|
const FLAC__StreamMetadata *block);
|
||||||
|
@ -238,7 +238,7 @@ gme_scan_file(Path path_fs,
|
|||||||
|
|
||||||
if (ti->length > 0)
|
if (ti->length > 0)
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
ti->length / 100);
|
SongTime::FromMS(ti->length));
|
||||||
|
|
||||||
if (ti->song != nullptr) {
|
if (ti->song != nullptr) {
|
||||||
if (gme_track_count(emu) > 1) {
|
if (gme_track_count(emu) > 1) {
|
||||||
|
@ -1094,11 +1094,9 @@ mad_decoder_scan_stream(InputStream &is,
|
|||||||
if (!result.first)
|
if (!result.first)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned duration = result.second.IsNegative()
|
if (!result.second.IsNegative())
|
||||||
? 0
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
: result.second.RoundS();
|
SongTime(result.second));
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ modplug_scan_stream(InputStream &is,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
ModPlug_GetLength(f) / 1000);
|
SongTime::FromMS(ModPlug_GetLength(f)));
|
||||||
|
|
||||||
const char *title = ModPlug_GetName(f);
|
const char *title = ModPlug_GetName(f);
|
||||||
if (title != nullptr)
|
if (title != nullptr)
|
||||||
|
@ -256,8 +256,10 @@ mp4_scan_file(Path path_fs,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MP4Duration dur = MP4GetTrackDuration(handle, id) /
|
const MP4Timestamp scale = MP4GetTrackTimeScale(handle, id);
|
||||||
MP4GetTrackTimeScale(handle, id);
|
const SongTime dur =
|
||||||
|
SongTime::FromScale<uint64_t>(MP4GetTrackDuration(handle, id),
|
||||||
|
scale);
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, dur);
|
tag_handler_invoke_duration(handler, handler_ctx, dur);
|
||||||
|
|
||||||
const MP4Tags* tags = MP4TagsAlloc();
|
const MP4Tags* tags = MP4TagsAlloc();
|
||||||
|
@ -228,7 +228,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
|
|||||||
mpc_demux_exit(demux);
|
mpc_demux_exit(demux);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float
|
static SignedSongTime
|
||||||
mpcdec_get_file_duration(InputStream &is)
|
mpcdec_get_file_duration(InputStream &is)
|
||||||
{
|
{
|
||||||
mpc_decoder_data data(is, nullptr);
|
mpc_decoder_data data(is, nullptr);
|
||||||
@ -243,25 +243,24 @@ mpcdec_get_file_duration(InputStream &is)
|
|||||||
|
|
||||||
mpc_demux *demux = mpc_demux_init(&reader);
|
mpc_demux *demux = mpc_demux_init(&reader);
|
||||||
if (demux == nullptr)
|
if (demux == nullptr)
|
||||||
return -1;
|
return SignedSongTime::Negative();
|
||||||
|
|
||||||
mpc_streaminfo info;
|
mpc_streaminfo info;
|
||||||
mpc_demux_get_info(demux, &info);
|
mpc_demux_get_info(demux, &info);
|
||||||
mpc_demux_exit(demux);
|
mpc_demux_exit(demux);
|
||||||
|
|
||||||
return mpc_streaminfo_get_length(&info);
|
return SongTime::FromS(mpc_streaminfo_get_length(&info));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mpcdec_scan_stream(InputStream &is,
|
mpcdec_scan_stream(InputStream &is,
|
||||||
const struct tag_handler *handler, void *handler_ctx)
|
const struct tag_handler *handler, void *handler_ctx)
|
||||||
{
|
{
|
||||||
float total_time = mpcdec_get_file_duration(is);
|
const auto duration = mpcdec_get_file_duration(is);
|
||||||
|
if (duration.IsNegative())
|
||||||
if (total_time < 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, total_time);
|
tag_handler_invoke_duration(handler, handler_ctx, SongTime(duration));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,8 +233,11 @@ mpd_mpg123_scan_file(Path path_fs,
|
|||||||
|
|
||||||
mpg123_delete(handle);
|
mpg123_delete(handle);
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto duration =
|
||||||
num_samples / audio_format.sample_rate);
|
SongTime::FromScale<uint64_t>(num_samples,
|
||||||
|
audio_format.sample_rate);
|
||||||
|
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,9 +441,12 @@ mpd_opus_scan_stream(InputStream &is,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.e_o_s || OggSeekFindEOS(oy, os, packet, is))
|
if (packet.e_o_s || OggSeekFindEOS(oy, os, packet, is)) {
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto duration =
|
||||||
packet.granulepos / opus_sample_rate);
|
SongTime::FromScale<uint64_t>(packet.granulepos,
|
||||||
|
opus_sample_rate);
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
|
}
|
||||||
|
|
||||||
ogg_stream_clear(&os);
|
ogg_stream_clear(&os);
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ sidplay_scan_file(Path path_fs,
|
|||||||
const auto duration = get_song_length(path_fs);
|
const auto duration = get_song_length(path_fs);
|
||||||
if (!duration.IsNegative())
|
if (!duration.IsNegative())
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
duration.RoundS());
|
SongTime(duration));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,9 @@ sndfile_scan_stream(InputStream &is,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto duration =
|
||||||
info.frames / info.samplerate);
|
SongTime::FromScale<uint64_t>(info.frames, info.samplerate);
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
|
|
||||||
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, handler_ctx);
|
||||||
|
@ -347,8 +347,10 @@ vorbis_scan_stream(InputStream &is,
|
|||||||
if (!vorbis_is_open(&vis, &vf))
|
if (!vorbis_is_open(&vis, &vf))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto total = ov_time_total(&vf, -1);
|
||||||
(int)(ov_time_total(&vf, -1) + 0.5));
|
if (total >= 0)
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx,
|
||||||
|
SongTime::FromS(total));
|
||||||
|
|
||||||
vorbis_comments_scan(ov_comment(&vf, -1)->user_comments,
|
vorbis_comments_scan(ov_comment(&vf, -1)->user_comments,
|
||||||
handler, handler_ctx);
|
handler, handler_ctx);
|
||||||
|
@ -283,9 +283,10 @@ wavpack_scan_file(Path path_fs,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_handler_invoke_duration(handler, handler_ctx,
|
const auto duration =
|
||||||
WavpackGetNumSamples(wpc) /
|
SongTime::FromScale<uint64_t>(WavpackGetNumSamples(wpc),
|
||||||
WavpackGetSampleRate(wpc));
|
WavpackGetSampleRate(wpc));
|
||||||
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
|
|
||||||
/* the WavPack format implies APEv2 tags, which means we can
|
/* the WavPack format implies APEv2 tags, which means we can
|
||||||
reuse the mapping from tag_ape.c */
|
reuse the mapping from tag_ape.c */
|
||||||
|
@ -135,7 +135,9 @@ wildmidi_scan_file(Path path_fs,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int duration = info->approx_total_samples / WILDMIDI_SAMPLE_RATE;
|
const auto duration =
|
||||||
|
SongTime::FromScale<uint64_t>(info->approx_total_samples,
|
||||||
|
WILDMIDI_SAMPLE_RATE);
|
||||||
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||||
|
|
||||||
WildMidi_Close(wm);
|
WildMidi_Close(wm);
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_tag_duration(unsigned seconds, void *ctx)
|
add_tag_duration(SongTime duration, void *ctx)
|
||||||
{
|
{
|
||||||
TagBuilder &tag = *(TagBuilder *)ctx;
|
TagBuilder &tag = *(TagBuilder *)ctx;
|
||||||
|
|
||||||
tag.SetDuration(SignedSongTime::FromS(seconds));
|
tag.SetDuration(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "TagType.h"
|
#include "TagType.h"
|
||||||
|
#include "Chrono.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -30,11 +31,11 @@
|
|||||||
*/
|
*/
|
||||||
struct tag_handler {
|
struct tag_handler {
|
||||||
/**
|
/**
|
||||||
* Declare the duration of a song, in seconds. 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".
|
||||||
*/
|
*/
|
||||||
void (*duration)(unsigned seconds, void *ctx);
|
void (*duration)(SongTime duration, void *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tag has been read.
|
* A tag has been read.
|
||||||
@ -53,12 +54,12 @@ struct tag_handler {
|
|||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tag_handler_invoke_duration(const struct tag_handler *handler, void *ctx,
|
tag_handler_invoke_duration(const struct tag_handler *handler, void *ctx,
|
||||||
unsigned seconds)
|
SongTime duration)
|
||||||
{
|
{
|
||||||
assert(handler != nullptr);
|
assert(handler != nullptr);
|
||||||
|
|
||||||
if (handler->duration != nullptr)
|
if (handler->duration != nullptr)
|
||||||
handler->duration(seconds, ctx);
|
handler->duration(duration, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -48,9 +48,9 @@
|
|||||||
static bool empty = true;
|
static bool empty = true;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_duration(unsigned seconds, gcc_unused void *ctx)
|
print_duration(SongTime duration, gcc_unused void *ctx)
|
||||||
{
|
{
|
||||||
printf("duration=%d\n", seconds);
|
printf("duration=%f\n", duration.ToDoubleS());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user