diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index c060c74b..d1fbe85c 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -59,7 +59,7 @@ FileRef::FileRef() d = new FileRefPrivate(0); } -FileRef::FileRef(const char *fileName, bool readAudioProperties, +FileRef::FileRef(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle)); @@ -150,7 +150,7 @@ bool FileRef::operator!=(const FileRef &ref) const return ref.d->file != d->file; } -File *FileRef::create(const char *fileName, bool readAudioProperties, +File *FileRef::create(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) // static { @@ -164,7 +164,15 @@ File *FileRef::create(const char *fileName, bool readAudioProperties, // Ok, this is really dumb for now, but it works for testing. - String s = fileName; + String s; +#ifdef _WIN32 + if((const wchar_t *)fileName) + s = (const wchar_t *)fileName; + else + s = (const char *)fileName; +#else + s = fileName; +#endif // If this list is updated, the method defaultFileExtensions() should also be // updated. However at some point that list should be created at the same time diff --git a/taglib/fileref.h b/taglib/fileref.h index 05ad24e4..2fc094b5 100644 --- a/taglib/fileref.h +++ b/taglib/fileref.h @@ -26,6 +26,7 @@ #ifndef TAGLIB_FILEREF_H #define TAGLIB_FILEREF_H +#include #include #include "taglib_export.h" @@ -33,8 +34,6 @@ namespace TagLib { - class String; - class File; class Tag; //! This class provides a simple abstraction for creating and handling files @@ -105,7 +104,7 @@ namespace TagLib { * deleted. Deletion will happen automatically when the FileRef passes * out of scope. */ - virtual File *createFile(const char *fileName, + virtual File *createFile(FileName fileName, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average) const = 0; @@ -125,7 +124,7 @@ namespace TagLib { * Also see the note in the class documentation about why you may not want to * use this method in your application. */ - explicit FileRef(const char *fileName, + explicit FileRef(FileName fileName, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); @@ -248,7 +247,7 @@ namespace TagLib { * * \deprecated */ - static File *create(const char *fileName, + static File *create(FileName fileName, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp index e44f771a..035102f7 100644 --- a/taglib/flac/flacfile.cpp +++ b/taglib/flac/flacfile.cpp @@ -102,7 +102,7 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -FLAC::File::File(const char *file, bool readProperties, +FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { @@ -110,7 +110,7 @@ FLAC::File::File(const char *file, bool readProperties, read(readProperties, propertiesStyle); } -FLAC::File::File(const char *file, ID3v2::FrameFactory *frameFactory, +FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h index 5cc70843..63c3c0dd 100644 --- a/taglib/flac/flacfile.h +++ b/taglib/flac/flacfile.h @@ -72,7 +72,7 @@ namespace TagLib { * \deprecated This constructor will be dropped in favor of the one below * in a future version. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! @@ -84,7 +84,7 @@ namespace TagLib { * \a frameFactory. */ // BIC: merge with the above constructor - File(const char *file, ID3v2::FrameFactory *frameFactory, + File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); diff --git a/taglib/mpc/mpcfile.cpp b/taglib/mpc/mpcfile.cpp index a5a8a005..72bd27da 100644 --- a/taglib/mpc/mpcfile.cpp +++ b/taglib/mpc/mpcfile.cpp @@ -93,7 +93,7 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -MPC::File::File(const char *file, bool readProperties, +MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { d = new FilePrivate; diff --git a/taglib/mpc/mpcfile.h b/taglib/mpc/mpcfile.h index d4c337dd..cf1c7083 100644 --- a/taglib/mpc/mpcfile.h +++ b/taglib/mpc/mpcfile.h @@ -85,7 +85,7 @@ namespace TagLib { * file's audio properties will also be read using \a propertiesStyle. If * false, \a propertiesStyle is ignored. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index 537a8cc6..e79aa8e9 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -71,7 +71,7 @@ TagLib::uint Frame::headerSize(uint version) ByteVector Frame::textDelimiter(String::Type t) { ByteVector d = char(0); - if(t == String::UTF16 || t == String::UTF16BE) + if(t == String::UTF16 || t == String::UTF16BE || t == String::UTF16LE) d.append(char(0)); return d; } diff --git a/taglib/mpeg/id3v2/id3v2synchdata.h b/taglib/mpeg/id3v2/id3v2synchdata.h index ad49b099..d42d265a 100644 --- a/taglib/mpeg/id3v2/id3v2synchdata.h +++ b/taglib/mpeg/id3v2/id3v2synchdata.h @@ -51,17 +51,17 @@ namespace TagLib { * 6.2). The default \a length of * 4 is used if another value is not specified. */ - uint toUInt(const ByteVector &data); + TAGLIB_EXPORT uint toUInt(const ByteVector &data); /*! * Returns a 4 byte (32 bit) synchsafe integer based on \a value. */ - ByteVector fromUInt(uint value); + TAGLIB_EXPORT ByteVector fromUInt(uint value); /*! * Deunsynchronize the data (in-place). */ - void decode(ByteVector &data); + TAGLIB_EXPORT void decode(ByteVector &data); } } diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp index d9035f1e..be1ed39e 100644 --- a/taglib/mpeg/mpegfile.cpp +++ b/taglib/mpeg/mpegfile.cpp @@ -225,7 +225,7 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -MPEG::File::File(const char *file, bool readProperties, +MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { d = new FilePrivate; @@ -235,7 +235,7 @@ MPEG::File::File(const char *file, bool readProperties, } } -MPEG::File::File(const char *file, ID3v2::FrameFactory *frameFactory, +MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h index 8df12fb0..fc319017 100644 --- a/taglib/mpeg/mpegfile.h +++ b/taglib/mpeg/mpegfile.h @@ -77,7 +77,7 @@ namespace TagLib { * \deprecated This constructor will be dropped in favor of the one below * in a future version. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! @@ -87,7 +87,7 @@ namespace TagLib { * \a frameFactory. */ // BIC: merge with the above constructor - File(const char *file, ID3v2::FrameFactory *frameFactory, + File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); diff --git a/taglib/ogg/flac/oggflacfile.cpp b/taglib/ogg/flac/oggflacfile.cpp index b69fb64d..3070f3ab 100644 --- a/taglib/ogg/flac/oggflacfile.cpp +++ b/taglib/ogg/flac/oggflacfile.cpp @@ -68,7 +68,7 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -Ogg::FLAC::File::File(const char *file, bool readProperties, +Ogg::FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : Ogg::File(file) { d = new FilePrivate; diff --git a/taglib/ogg/flac/oggflacfile.h b/taglib/ogg/flac/oggflacfile.h index 14ac2c12..ab1e79de 100644 --- a/taglib/ogg/flac/oggflacfile.h +++ b/taglib/ogg/flac/oggflacfile.h @@ -68,7 +68,7 @@ namespace TagLib { * the file's audio properties will also be read using \a propertiesStyle. * If false, \a propertiesStyle is ignored. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! diff --git a/taglib/ogg/oggfile.cpp b/taglib/ogg/oggfile.cpp index a6efb240..e9e6d4fc 100644 --- a/taglib/ogg/oggfile.cpp +++ b/taglib/ogg/oggfile.cpp @@ -208,7 +208,7 @@ bool Ogg::File::save() // protected members //////////////////////////////////////////////////////////////////////////////// -Ogg::File::File(const char *file) : TagLib::File(file) +Ogg::File::File(FileName file) : TagLib::File(file) { d = new FilePrivate; } diff --git a/taglib/ogg/oggfile.h b/taglib/ogg/oggfile.h index 6825bddf..1882cdfa 100644 --- a/taglib/ogg/oggfile.h +++ b/taglib/ogg/oggfile.h @@ -90,7 +90,7 @@ namespace TagLib { * instantiated directly but rather should be used through the codec * specific subclasses. */ - File(const char *file); + File(FileName file); private: File(const File &); diff --git a/taglib/ogg/vorbis/vorbisfile.cpp b/taglib/ogg/vorbis/vorbisfile.cpp index 033b8cdf..6d48ce61 100644 --- a/taglib/ogg/vorbis/vorbisfile.cpp +++ b/taglib/ogg/vorbis/vorbisfile.cpp @@ -61,7 +61,7 @@ namespace TagLib { // public members //////////////////////////////////////////////////////////////////////////////// -Vorbis::File::File(const char *file, bool readProperties, +Vorbis::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : Ogg::File(file) { d = new FilePrivate; diff --git a/taglib/ogg/vorbis/vorbisfile.h b/taglib/ogg/vorbis/vorbisfile.h index 16d630ef..f75df5ea 100644 --- a/taglib/ogg/vorbis/vorbisfile.h +++ b/taglib/ogg/vorbis/vorbisfile.h @@ -67,7 +67,7 @@ namespace TagLib { * file's audio properties will also be read using \a propertiesStyle. If * false, \a propertiesStyle is ignored. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp index 90c296b7..cf33873f 100644 --- a/taglib/toolkit/tfile.cpp +++ b/taglib/toolkit/tfile.cpp @@ -31,6 +31,8 @@ #include #include #ifdef _WIN32 +# include +# include # include # define ftruncate _chsize #else @@ -50,7 +52,7 @@ using namespace TagLib; class File::FilePrivate { public: - FilePrivate(const char *fileName) : + FilePrivate(FileName fileName) : file(0), name(fileName), readOnly(true), @@ -60,37 +62,96 @@ public: ~FilePrivate() { +#ifdef _WIN32 + free((void *)((const char *)name)); + free((void *)((const wchar_t *)name)); +#else free((void *)name); +#endif } + void openFile(const char *file, bool printError = true); +#ifdef _WIN32 + void openFile(const wchar_t *file); +#endif + FILE *file; - const char *name; + FileName name; bool readOnly; bool valid; ulong size; static const uint bufferSize = 1024; }; +void File::FilePrivate::openFile(const char *name, bool printError) +{ + // First try with read/write mode, if that fails, fall back to read only. + // We can't use ::access() since that works in odd ways on some file systems. + + file = fopen(name, "rb+"); + + if(file) + readOnly = false; + else + file = fopen(name, "rb"); + + if(!file && printError) + debug("Could not open file " + String(name)); +} + +#ifdef _WIN32 + +void File::FilePrivate::openFile(const wchar_t *name) +{ + // Windows NT/2000/XP/Vista + + if(GetVersion() < 0x80000000) { + file = _wfopen(name, L"rb+"); + if(file) + readOnly = false; + else + file = _wfopen(name, L"rb"); + } + + // Windows 9x/ME + + else { + size_t length = wcslen(name) + 1; + char *tmpname = (char *)malloc(length); + if(tmpname) { + if(WideCharToMultiByte(CP_ACP, 0, name, -1, tmpname, length, NULL, NULL)) + openFile(tmpname, false); + free(tmpname); + } + } + + if(!file) + debug("Could not open file " + String(name)); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -File::File(const char *file) +File::File(FileName file) { +#ifdef _WIN32 + const char *name = (const char *)file; + const wchar_t *wname = (const wchar_t *)file; + if(wname) { + d = new FilePrivate(::_wcsdup(wname)); + d->openFile(wname); + } + else { + d = new FilePrivate(::strdup(name)); + d->openFile(name); + } +#else d = new FilePrivate(::strdup(file)); - - // First try with read/write mode, if that fails, fall back to read only. - // We can't use ::access() since that works in odd ways on some file systems. - - d->file = fopen(file, "rb+"); - - if(d->file) - d->readOnly = false; - else - d->file = fopen(file,"rb"); - - if(!d->file) - debug("Could not open file " + String(file)); + d->openFile(d->name); +#endif } File::~File() @@ -100,7 +161,7 @@ File::~File() delete d; } -const char *File::name() const +FileName File::name() const { return d->name; } diff --git a/taglib/toolkit/tfile.h b/taglib/toolkit/tfile.h index 1dad4700..4fbdd8fb 100644 --- a/taglib/toolkit/tfile.h +++ b/taglib/toolkit/tfile.h @@ -36,6 +36,23 @@ namespace TagLib { class Tag; class AudioProperties; + +#ifdef _WIN32 + class TAGLIB_EXPORT FileName + { + public: + FileName(const wchar_t *name) : name(0), wname(name) {} + FileName(const char *name) : name(name), wname(0) {} + operator const wchar_t *() { return wname; } + operator const char *() { return name; } + protected: + const char *name; + const wchar_t *wname; + }; +#else + typedef const char *FileName; +#endif + //! A file class with some useful methods for tag manipulation /*! @@ -67,7 +84,7 @@ namespace TagLib { /*! * Returns the file name in the local file system encoding. */ - const char *name() const; + FileName name() const; /*! * Returns a pointer to this file's tag. This should be reimplemented in @@ -223,7 +240,7 @@ namespace TagLib { * \note Constructor is protected since this class should only be * instantiated through subclasses. */ - File(const char *file); + File(FileName file); /*! * Marks the file as valid or invalid. diff --git a/taglib/wavpack/wavpackfile.cpp b/taglib/wavpack/wavpackfile.cpp index 9667bbe9..5bd1a472 100644 --- a/taglib/wavpack/wavpackfile.cpp +++ b/taglib/wavpack/wavpackfile.cpp @@ -86,7 +86,7 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -WavPack::File::File(const char *file, bool readProperties, +WavPack::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : TagLib::File(file) { d = new FilePrivate; diff --git a/taglib/wavpack/wavpackfile.h b/taglib/wavpack/wavpackfile.h index 8574a176..b7572601 100644 --- a/taglib/wavpack/wavpackfile.h +++ b/taglib/wavpack/wavpackfile.h @@ -84,7 +84,7 @@ namespace TagLib { * file's audio properties will also be read using \a propertiesStyle. If * false, \a propertiesStyle is ignored. */ - File(const char *file, bool readProperties = true, + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*!