23 #include <sys/types.h> 45 m_path(source.getLocalFilename()),
59 if (::stat(
m_path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) {
71 if ((fd = ::open(
m_path.toLocal8Bit().data(), O_RDONLY
76 m_error = QString(
"Failed to open file %1 for reading.").arg(
m_path);
83 m_error = QString(
"Out of memory");
93 m_error = QString(
"Read error for file %1 (after %2 bytes)")
99 cerr << QString(
"MP3FileReader::MP3FileReader: Warning: reached EOF after only %1 of %2 bytes")
116 (tr(
"Decoding %1...").arg(QFileInfo(
m_path).fileName()));
141 cerr <<
"MP3FileReader ctor: exiting with file rate = " <<
m_fileRate << endl;
145 cerr <<
"MP3FileReader::MP3FileReader(\"" <<
m_path <<
"\"): ERROR: " <<
m_error << endl;
171 id3_file *file = id3_file_open(
m_path.toLocal8Bit().data(),
172 ID3_FILE_MODE_READONLY);
178 id3_tag *tag = id3_file_tag(file);
181 SVDEBUG <<
"MP3FileReader::loadTags: No ID3 tag found" << endl;
183 id3_file_close(file);
193 for (
unsigned int i = 0; i < tag->nframes; ++i) {
194 if (tag->frames[i]) {
195 QString value =
loadTag(tag, tag->frames[i]->id);
196 if (value !=
"")
m_tags[tag->frames[i]->id] = value;
200 id3_file_close(file);
204 SVDEBUG <<
"MP3FileReader::loadTags: ID3 tag support not compiled in" 214 id3_tag *tag = (id3_tag *)vtag;
216 id3_frame *frame = id3_tag_findframe(tag, name, 0);
219 SVDEBUG <<
"MP3FileReader::loadTags: No \"" << name <<
"\" in ID3 tag" << endl;
224 if (frame->nfields < 2) {
225 SVDEBUG <<
"MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields <<
") for \"" << name <<
"\" in ID3 tag" << endl;
229 unsigned int nstrings = id3_field_getnstrings(&frame->fields[1]);
232 SVDEBUG <<
"MP3FileReader::loadTags: No strings for \"" << name <<
"\" in ID3 tag" << endl;
237 id3_ucs4_t
const *ustr = id3_field_getstrings(&frame->fields[1], 0);
240 SVDEBUG <<
"MP3FileReader::loadTags: Invalid or absent data for \"" << name <<
"\" in ID3 tag" << endl;
245 id3_utf8_t *u8str = id3_ucs4_utf8duplicate(ustr);
247 cerr <<
"MP3FileReader::loadTags: ERROR: Internal error: Failed to convert UCS4 to UTF8 in ID3 title" << endl;
251 QString rv = QString::fromUtf8((
const char *)u8str);
255 SVDEBUG <<
"MP3FileReader::loadTags: tag \"" << name <<
"\" -> \"" 256 << rv <<
"\"" << endl;
297 struct mad_decoder decoder;
299 data.
start = (
unsigned char const *)mm;
300 data.
length = (
unsigned long)sz;
304 mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
305 mad_decoder_finish(&decoder);
316 if (!data->
length)
return MAD_FLOW_STOP;
318 unsigned char const *start = data->
start;
319 unsigned long length = data->
length;
322 if (length > ID3_TAG_QUERYSIZE) {
323 int taglen = id3_tag_query(start, ID3_TAG_QUERYSIZE);
332 mad_stream_buffer(stream, start, length);
335 return MAD_FLOW_CONTINUE;
340 struct mad_header
const *header,
351 int channels = pcm->channels;
352 int frames = pcm->length;
359 if (frames < 1)
return MAD_FLOW_CONTINUE;
376 double duration = double(
m_fileSize * 8) / bitrate;
378 double percent = 100;
379 if (duration > 0.0) percent = ((elapsed * 100.0) / duration);
380 int p = int(percent);
398 for (
int c = 0; c < channels; ++c) {
402 for (
int c = 0; c < channels; ++c) {
409 int activeChannels = int(
sizeof(pcm->samples) /
sizeof(pcm->samples[0]));
411 for (
int ch = 0; ch < channels; ++ch) {
413 for (
int i = 0; i < frames; ++i) {
415 mad_fixed_t sample = 0;
416 if (ch < activeChannels) {
417 sample = pcm->samples[ch][i];
419 float fsample = float(sample) / float(MAD_F_ONE);
427 return MAD_FLOW_CONTINUE;
432 struct mad_stream * ,
441 return MAD_FLOW_CONTINUE;
447 extensions.insert(
"mp3");
453 std::set<QString> extensions;
455 return (extensions.find(extension.toLower()) != extensions.end());
461 return (type ==
"audio/mpeg");
QString getExtension() const
Return the file extension for this file, if any.
unsigned char const * start
QString loadTag(void *vtag, const char *name)
static void getSupportedExtensions(std::set< QString > &extensions)
static enum mad_flow input(void *, struct mad_stream *)
DecodeThread * m_decodeThread
enum mad_flow accept(struct mad_header const *, struct mad_pcm *)
static enum mad_flow output(void *, struct mad_header const *, struct mad_pcm *)
void addSamplesToDecodeCache(float **samples, int nframes)
unsigned char * m_filebuffer
MP3FileReader(FileSource source, DecodeMode decodeMode, CacheMode cacheMode, int targetRate=0, bool normalised=false, ProgressReporter *reporter=0)
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
bool decode(void *mm, int sz)
virtual void setProgress(int percentage)=0
static bool supports(FileSource &source)
bool isDecodeCacheInitialised() const
ProgressReporter * m_reporter
void initialiseDecodeCache()
QString getContentType() const
Return the MIME content type of this file, if known.
virtual void setMessage(QString text)=0
static enum mad_flow error(void *, struct mad_stream *, struct mad_frame *)
void startSerialised(QString id)
static bool supportsExtension(QString ext)
static bool supportsContentType(QString type)