From 28e9141a9e7e4a30e6cd384ada7c87edab7d8efb Mon Sep 17 00:00:00 2001 From: Richard Kettlewell Date: Wed, 9 Jun 2010 20:00:30 +0100 Subject: [PATCH] Split up tracklength module into separate files for each file format. --- plugins/Makefile.am | 4 +- plugins/tracklength-flac.c | 97 ++++++++++++++++++++++++++ plugins/tracklength-mp3.c | 71 +++++++++++++++++++ plugins/tracklength-ogg.c | 47 +++++++++++++ plugins/tracklength-wav.c | 49 +++++++++++++ plugins/tracklength.c | 166 +-------------------------------------------- plugins/tracklength.h | 50 ++++++++++++++ 7 files changed, 318 insertions(+), 166 deletions(-) create mode 100644 plugins/tracklength-flac.c create mode 100644 plugins/tracklength-mp3.c create mode 100644 plugins/tracklength-ogg.c create mode 100644 plugins/tracklength-wav.c create mode 100644 plugins/tracklength.h diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 7852152..3626991 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -23,7 +23,9 @@ AM_CPPFLAGS=-I${top_srcdir}/lib notify_la_SOURCES=notify.c notify_la_LDFLAGS=-module -disorder_tracklength_la_SOURCES=tracklength.c mad.c madshim.h ../lib/wav.h ../lib/wav.c +disorder_tracklength_la_SOURCES=tracklength.c tracklength.h \ +tracklength-mp3.c tracklength-ogg.c tracklength-wav.c \ +tracklength-flac.c mad.c madshim.h ../lib/wav.h ../lib/wav.c disorder_tracklength_la_LDFLAGS=-module disorder_tracklength_la_LIBADD=$(LIBVORBISFILE) $(LIBMAD) $(LIBFLAC) -lm diff --git a/plugins/tracklength-flac.c b/plugins/tracklength-flac.c new file mode 100644 index 0000000..a838966 --- /dev/null +++ b/plugins/tracklength-flac.c @@ -0,0 +1,97 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2007 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file plugins/tracklength-flac.c + * @brief Compute track lengths for FLAC files + */ +#include "tracklength.h" +#include + +/* libFLAC's "simplified" interface is rather heavyweight... */ + +struct flac_state { + long duration; + const char *path; +}; + +static void flac_metadata(const FLAC__StreamDecoder attribute((unused)) *decoder, + const FLAC__StreamMetadata *metadata, + void *client_data) { + struct flac_state *const state = client_data; + const FLAC__StreamMetadata_StreamInfo *const stream_info + = &metadata->data.stream_info; + + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) + /* FLAC uses 0 to mean unknown and conveniently so do we */ + state->duration = (stream_info->total_samples + + stream_info->sample_rate - 1) + / stream_info->sample_rate; +} + +static void flac_error(const FLAC__StreamDecoder attribute((unused)) *decoder, + FLAC__StreamDecoderErrorStatus status, + void *client_data) { + const struct flac_state *const state = client_data; + + disorder_error(0, "error decoding %s: %s", state->path, + FLAC__StreamDecoderErrorStatusString[status]); +} + +static FLAC__StreamDecoderWriteStatus flac_write + (const FLAC__StreamDecoder attribute((unused)) *decoder, + const FLAC__Frame attribute((unused)) *frame, + const FLAC__int32 attribute((unused)) *const buffer_[], + void attribute((unused)) *client_data) { + const struct flac_state *const state = client_data; + + if(state->duration >= 0) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + else + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +long tl_flac(const char *path) { + FLAC__StreamDecoder *sd = 0; + FLAC__StreamDecoderInitStatus is; + struct flac_state state[1]; + + state->duration = -1; /* error */ + state->path = path; + if(!(sd = FLAC__stream_decoder_new())) { + disorder_error(0, "FLAC__stream_decoder_new failed"); + goto fail; + } + if((is = FLAC__stream_decoder_init_file(sd, path, flac_write, flac_metadata, + flac_error, state))) { + disorder_error(0, "FLAC__stream_decoder_init_file %s: %s", + path, FLAC__StreamDecoderInitStatusString[is]); + goto fail; + } + FLAC__stream_decoder_process_until_end_of_metadata(sd); +fail: + if(sd) + FLAC__stream_decoder_delete(sd); + return state->duration; +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +End: +*/ diff --git a/plugins/tracklength-mp3.c b/plugins/tracklength-mp3.c new file mode 100644 index 0000000..ecd1c1e --- /dev/null +++ b/plugins/tracklength-mp3.c @@ -0,0 +1,71 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2007 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file plugins/tracklength-mp3.c + * @brief Compute track lengths for MP3 files + */ +#include "tracklength.h" +#include +#include "madshim.h" + +static void *mmap_file(const char *path, size_t *lengthp) { + int fd; + void *base; + struct stat sb; + + if((fd = open(path, O_RDONLY)) < 0) { + disorder_error(errno, "error opening %s", path); + return 0; + } + if(fstat(fd, &sb) < 0) { + disorder_error(errno, "error calling stat on %s", path); + goto error; + } + if(sb.st_size == 0) /* can't map 0-length files */ + goto error; + if((base = mmap(0, sb.st_size, PROT_READ, + MAP_SHARED, fd, 0)) == (void *)-1) { + disorder_error(errno, "error calling mmap on %s", path); + goto error; + } + *lengthp = sb.st_size; + close(fd); + return base; +error: + close(fd); + return 0; +} + +long tl_mp3(const char *path) { + size_t length; + void *base; + buffer b; + + if(!(base = mmap_file(path, &length))) return -1; + b.duration = mad_timer_zero; + scan_mp3(base, length, &b); + munmap(base, length); + return b.duration.seconds + !!b.duration.fraction; +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +End: +*/ diff --git a/plugins/tracklength-ogg.c b/plugins/tracklength-ogg.c new file mode 100644 index 0000000..c5c90c6 --- /dev/null +++ b/plugins/tracklength-ogg.c @@ -0,0 +1,47 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2007 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file plugins/tracklength-ogg.c + * @brief Compute track lengths for OGG files + */ +#include "tracklength.h" +#include + +long tl_ogg(const char *path) { + OggVorbis_File vf; + FILE *fp = 0; + double length; + + if(!path) goto error; + if(!(fp = fopen(path, "rb"))) goto error; + if(ov_open(fp, &vf, 0, 0)) goto error; + fp = 0; + length = ov_time_total(&vf, -1); + ov_clear(&vf); + return ceil(length); +error: + if(fp) fclose(fp); + return -1; +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +End: +*/ diff --git a/plugins/tracklength-wav.c b/plugins/tracklength-wav.c new file mode 100644 index 0000000..bf501c5 --- /dev/null +++ b/plugins/tracklength-wav.c @@ -0,0 +1,49 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2007 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file plugins/tracklength-wav.c + * @brief Compute track lengths for WAV files + */ +#include "tracklength.h" +#include "wav.h" + +long tl_wav(const char *path) { + struct wavfile f[1]; + int err, sample_frame_size; + long duration; + + if((err = wav_init(f, path))) { + disorder_error(err, "error opening %s", path); + return -1; + } + sample_frame_size = (f->bits + 7) / 8 * f->channels; + if(sample_frame_size) { + const long long n_samples = f->datasize / sample_frame_size; + duration = (n_samples + f->rate - 1) / f->rate; + } else + duration = -1; + wav_destroy(f); + return duration; +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +End: +*/ diff --git a/plugins/tracklength.c b/plugins/tracklength.c index a31792e..24d22b6 100644 --- a/plugins/tracklength.c +++ b/plugins/tracklength.c @@ -20,171 +20,7 @@ * * Currently implements MP3, OGG, FLAC and WAV. */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#include - -#include "madshim.h" -#include "wav.h" - -static void *mmap_file(const char *path, size_t *lengthp) { - int fd; - void *base; - struct stat sb; - - if((fd = open(path, O_RDONLY)) < 0) { - disorder_error(errno, "error opening %s", path); - return 0; - } - if(fstat(fd, &sb) < 0) { - disorder_error(errno, "error calling stat on %s", path); - goto error; - } - if(sb.st_size == 0) /* can't map 0-length files */ - goto error; - if((base = mmap(0, sb.st_size, PROT_READ, - MAP_SHARED, fd, 0)) == (void *)-1) { - disorder_error(errno, "error calling mmap on %s", path); - goto error; - } - *lengthp = sb.st_size; - close(fd); - return base; -error: - close(fd); - return 0; -} - -static long tl_mp3(const char *path) { - size_t length; - void *base; - buffer b; - - if(!(base = mmap_file(path, &length))) return -1; - b.duration = mad_timer_zero; - scan_mp3(base, length, &b); - munmap(base, length); - return b.duration.seconds + !!b.duration.fraction; -} - -static long tl_ogg(const char *path) { - OggVorbis_File vf; - FILE *fp = 0; - double length; - - if(!path) goto error; - if(!(fp = fopen(path, "rb"))) goto error; - if(ov_open(fp, &vf, 0, 0)) goto error; - fp = 0; - length = ov_time_total(&vf, -1); - ov_clear(&vf); - return ceil(length); -error: - if(fp) fclose(fp); - return -1; -} - -static long tl_wav(const char *path) { - struct wavfile f[1]; - int err, sample_frame_size; - long duration; - - if((err = wav_init(f, path))) { - disorder_error(err, "error opening %s", path); - return -1; - } - sample_frame_size = (f->bits + 7) / 8 * f->channels; - if(sample_frame_size) { - const long long n_samples = f->datasize / sample_frame_size; - duration = (n_samples + f->rate - 1) / f->rate; - } else - duration = -1; - wav_destroy(f); - return duration; -} - -/* libFLAC's "simplified" interface is rather heavyweight... */ - -struct flac_state { - long duration; - const char *path; -}; - -static void flac_metadata(const FLAC__StreamDecoder attribute((unused)) *decoder, - const FLAC__StreamMetadata *metadata, - void *client_data) { - struct flac_state *const state = client_data; - const FLAC__StreamMetadata_StreamInfo *const stream_info - = &metadata->data.stream_info; - - if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) - /* FLAC uses 0 to mean unknown and conveniently so do we */ - state->duration = (stream_info->total_samples - + stream_info->sample_rate - 1) - / stream_info->sample_rate; -} - -static void flac_error(const FLAC__StreamDecoder attribute((unused)) *decoder, - FLAC__StreamDecoderErrorStatus status, - void *client_data) { - const struct flac_state *const state = client_data; - - disorder_error(0, "error decoding %s: %s", state->path, - FLAC__StreamDecoderErrorStatusString[status]); -} - -static FLAC__StreamDecoderWriteStatus flac_write - (const FLAC__StreamDecoder attribute((unused)) *decoder, - const FLAC__Frame attribute((unused)) *frame, - const FLAC__int32 attribute((unused)) *const buffer_[], - void attribute((unused)) *client_data) { - const struct flac_state *const state = client_data; - - if(state->duration >= 0) - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - else - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -static long tl_flac(const char *path) { - FLAC__StreamDecoder *sd = 0; - FLAC__StreamDecoderInitStatus is; - struct flac_state state[1]; - - state->duration = -1; /* error */ - state->path = path; - if(!(sd = FLAC__stream_decoder_new())) { - disorder_error(0, "FLAC__stream_decoder_new failed"); - goto fail; - } - if((is = FLAC__stream_decoder_init_file(sd, path, flac_write, flac_metadata, - flac_error, state))) { - disorder_error(0, "FLAC__stream_decoder_init_file %s: %s", - path, FLAC__StreamDecoderInitStatusString[is]); - goto fail; - } - FLAC__stream_decoder_process_until_end_of_metadata(sd); -fail: - if(sd) - FLAC__stream_decoder_delete(sd); - return state->duration; -} +#include "tracklength.h" static const struct { const char *ext; diff --git a/plugins/tracklength.h b/plugins/tracklength.h new file mode 100644 index 0000000..c8e22a4 --- /dev/null +++ b/plugins/tracklength.h @@ -0,0 +1,50 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2007 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TRACKLENGTH_H +#define TRACKLENGTH_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +long tl_ogg(const char *path); +long tl_wav(const char *path); +long tl_mp3(const char *path); +long tl_flac(const char *path); + +#endif /* TRACKLENGTH_H */ + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ -- 2.11.0