diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp index e44f771a..f829076d 100644 --- a/taglib/flac/flacfile.cpp +++ b/taglib/flac/flacfile.cpp @@ -119,6 +119,17 @@ FLAC::File::File(const char *file, ID3v2::FrameFactory *frameFactory, read(readProperties, propertiesStyle); } +#ifdef TAGLIB_UNICODE_FILENAMES +FLAC::File::File(const wchar_t *file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate; + d->ID3v2FrameFactory = frameFactory; + read(readProperties, propertiesStyle); +} +#endif + FLAC::File::~File() { delete d; diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h index 5cc70843..9c016488 100644 --- a/taglib/flac/flacfile.h +++ b/taglib/flac/flacfile.h @@ -88,6 +88,20 @@ namespace TagLib { bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs a FLAC 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. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + */ + File(const wchar_t *file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); +#endif + /*! * Destroys this instance of the File. */ diff --git a/taglib/mpc/mpcfile.cpp b/taglib/mpc/mpcfile.cpp index a5a8a005..352a3152 100644 --- a/taglib/mpc/mpcfile.cpp +++ b/taglib/mpc/mpcfile.cpp @@ -100,6 +100,15 @@ MPC::File::File(const char *file, bool readProperties, read(readProperties, propertiesStyle); } +#ifdef TAGLIB_UNICODE_FILENAMES +MPC::File::File(const wchar_t *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} +#endif + MPC::File::~File() { delete d; diff --git a/taglib/mpc/mpcfile.h b/taglib/mpc/mpcfile.h index d4c337dd..4f4cce58 100644 --- a/taglib/mpc/mpcfile.h +++ b/taglib/mpc/mpcfile.h @@ -88,6 +88,16 @@ namespace TagLib { File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs an MPC 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(const wchar_t *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); +#endif + /*! * Destroys this instance of the File. */ diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp index d9035f1e..21538baa 100644 --- a/taglib/mpeg/mpegfile.cpp +++ b/taglib/mpeg/mpegfile.cpp @@ -246,6 +246,19 @@ MPEG::File::File(const char *file, ID3v2::FrameFactory *frameFactory, } } +#ifdef TAGLIB_UNICODE_FILENAMES +MPEG::File::File(const wchar_t *file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate(frameFactory); + if(isOpen()) { + d->tag = new MPEGTag(this); + read(readProperties, propertiesStyle); + } +} +#endif + MPEG::File::~File() { delete d; diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h index 8df12fb0..a6f9cbd1 100644 --- a/taglib/mpeg/mpegfile.h +++ b/taglib/mpeg/mpegfile.h @@ -91,6 +91,18 @@ namespace TagLib { bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs an MPEG 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. The frames will be created using + * \a frameFactory. + */ + File(const wchar_t *file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); +#endif + /*! * Destroys this instance of the File. */ diff --git a/taglib/ogg/flac/oggflacfile.cpp b/taglib/ogg/flac/oggflacfile.cpp index b69fb64d..0ab961fd 100644 --- a/taglib/ogg/flac/oggflacfile.cpp +++ b/taglib/ogg/flac/oggflacfile.cpp @@ -75,6 +75,15 @@ Ogg::FLAC::File::File(const char *file, bool readProperties, read(readProperties, propertiesStyle); } +#ifdef TAGLIB_UNICODE_FILENAMES +Ogg::FLAC::File::File(const wchar_t *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} +#endif + Ogg::FLAC::File::~File() { delete d; diff --git a/taglib/ogg/flac/oggflacfile.h b/taglib/ogg/flac/oggflacfile.h index 14ac2c12..5c9d7e97 100644 --- a/taglib/ogg/flac/oggflacfile.h +++ b/taglib/ogg/flac/oggflacfile.h @@ -71,6 +71,16 @@ namespace TagLib { File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs an Ogg/FLAC 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(const wchar_t *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); +#endif + /*! * Destroys this instance of the File. */ diff --git a/taglib/ogg/oggfile.cpp b/taglib/ogg/oggfile.cpp index a6efb240..bc33ab01 100644 --- a/taglib/ogg/oggfile.cpp +++ b/taglib/ogg/oggfile.cpp @@ -213,6 +213,13 @@ Ogg::File::File(const char *file) : TagLib::File(file) d = new FilePrivate; } +#ifdef TAGLIB_UNICODE_FILENAMES +Ogg::File::File(const wchar_t *file) : TagLib::File(file) +{ + d = new FilePrivate; +} +#endif + //////////////////////////////////////////////////////////////////////////////// // private members //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/ogg/oggfile.h b/taglib/ogg/oggfile.h index 6825bddf..76b5c9c5 100644 --- a/taglib/ogg/oggfile.h +++ b/taglib/ogg/oggfile.h @@ -92,6 +92,19 @@ namespace TagLib { */ File(const char *file); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs an Ogg 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. + * + * \note This constructor is protected since Ogg::File shouldn't be + * instantiated directly but rather should be used through the codec + * specific subclasses. + */ + File(const wchar_t *file); +#endif + private: File(const File &); File &operator=(const File &); diff --git a/taglib/ogg/vorbis/vorbisfile.cpp b/taglib/ogg/vorbis/vorbisfile.cpp index 033b8cdf..0e9cc9e1 100644 --- a/taglib/ogg/vorbis/vorbisfile.cpp +++ b/taglib/ogg/vorbis/vorbisfile.cpp @@ -68,6 +68,15 @@ Vorbis::File::File(const char *file, bool readProperties, read(readProperties, propertiesStyle); } +#ifdef TAGLIB_UNICODE_FILENAMES +Vorbis::File::File(const wchar_t *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} +#endif + Vorbis::File::~File() { delete d; diff --git a/taglib/ogg/vorbis/vorbisfile.h b/taglib/ogg/vorbis/vorbisfile.h index 16d630ef..ddff68e2 100644 --- a/taglib/ogg/vorbis/vorbisfile.h +++ b/taglib/ogg/vorbis/vorbisfile.h @@ -70,6 +70,16 @@ namespace TagLib { File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Contructs a Vorbis 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(const wchar_t *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); +#endif + /*! * Destroys this instance of the File. */ diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index 41476cf0..46092c6e 100644 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -30,6 +30,10 @@ #define TAGLIB_MINOR_VERSION 4 #define TAGLIB_PATCH_VERSION 0 +#ifdef _WIN32 +#define TAGLIB_UNICODE_FILENAMES 1 +#endif + #include //! A namespace for all TagLib related classes and functions diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp index 90c296b7..0f875ec0 100644 --- a/taglib/toolkit/tfile.cpp +++ b/taglib/toolkit/tfile.cpp @@ -45,6 +45,15 @@ # define W_OK 2 #endif +#ifdef TAGLIB_UNICODE_FILENAMES +# ifdef _WIN32 +# include +# include +# else +# error "Unicode filenames are not supported on this platform." +# endif +#endif + using namespace TagLib; class File::FilePrivate @@ -53,6 +62,9 @@ public: FilePrivate(const char *fileName) : file(0), name(fileName), +#ifdef TAGLIB_UNICODE_FILENAMES + wname(0), +#endif readOnly(true), valid(true), size(0) @@ -61,10 +73,16 @@ public: ~FilePrivate() { free((void *)name); +#ifdef TAGLIB_UNICODE_FILENAMES + free((void *)wname); +#endif } FILE *file; const char *name; +#ifdef TAGLIB_UNICODE_FILENAMES + const wchar_t *wname; +#endif bool readOnly; bool valid; ulong size; @@ -87,12 +105,45 @@ File::File(const char *file) if(d->file) d->readOnly = false; else - d->file = fopen(file,"rb"); + d->file = fopen(file, "rb"); if(!d->file) debug("Could not open file " + String(file)); } +#ifdef TAGLIB_UNICODE_FILENAMES +File::File(const wchar_t *file) +{ +#ifdef _WIN32 + d = new FilePrivate(0); + d->wname = _wcsdup(file); + + if(GetVersion() < 0x80000000) { + d->file = _wfopen(file, L"rb+"); + if(d->file) + d->readOnly = false; + else + d->file = _wfopen(file, L"rb"); + } + else { + size_t size = wcslen(file) + 1; + d->name = (char *)malloc(size); + if(WideCharToMultiByte(CP_ACP, 0, file, -1, (CHAR*)d->name, size, + NULL, NULL) > 0) { + d->file = fopen(d->name, "rb+"); + if(d->file) + d->readOnly = false; + else + d->file = fopen(d->name, "rb"); + } + } + + if(!d->file) + debug("Could not open file " + String(file, String::UTF16LE)); +#endif +} +#endif + File::~File() { if(d->file) @@ -105,6 +156,13 @@ const char *File::name() const return d->name; } +#ifdef TAGLIB_UNICODE_FILENAMES +const wchar_t *File::unicodeName() const +{ + return d->wname; +} +#endif + ByteVector File::readBlock(ulong length) { if(!d->file) { diff --git a/taglib/toolkit/tfile.h b/taglib/toolkit/tfile.h index 1dad4700..59a82e94 100644 --- a/taglib/toolkit/tfile.h +++ b/taglib/toolkit/tfile.h @@ -69,6 +69,13 @@ namespace TagLib { */ const char *name() const; +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Returns the file name in UTF-16. + */ + const wchar_t *unicodeName() const; +#endif + /*! * Returns a pointer to this file's tag. This should be reimplemented in * the concrete subclasses. @@ -225,6 +232,17 @@ namespace TagLib { */ File(const char *file); +#ifdef TAGLIB_UNICODE_FILENAMES + /*! + * Construct a File object and opens the \a file. \a file should be a + * be a null-terminated Unicode string in UTF-16. + * + * \note Constructor is protected since this class should only be + * instantiated through subclasses. + */ + File(const wchar_t *file); +#endif + /*! * Marks the file as valid or invalid. *