From f75f5ac9bbacc78d91ec207b28c53f11214b8637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Tue, 14 Jun 2011 03:47:08 +0200 Subject: [PATCH] added .mod file support --- taglib/CMakeLists.txt | 6 +- taglib/fileref.cpp | 4 + taglib/it/itfile.cpp | 5 +- taglib/it/itfile.h | 2 - taglib/mod/modfile.cpp | 164 ++++++++++++++++++ taglib/mod/modfile.h | 89 ++++++++++ taglib/mod/modfilebase.cpp | 19 +- taglib/mod/modfilebase.h | 8 +- taglib/mod/modfileprivate.h | 4 + .../{xm/xmtag.cpp => mod/modproperties.cpp} | 90 ++++------ taglib/{xm/xmtag.h => mod/modproperties.h} | 56 +++--- taglib/mod/modtag.cpp | 11 ++ taglib/mod/modtag.h | 2 + taglib/s3m/s3mfile.cpp | 7 +- taglib/s3m/s3mfile.h | 2 - taglib/xm/xmfile.cpp | 22 +-- taglib/xm/xmfile.h | 6 +- 17 files changed, 374 insertions(+), 123 deletions(-) create mode 100644 taglib/mod/modfile.cpp create mode 100644 taglib/mod/modfile.h rename taglib/{xm/xmtag.cpp => mod/modproperties.cpp} (60%) rename taglib/{xm/xmtag.h => mod/modproperties.h} (61%) diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index f344c462..837006af 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -102,14 +102,15 @@ set(tag_HDRS riff/wav/wavfile.h riff/wav/wavproperties.h mod/modfilebase.h + mod/modfile.h mod/modtag.h + mod/modproperties.h it/itfile.h it/itproperties.h s3m/s3mfile.h s3m/s3mproperties.h xm/xmfile.h xm/xmproperties.h - xm/xmtag.h ) if(WITH_ASF) set(tag_HDRS ${tag_HDRS} @@ -252,7 +253,9 @@ set(wav_SRCS set(mod_SRCS mod/modfilebase.cpp + mod/modfile.cpp mod/modtag.cpp + mod/modproperties.cpp ) set(s3m_SRCS @@ -267,7 +270,6 @@ set(it_SRCS set(xm_SRCS xm/xmfile.cpp - xm/xmtag.cpp xm/xmproperties.cpp ) diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index 8bb9c01b..63ac6672 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -49,6 +49,7 @@ #include "aifffile.h" #include "wavfile.h" #include "apefile.h" +#include "modfile.h" #include "s3mfile.h" #include "itfile.h" #include "xmfile.h" @@ -266,6 +267,9 @@ File *FileRef::create(FileName fileName, bool readAudioProperties, return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle); if(ext == "APE") return new APE::File(fileName, readAudioProperties, audioPropertiesStyle); + // module, nst and wow are possible but uncommon extensions + if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW") + return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle); if(ext == "S3M") return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle); if(ext == "IT") diff --git a/taglib/it/itfile.cpp b/taglib/it/itfile.cpp index f3917c9e..b5e12cb4 100644 --- a/taglib/it/itfile.cpp +++ b/taglib/it/itfile.cpp @@ -119,7 +119,7 @@ void IT::File::read(bool) for(ushort i = 0; i < instrumentCount; ++ i) { - seek(192 + length + (i << 2)); + seek(192L + length + ((long)i << 2)); READ_U32L_AS(instrumentOffset); seek(instrumentOffset); @@ -137,7 +137,7 @@ void IT::File::read(bool) for(ushort i = 0; i < sampleCount; ++ i) { - seek(192 + length + (instrumentCount << 2) + (i << 2)); + seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2)); READ_U32L_AS(sampleOffset); seek(sampleOffset); @@ -182,4 +182,5 @@ void IT::File::read(bool) } d->tag.setComment(comment.toString("\n")); + d->tag.setTrackerName("Impulse Tracker"); } diff --git a/taglib/it/itfile.h b/taglib/it/itfile.h index 5d6b3deb..73256d32 100644 --- a/taglib/it/itfile.h +++ b/taglib/it/itfile.h @@ -22,8 +22,6 @@ #ifndef TAGLIB_ITFILE_H #define TAGLIB_ITFILE_H -#include - #include "tfile.h" #include "audioproperties.h" #include "taglib_export.h" diff --git a/taglib/mod/modfile.cpp b/taglib/mod/modfile.cpp new file mode 100644 index 00000000..4525f119 --- /dev/null +++ b/taglib/mod/modfile.cpp @@ -0,0 +1,164 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "modfile.h" +#include "tstringlist.h" +#include "modfileprivate.h" + +using namespace TagLib; +using namespace Mod; + +class Mod::File::FilePrivate +{ +public: + FilePrivate(AudioProperties::ReadStyle propertiesStyle) + : properties(propertiesStyle) + { + } + + Mod::Tag tag; + Mod::Properties properties; +}; + +Mod::File::File(FileName file, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(file), + d(new FilePrivate(propertiesStyle)) +{ + read(readProperties); +} + +Mod::File::File(IOStream *stream, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(stream), + d(new FilePrivate(propertiesStyle)) +{ + read(readProperties); +} + +Mod::File::~File() +{ + delete d; +} + +Mod::Tag *Mod::File::tag() const +{ + return &d->tag; +} + +Mod::Properties *Mod::File::audioProperties() const +{ + return &d->properties; +} + +bool Mod::File::save() +{ + // note: if title starts with "Extended Module: " + // the file would look like an .xm file + seek(0); + writeString(d->tag.title(), 20, ' '); + // TODO: write comment as sample names + return true; +} + +void Mod::File::read(bool) +{ + if(!isOpen()) + return; + + seek(1080); + ByteVector modId = readBlock(4); + READ_ASSERT(modId.size() == 4); + + int channels = 4; + int instruments = 31; + if(modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.") + { + d->tag.setTrackerName("ProTracker"); + channels = 4; + } + else if(modId.startsWith("FLT") || modId.startsWith("TDZ")) + { + d->tag.setTrackerName("StarTrekker"); + char digit = modId[3]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = digit - '0'; + } + else if(modId.endsWith("CHN")) + { + d->tag.setTrackerName("StarTrekker"); + char digit = modId[0]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = digit - '0'; + } + else if(modId == "CD81" || modId == "OKTA") + { + d->tag.setTrackerName("Atari Oktalyzer"); + channels = 8; + } + else if(modId.endsWith("CH") || modId.endsWith("CN")) + { + d->tag.setTrackerName("TakeTracker"); + char digit = modId[0]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = (digit - '0') * 10; + digit = modId[1]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels += digit - '0'; + } + else + { + d->tag.setTrackerName("NoiseTracker"); // probably + channels = 4; + instruments = 15; + } + d->properties.setChannels(channels); + d->properties.setInstrumentCount(instruments); + + seek(0); + READ_STRING(d->tag.setTitle, 20); + + StringList comment; + for(int i = 0; i < instruments; ++ i) + { + READ_STRING_AS(instrumentName, 22); + READ_U16B_AS(instrumentLength); + + READ_BYTE_AS(fineTuneByte); + int fineTune = fineTuneByte & 0xF; + // > 7 means nagative value + if(fineTune > 7) fineTune -= 16; + + READ_BYTE_AS(volume); + if(volume > 64) volume = 64; + + READ_U16B_AS(repeatStart); + // (int)repatStart << 1; + READ_U16B_AS(repatLength); + // (int)repatLength << 1; + + comment.append(instrumentName); + } + + READ_BYTE(d->properties.setPatternCount); + + d->tag.setComment(comment.toString("\n")); +} diff --git a/taglib/mod/modfile.h b/taglib/mod/modfile.h new file mode 100644 index 00000000..6fd41b00 --- /dev/null +++ b/taglib/mod/modfile.h @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILE_H +#define TAGLIB_MODFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "modproperties.h" + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT File : public TagLib::Mod::FileBase { + public: + /*! + * Contructs a Protracker file from \a file. If \a readProperties + * is true the file's audio properties will also be read using + * \a propertiesStyle. If false, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Contructs a Protracker file from \a stream. If \a readProperties + * is true the file's audio properties will also be read using + * \a propertiesStyle. If false, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Returns the Mod::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + Mod::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Protracker tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/taglib/mod/modfilebase.cpp b/taglib/mod/modfilebase.cpp index 3680e976..2ae9977f 100644 --- a/taglib/mod/modfilebase.cpp +++ b/taglib/mod/modfilebase.cpp @@ -32,10 +32,10 @@ Mod::FileBase::FileBase(IOStream *stream) : TagLib::File(stream) { } -void Mod::FileBase::writeString(const String &s, ulong size) +void Mod::FileBase::writeString(const String &s, ulong size, char padding) { ByteVector data(s.data(String::Latin1)); - data.resize(size, 0); + data.resize(size, padding); writeBlock(data); } @@ -76,3 +76,18 @@ bool Mod::FileBase::readU32L(ulong &number) { number = data.toUInt(false); return true; } + +bool Mod::FileBase::readU16B(ushort &number) +{ + ByteVector data(readBlock(2)); + if(data.size() < 2) return false; + number = data.toUShort(true); + return true; +} + +bool Mod::FileBase::readU32B(ulong &number) { + ByteVector data(readBlock(4)); + if(data.size() < 4) return false; + number = data.toUInt(true); + return true; +} diff --git a/taglib/mod/modfilebase.h b/taglib/mod/modfilebase.h index d763ba13..aff6faec 100644 --- a/taglib/mod/modfilebase.h +++ b/taglib/mod/modfilebase.h @@ -19,8 +19,8 @@ * MA 02110-1301 USA * ***************************************************************************/ -#ifndef TAGLIB_MODFILE_H -#define TAGLIB_MODFILE_H +#ifndef TAGLIB_MODFILEBASE_H +#define TAGLIB_MODFILEBASE_H #include "taglib.h" #include "tfile.h" @@ -34,11 +34,13 @@ namespace TagLib { FileBase(FileName file); FileBase(IOStream *stream); - void writeString(const String &s, ulong size); + void writeString(const String &s, ulong size, char padding = 0); bool readString(String &s, ulong size); bool readByte(uchar &byte); bool readU16L(ushort &number); bool readU32L(ulong &number); + bool readU16B(ushort &number); + bool readU32B(ulong &number); }; } } diff --git a/taglib/mod/modfileprivate.h b/taglib/mod/modfileprivate.h index 1dc940b5..19a30019 100644 --- a/taglib/mod/modfileprivate.h +++ b/taglib/mod/modfileprivate.h @@ -40,6 +40,8 @@ #define READ_BYTE(setter) READ(setter,uchar,readByte) #define READ_U16L(setter) READ(setter,ushort,readU16L) #define READ_U32L(setter) READ(setter,ulong,readU32L) +#define READ_U16B(setter) READ(setter,ushort,readU16B) +#define READ_U32B(setter) READ(setter,ulong,readU32B) #define READ_STRING(setter,size) \ { \ @@ -55,6 +57,8 @@ #define READ_BYTE_AS(name) READ_AS(uchar,name,readByte) #define READ_U16L_AS(name) READ_AS(ushort,name,readU16L) #define READ_U32L_AS(name) READ_AS(ulong,name,readU32L) +#define READ_U16B_AS(name) READ_AS(ushort,name,readU16B) +#define READ_U32B_AS(name) READ_AS(ulong,name,readU32B) #define READ_STRING_AS(name,size) \ String name; \ diff --git a/taglib/xm/xmtag.cpp b/taglib/mod/modproperties.cpp similarity index 60% rename from taglib/xm/xmtag.cpp rename to taglib/mod/modproperties.cpp index bd91233a..a8b5746c 100644 --- a/taglib/xm/xmtag.cpp +++ b/taglib/mod/modproperties.cpp @@ -19,102 +19,78 @@ * MA 02110-1301 USA * ***************************************************************************/ -#include "xmtag.h" +#include "modproperties.h" using namespace TagLib; -using namespace XM; +using namespace Mod; -class XM::Tag::TagPrivate +class Mod::Properties::PropertiesPrivate { public: - TagPrivate() {} - - String title; - String comment; - String trackerName; + PropertiesPrivate() : + channels(0), + instrumentCount(0), + patternCount(0) + { + } + + int channels; + uint instrumentCount; + uint patternCount; }; -XM::Tag::Tag() : TagLib::Tag() +Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : + AudioProperties(propertiesStyle), + d(new PropertiesPrivate) { - d = new TagPrivate; } -XM::Tag::~Tag() +Mod::Properties::~Properties() { delete d; } -String XM::Tag::title() const -{ - return d->title; -} - -String XM::Tag::artist() const -{ - return String::null; -} - -String XM::Tag::album() const -{ - return String::null; -} - -String XM::Tag::comment() const -{ - return d->comment; -} - -String XM::Tag::genre() const -{ - return String::null; -} - -uint XM::Tag::year() const +int Mod::Properties::length() const { return 0; } -uint XM::Tag::track() const +int Mod::Properties::bitrate() const { return 0; } -String XM::Tag::trackerName() const +int Mod::Properties::sampleRate() const { - return d->trackerName; + return 0; } -void XM::Tag::setTitle(const String &title) +int Mod::Properties::channels() const { - d->title = title; + return d->channels; } -void XM::Tag::setArtist(const String &) +uint Mod::Properties::instrumentCount() const { + return d->instrumentCount; } -void XM::Tag::setAlbum(const String &) +uint Mod::Properties::patternCount() const { + return d->patternCount; } -void XM::Tag::setComment(const String &comment) +void Mod::Properties::setChannels(int channels) { - d->comment = comment; + d->channels = channels; } -void XM::Tag::setGenre(const String &) +void Mod::Properties::setInstrumentCount(uint instrumentCount) { + d->instrumentCount = instrumentCount; } -void XM::Tag::setYear(uint) +void Mod::Properties::setPatternCount(uint patternCount) { -} - -void XM::Tag::setTrack(uint) -{ -} - -void XM::Tag::setTrackerName(const String &trackerName) -{ - d->trackerName = trackerName; + d->patternCount = patternCount; } diff --git a/taglib/xm/xmtag.h b/taglib/mod/modproperties.h similarity index 61% rename from taglib/xm/xmtag.h rename to taglib/mod/modproperties.h index 3d0cb21f..83055573 100644 --- a/taglib/xm/xmtag.h +++ b/taglib/mod/modproperties.h @@ -19,42 +19,40 @@ * MA 02110-1301 USA * ***************************************************************************/ -#ifndef TAGLIB_XMTAG_H -#define TAGLIB_XMTAG_H +#ifndef TAGLIB_MODPROPERTIES_H +#define TAGLIB_MODPROPERTIES_H -#include "modtag.h" +#include "taglib.h" +#include "audioproperties.h" namespace TagLib { - namespace XM { - class Tag : public TagLib::Tag { - public: - Tag(); - virtual ~Tag(); + namespace Mod { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int bitrate() const; + int sampleRate() const; + int channels() const; - String title() const; - String artist() const; - String album() const; - String comment() const; - String genre() const; - uint year() const; - uint track() const; - String trackerName() const; + uint instrumentCount() const; + uint patternCount() const; - void setTitle (const String &title); - void setArtist (const String &artist); - void setAlbum (const String &album); - void setComment(const String &comment); - void setGenre (const String &genre); - void setYear (uint year); - void setTrack(uint track); - void setTrackerName(const String &trackerName); + protected: + void setChannels(int channels); - private: - Tag(const Tag &); - Tag &operator=(const Tag &); + void setInstrumentCount(uint sampleCount); + void setPatternCount(uint patternCount); - class TagPrivate; - TagPrivate *d; + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; }; } } diff --git a/taglib/mod/modtag.cpp b/taglib/mod/modtag.cpp index 29344b8f..a1b11388 100644 --- a/taglib/mod/modtag.cpp +++ b/taglib/mod/modtag.cpp @@ -31,6 +31,7 @@ public: String title; String comment; + String trackerName; }; Mod::Tag::Tag() : TagLib::Tag() @@ -78,6 +79,11 @@ uint Mod::Tag::track() const return 0; } +String Mod::Tag::trackerName() const +{ + return d->trackerName; +} + void Mod::Tag::setTitle(const String &title) { d->title = title; @@ -107,3 +113,8 @@ void Mod::Tag::setYear(uint) void Mod::Tag::setTrack(uint) { } + +void Mod::Tag::setTrackerName(const String &trackerName) +{ + d->trackerName = trackerName; +} diff --git a/taglib/mod/modtag.h b/taglib/mod/modtag.h index 8d6482cb..3a21d67c 100644 --- a/taglib/mod/modtag.h +++ b/taglib/mod/modtag.h @@ -38,6 +38,7 @@ namespace TagLib { String genre() const; uint year() const; uint track() const; + String trackerName() const; void setTitle (const String &title); void setArtist (const String &artist); @@ -46,6 +47,7 @@ namespace TagLib { void setGenre (const String &genre); void setYear (uint year); void setTrack(uint track); + void setTrackerName(const String &trackerName); private: Tag(const Tag &); diff --git a/taglib/s3m/s3mfile.cpp b/taglib/s3m/s3mfile.cpp index 614688e3..c0d4b241 100644 --- a/taglib/s3m/s3mfile.cpp +++ b/taglib/s3m/s3mfile.cpp @@ -106,7 +106,7 @@ void S3M::File::read(bool) READ_ASSERT(readBlock(4) == "SCRM"); READ_BYTE_AS(baseVolume); - d->properties.setBaseVolume(baseVolume << 1); + d->properties.setBaseVolume((int)baseVolume << 1); READ_BYTE(d->properties.setTempo); READ_BYTE(d->properties.setBpmSpeed); @@ -133,10 +133,10 @@ void S3M::File::read(bool) StringList comment; for(ushort i = 0; i < sampleCount; ++ i) { - seek(96 + length + (i << 1)); + seek(96L + length + ((long)i << 1)); READ_U16L_AS(instrumentOffset); - seek(instrumentOffset << 4); + seek((long)instrumentOffset << 4); READ_BYTE_AS(sampleType); READ_STRING_AS(dosFileName, 13); @@ -158,4 +158,5 @@ void S3M::File::read(bool) } d->tag.setComment(comment.toString("\n")); + d->tag.setTrackerName("ScreamTracker III"); } diff --git a/taglib/s3m/s3mfile.h b/taglib/s3m/s3mfile.h index 28433e13..6eb938a3 100644 --- a/taglib/s3m/s3mfile.h +++ b/taglib/s3m/s3mfile.h @@ -22,8 +22,6 @@ #ifndef TAGLIB_S3MFILE_H #define TAGLIB_S3MFILE_H -#include - #include "tfile.h" #include "audioproperties.h" #include "taglib_export.h" diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp index f567c25d..ed5e07ec 100644 --- a/taglib/xm/xmfile.cpp +++ b/taglib/xm/xmfile.cpp @@ -36,7 +36,7 @@ public: { } - XM::Tag tag; + Mod::Tag tag; XM::Properties properties; }; @@ -61,7 +61,7 @@ XM::File::~File() delete d; } -XM::Tag *XM::File::tag() const +Mod::Tag *XM::File::tag() const { return &d->tag; } @@ -131,27 +131,15 @@ void XM::File::read(bool) if(instrumentSize > 4) { - if(!readString(instrumentName, std::min(22UL, instrumentSize-4))) - { - setValid(false); - return; - } + READ_ASSERT(readString(instrumentName, std::min(22UL, instrumentSize-4))); if(instrumentSize >= (4+22+1)) { - if(!readByte(instrumentType)) - { - setValid(false); - return; - } + READ_ASSERT(readByte(instrumentType)); if(instrumentSize >= (4+22+1+2)) { - if(!readU16L(sampleCount)) - { - setValid(false); - return; - } + READ_ASSERT(readU16L(sampleCount)); } } } diff --git a/taglib/xm/xmfile.h b/taglib/xm/xmfile.h index 7d0b919d..a4ae7244 100644 --- a/taglib/xm/xmfile.h +++ b/taglib/xm/xmfile.h @@ -22,13 +22,11 @@ #ifndef TAGLIB_XMFILE_H #define TAGLIB_XMFILE_H -#include - #include "tfile.h" #include "audioproperties.h" #include "taglib_export.h" #include "modfilebase.h" -#include "xmtag.h" +#include "modtag.h" #include "xmproperties.h" namespace TagLib { @@ -60,7 +58,7 @@ namespace TagLib { */ virtual ~File(); - XM::Tag *tag() const; + Mod::Tag *tag() const; /*! * Returns the XM::Properties for this file. If no audio properties