1 ///WARING! this MAY BE 64-bit unsafe!
8 ////////////////////////////////////////////////////////////////////////////////
13 class TagLibException
: Exception
{
14 this (string msg
, string file
=__FILE__
, size_t line
=__LINE__
, Throwable next
=null) @safe @pure @nothrow {
15 super(msg
, file
, line
, next
);
22 Autodetect
=-1, // k8 extension, do not use in C API!
36 this (string fname
, FileType type
=FileType
.Autodetect
) @trusted {
37 loadInfo(fname
, type
);
44 void clear () @trusted {
47 taglib_file_free(mFL
);
50 mFName
= mArtist
= mAlbum
= mTitle
= mComment
= mGenre
= null;
55 void save () @trusted {
56 if (!mInited
) throw new TagLibException("can't save tags object to empty file");
57 if (!taglib_file_save(mFL
)) throw new TagLibException("can't save tags object to file '"~mFName
~"'");
60 @property bool valid () const @trusted @nothrow { return mInited
; }
62 @property string
filename () const @trusted @nothrow { return (mInited ? mFName
: null); }
64 mixin(strPropMixin("artist"));
65 mixin(strPropMixin("album"));
66 mixin(strPropMixin("title"));
67 mixin(strPropMixin("genre"));
68 mixin(strPropMixin("comment"));
70 @property uint year () const @trusted @nothrow { return (mInited ? mYear
: 0); }
71 @property void year (uint v
) @trusted {
72 if (!mInited
) throw new TagLibException("can't set YEAR tag for empty file");
75 if (v
< 50) v
+= 2000;
76 else if (v
< 100) v
+= 1900;
77 else if (v
< 1930) v
= 0;
78 if (v
< 1930 || v
> 2099) throw new TagLibException("invalid YEAR tag value: "~to
!string(ov
));
81 taglib_tag_set_year(mTags
, v
);
84 @property uint track () const @trusted @nothrow { return (mInited ? mTrack
: 0); }
85 @property void track (uint v
) @trusted {
86 if (!mInited
) throw new TagLibException("can't set TRACK tag for empty file");
87 if (v
> 999) throw new TagLibException("invalid TRACK tag value: "~to
!string(v
));
89 taglib_tag_set_track(mTags
, v
);
92 mixin(uintPropMixin("length")); // file length in seconds
93 mixin(uintPropMixin("channels")); // number of channels in file
94 mixin(uintPropMixin("bitrate")); // file bitrate in kb/s
95 mixin(uintPropMixin("samplerate")); // file samplerate in Hz
98 static string
uintPropMixin (string propName
) @pure @safe @nothrow {
100 `@property uint `~propName
~` () @trusted {`~
101 `if (!mInited) return 0;`~
102 `auto tp = taglib_file_audioproperties(mFL);`~
103 `if (!tp) throw new TagLibException("can't get audio properties for file '"~mFName~"'");`~
104 `auto r = taglib_audioproperties_`~propName
~`(tp);`~
105 `return (r < 0 ? 0 : r);`~
109 static string
strPropMixin (string propName
) @pure @safe {
112 `@property void `~propName
~` (string v) @trusted {`~
113 `if (!mInited) throw new TagLibException("can't set `~toUpper(propName
)~` tag for empty file");`~
114 `string s = trimStr(v);`~
115 `taglib_tag_set_`~propName
~`(mTags, s.toStringz);`~
116 `m`~capitalize(propName
)~` = s.idup;`~
118 `@property string `~propName
~` () const @trusted @nothrow { return (mInited ? m`~capitalize(propName
)~` : null); }`;
121 static string
stripL (string
str) @trusted {
123 foreach (i
, dchar c
; str) if (c
!= '_' && !std
.uni
.isWhite(c
)) return str[i
..$];
127 static string
stripR (string
str) @trusted {
128 import std
.uni
, std
.utf
;
129 foreach_reverse (i
, dchar c
; str) if (c
!= '_' && !std
.uni
.isWhite(c
)) return str[0..i
+codeLength
!char(c
)];
133 static string
trimStr (string s
) @trusted {
135 auto res
= appender
!string();
137 foreach (dchar ch
; s
) {
138 if (ch
< ' ') ch
= ' ';
139 // remove duplicate underlines
140 if (pch
== '_' && ch
== '_') { pch
= ch
; continue; }
141 // remove duplicate spaces
142 if (pch
== ' ' && ch
== ' ') { pch
= ch
; continue; }
145 return stripL(stripR(res
.data
));
148 static string
trimStr (char* s
) @trusted {
150 auto res
= trimStr(to
!string(s
));
157 void loadInfo (string fname
, FileType type
=FileType
.Autodetect
) @trusted {
159 if (type
== FileType
.Autodetect
) {
160 mFL
= taglib_file_new(fname
.toStringz
);
162 mFL
= taglib_file_new_type(fname
.toStringz
, cast(TagLibFileType
)type
);
164 scope(failure
) clear();
165 if (!mFL
) throw new TagLibException("can't open file '"~fname
~"'");
166 mTags
= taglib_file_tag(mFL
);
167 if (!mTags
) throw new TagLibException("can't init tags object for file '"~fname
~"'");
168 mArtist
= trimStr(taglib_tag_artist(mTags
));
169 mAlbum
= trimStr(taglib_tag_album(mTags
));
170 mTitle
= trimStr(taglib_tag_title(mTags
));
171 mGenre
= trimStr(taglib_tag_genre(mTags
));
172 mYear
= taglib_tag_year(mTags
);
174 if (mYear
< 50) mYear
+= 2000;
175 else if (mYear
< 100) mYear
+= 1900;
176 else if (mYear
< 1930) mYear
= 0;
178 if (mYear
< 1930 || mYear
> 2099) mYear
= 0;
179 mTrack
= taglib_tag_track(mTags
);
180 if (mTrack
> 999) mTrack
= 0;
200 ////////////////////////////////////////////////////////////////////////////////
201 shared static this () {
202 taglib_set_strings_unicode(true);
203 taglib_set_string_management_enabled(false);
207 ////////////////////////////////////////////////////////////////////////////////
213 struct TagLibFileT
{}
215 struct TagLibAudioPropertiesT
{}
217 alias TagLibFile
= TagLibFileT
*;
218 alias TagLibTag
= TagLibTagT
*;
219 alias TagLibAudioProperties
= TagLibAudioPropertiesT
*;
220 alias TagBool
= uint;
224 * By default all strings coming into or out of TagLib's C API are in UTF8.
225 * However, it may be desirable for TagLib to operate on Latin1 (ISO-8859-1)
226 * strings in which case this should be set to FALSE.
228 void taglib_set_strings_unicode (TagBool unicode
);
231 * TagLib can keep track of strings that are created when outputting tag values
232 * and clear them using taglib_tag_clear_strings(). This is enabled by default.
233 * However if you wish to do more fine grained management of strings, you can do
234 * so by setting \a management to FALSE.
236 void taglib_set_string_management_enabled (TagBool management
);
239 * Explicitly free a string returned from TagLib
241 void taglib_free (void* pointer
);
244 /*******************************************************************************
246 ******************************************************************************/
247 enum TagLibFileType
{
261 * Creates a TagLib file based on \a filename. TagLib will try to guess the file
264 * \returns NULL if the file type cannot be determined or the file cannot
267 TagLibFile
taglib_file_new (const(char)* filename
);
270 * Creates a TagLib file based on \a filename. Rather than attempting to guess
271 * the type, it will use the one specified by \a type.
273 TagLibFile
taglib_file_new_type (const(char)* filename
, TagLibFileType type
);
276 * Frees and closes the file.
278 void taglib_file_free (TagLibFile file
);
281 * Returns true if the file is open and readble and valid information for
282 * the Tag and / or AudioProperties was found.
285 TagBool
taglib_file_is_valid (const(TagLibFile
) file
);
288 * Returns a pointer to the tag associated with this file. This will be freed
289 * automatically when the file is freed.
291 TagLibTag
taglib_file_tag (const(TagLibFile
) file
);
294 * Returns a pointer to the the audio properties associated with this file. This
295 * will be freed automatically when the file is freed.
297 const(TagLibAudioProperties
) taglib_file_audioproperties (const(TagLibFile
) file
);
300 * Saves the \a file to disk.
302 TagBool
taglib_file_save (TagLibFile file
);
305 /******************************************************************************
307 ******************************************************************************/
310 * Returns a string with this tag's title.
312 * \note By default this string should be UTF8 encoded and its memory should be
313 * freed using taglib_tag_free_strings().
315 char *taglib_tag_title (const(TagLibTag
) tag
);
318 * Returns a string with this tag's artist.
320 * \note By default this string should be UTF8 encoded and its memory should be
321 * freed using taglib_tag_free_strings().
323 char *taglib_tag_artist (const(TagLibTag
) tag
);
326 * Returns a string with this tag's album name.
328 * \note By default this string should be UTF8 encoded and its memory should be
329 * freed using taglib_tag_free_strings().
331 char *taglib_tag_album (const(TagLibTag
) tag
);
334 * Returns a string with this tag's comment.
336 * \note By default this string should be UTF8 encoded and its memory should be
337 * freed using taglib_tag_free_strings().
339 char *taglib_tag_comment (const(TagLibTag
) tag
);
342 * Returns a string with this tag's genre.
344 * \note By default this string should be UTF8 encoded and its memory should be
345 * freed using taglib_tag_free_strings().
347 char *taglib_tag_genre (const(TagLibTag
) tag
);
350 * Returns the tag's year or 0 if year is not set.
352 uint taglib_tag_year (const(TagLibTag
) tag
);
355 * Returns the tag's track number or 0 if track number is not set.
357 uint taglib_tag_track (const(TagLibTag
) tag
);
360 * Sets the tag's title.
362 * \note By default this string should be UTF8 encoded.
364 void taglib_tag_set_title (TagLibTag tag
, const(char)* title
);
367 * Sets the tag's artist.
369 * \note By default this string should be UTF8 encoded.
371 void taglib_tag_set_artist (TagLibTag tag
, const(char)* artist
);
374 * Sets the tag's album.
376 * \note By default this string should be UTF8 encoded.
378 void taglib_tag_set_album (TagLibTag tag
, const(char)* album
);
381 * Sets the tag's comment.
383 * \note By default this string should be UTF8 encoded.
385 void taglib_tag_set_comment (TagLibTag tag
, const(char)* comment
);
388 * Sets the tag's genre.
390 * \note By default this string should be UTF8 encoded.
392 void taglib_tag_set_genre (TagLibTag tag
, const(char)* genre
);
395 * Sets the tag's year. 0 indicates that this field should be cleared.
397 void taglib_tag_set_year (TagLibTag tag
, uint year
);
400 * Sets the tag's track number. 0 indicates that this field should be cleared.
402 void taglib_tag_set_track (TagLibTag tag
, uint track
);
405 * Frees all of the strings that have been created by the tag.
407 void taglib_tag_free_strings ();
410 /******************************************************************************
411 * Audio Properties API
412 ******************************************************************************/
415 * Returns the length of the file in seconds.
417 int taglib_audioproperties_length (const(TagLibAudioProperties
) audioProperties
);
420 * Returns the bitrate of the file in kb/s.
422 int taglib_audioproperties_bitrate (const(TagLibAudioProperties
) audioProperties
);
425 * Returns the sample rate of the file in Hz.
427 int taglib_audioproperties_samplerate (const(TagLibAudioProperties
) audioProperties
);
430 * Returns the number of channels in the audio stream.
432 int taglib_audioproperties_channels (const(TagLibAudioProperties
) audioProperties
);
435 /*******************************************************************************
436 * Special convenience ID3v2 functions
437 *******************************************************************************/
438 enum TagLibID3v2Encoding
{
447 * This sets the default encoding for ID3v2 frames that are written to tags.
449 void taglib_id3v2_set_default_text_encoding (TagLibID3v2Encoding encoding
);